//      matrix.c
//      
//      Copyright 2009 Guy Sheffer <guysoft at gmail.com>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.


#include <util/delay.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <string.h>


#define BUFFER_SIZE 7

char matrix[4];
char scan[BUFFER_SIZE],screen[BUFFER_SIZE];
volatile long timer=0;

void transb(char c, char r)
{
	char b=0,d=0;
	r = ~r;
		
	if (r &  0b0000001)
		d |= ~0b1011111;
		
	if (r &  0b0000010)
		d |= ~0b1111110;
		
	if (r &  0b0000100)
		d |= ~0b0111111;
		
	if (r &  0b0001000)
	{
		b |= ~0b1101111;
		d |= ~0b1111011;
	}
	
	if (r &  0b0010000)
		b |= ~0b1111110;
	
	if (r &  0b0100000)
		b |= ~0b0111111;
		
	if (r &  0b1000000)
		b |= ~0b1111101;
		
		
		
	if (c &  0b0010000)
		d |= 0b0000010;
		
	if (c &  0b0001000)
		b |= 0b0000100;
		
	if (c &  0b0000100)
	{
		b |= 0b0001000;	
		d |= 0b0001000;
	}

	if (c &  0b0000010)
		d |= 0b0010000;	

	if (c &  0b0000001)
		b |= 0b0100000;


	matrix[0] = b;
	matrix[1] = d;
}


void print(char a[],long t)
{
	int i=0,j=0;
	long start;
	start = timer;
	while ( (timer - start) * 16.3  < t)
		for (i=0; i<7; i++) 
		{
		  transb(a[i] ,scan[i]);
		  
		  PORTB = matrix[0];
		  PORTD = matrix[1];
		  _delay_ms(1);
		  PORTB = 0;
		  PORTD = 0;
		  _delay_ms(2);
		}
}

void load_char(char a[],char l)
{
	switch (l)
	{
	case 'A':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0011111;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0010001;
		break;
	case 'B':
		a[0] =  0b0011110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0011110;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0011110;
		break;
	case 'C':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010000;
		a[3] =  0b0010000;
		a[4] =  0b0010000;
		a[5] =  0b0010001;
		a[6] =  0b0001110;
		break;
	case 'D':
		a[0] =  0b0011110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0010001;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0011110;
		break;
	case 'E':
		a[0] =  0b0011111;
		a[1] =  0b0010000;
		a[2] =  0b0010000;
		a[3] =  0b0011111;
		a[4] =  0b0010000;
		a[5] =  0b0010000;
		a[6] =  0b0011111;
		break;
	case 'F':
		a[0] =  0b0011111;
		a[1] =  0b0010000;
		a[2] =  0b0010000;
		a[3] =  0b0011111;
		a[4] =  0b0010000;
		a[5] =  0b0010000;
		a[6] =  0b0010000;
		break;
	case 'G':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010000;
		a[3] =  0b0010000;
		a[4] =  0b0010011;
		a[5] =  0b0010001;
		a[6] =  0b0001110;
		break;
	case 'H':
		a[0] =  0b0010001;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0011111;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0010001;
		break;
	case 'I':
		a[0] =  0b0001110;
		a[1] =  0b0000100;
		a[2] =  0b0000100;
		a[3] =  0b0000100;
		a[4] =  0b0000100;
		a[5] =  0b0000100;
		a[6] =  0b0001110;
		break;
	case 'J':
		a[0] =  0b0011111;
		a[1] =  0b0000100;
		a[2] =  0b0000100;
		a[3] =  0b0000100;
		a[4] =  0b0000100;
		a[5] =  0b0010100;
		a[6] =  0b0001000;
		break;
	case 'K':
		a[0] =  0b0010010;
		a[1] =  0b0010100;
		a[2] =  0b0011000;
		a[3] =  0b0011000;
		a[4] =  0b0010100;
		a[5] =  0b0010010;
		a[6] =  0b0010001;
		break;
	case 'L':
		a[0] =  0b0010000;
		a[1] =  0b0010000;
		a[2] =  0b0010000;
		a[3] =  0b0010000;
		a[4] =  0b0010000;
		a[5] =  0b0010000;
		a[6] =  0b0011111;
		break;
	case 'M':
		a[0] =  0b0001110;
		a[1] =  0b0010101;
		a[2] =  0b0010101;
		a[3] =  0b0010101;
		a[4] =  0b0010101;
		a[5] =  0b0010101;
		a[6] =  0b0010101;
		break;
	case 'N':
		a[0] =  0b0010001;
		a[1] =  0b0011001;
		a[2] =  0b0010101;
		a[3] =  0b0010101;
		a[4] =  0b0010101;
		a[5] =  0b0010011;
		a[6] =  0b0010001;
		break;
	case 'O':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0010001;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0001110;
		break;
	case 'P':
		a[0] =  0b0011110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0011110;
		a[4] =  0b0010000;
		a[5] =  0b0010000;
		a[6] =  0b0010000;
		break;
	case 'Q':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0010001;
		a[4] =  0b0010101;
		a[5] =  0b0010011;
		a[6] =  0b0001111;
		break;
	case 'R':
		a[0] =  0b0001110;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0011110;
		a[4] =  0b0010100;
		a[5] =  0b0010010;
		a[6] =  0b0010001;
		break;
	case 'S':
		a[0] =  0b0000110;
		a[1] =  0b0001001;
		a[2] =  0b0001000;
		a[3] =  0b0000100;
		a[4] =  0b0000010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case 'T':
		a[0] =  0b0011111;
		a[1] =  0b0000100;
		a[2] =  0b0000100;
		a[3] =  0b0000100;
		a[4] =  0b0000100;
		a[5] =  0b0000100;
		a[6] =  0b0000100;
		break;
	case 'U':
		a[0] =  0b0010001;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0010001;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0001110;
		break;
	case 'V':
		a[0] =  0b0010001;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0010001;
		a[4] =  0b0010001;
		a[5] =  0b0010001;
		a[6] =  0b0000100;
		break;
	case 'W':
		a[0] =  0b0010101;
		a[1] =  0b0010101;
		a[2] =  0b0010101;
		a[3] =  0b0010101;
		a[4] =  0b0010101;
		a[5] =  0b0010101;
		a[6] =  0b0000100;
		break;
	case 'X':
		a[0] =  0b0010001;
		a[1] =  0b0001010;
		a[2] =  0b0001010;
		a[3] =  0b0000100;
		a[4] =  0b0000100;
		a[5] =  0b0001010;
		a[6] =  0b0010001;
		break;
	case 'Y':
		a[0] =  0b0010001;
		a[1] =  0b0010001;
		a[2] =  0b0010001;
		a[3] =  0b0001010;
		a[4] =  0b0000100;
		a[5] =  0b0001000;
		a[6] =  0b0010000;
		break;
	case 'Z':
		a[0] =  0b0011111;
		a[1] =  0b0000001;
		a[2] =  0b0000010;
		a[3] =  0b0000100;
		a[4] =  0b0001000;
		a[5] =  0b0010000;
		a[6] =  0b0011111;
		break;
	case '1':
		a[0] =  0b0000100;
		a[1] =  0b0001100;
		a[2] =  0b0010100;
		a[3] =  0b0000100;
		a[4] =  0b0000100;
		a[5] =  0b0000100;
		a[6] =  0b0000100;
		break;
	case '2':
		a[0] =  0b0001100;
		a[1] =  0b0010010;
		a[2] =  0b0000010;
		a[3] =  0b0000100;
		a[4] =  0b0001000;
		a[5] =  0b0010000;
		a[6] =  0b0011110;
		break;
	case '3':
		a[0] =  0b0001100;
		a[1] =  0b0010010;
		a[2] =  0b0000010;
		a[3] =  0b0001100;
		a[4] =  0b0000010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case '4':
		a[0] =  0b0000010;
		a[1] =  0b0000110;
		a[2] =  0b0001010;
		a[3] =  0b0011111;
		a[4] =  0b0000010;
		a[5] =  0b0000010;
		a[6] =  0b0000010;
		break;
	case '5':
		a[0] =  0b0011110;
		a[1] =  0b0010000;
		a[2] =  0b0011100;
		a[3] =  0b0000010;
		a[4] =  0b0000010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case '6':
		a[0] =  0b0000100;
		a[1] =  0b0001000;
		a[2] =  0b0010000;
		a[3] =  0b0011100;
		a[4] =  0b0010010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case '7':
		a[0] =  0b0011111;
		a[1] =  0b0000001;
		a[2] =  0b0000010;
		a[3] =  0b0000100;
		a[4] =  0b0001000;
		a[5] =  0b0001000;
		a[6] =  0b0001000;
		break;
	case '8':
		a[0] =  0b0001100;
		a[1] =  0b0010010;
		a[2] =  0b0010010;
		a[3] =  0b0001100;
		a[4] =  0b0010010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case '9':
		a[0] =  0b0001100;
		a[1] =  0b0010010;
		a[2] =  0b0010010;
		a[3] =  0b0001110;
		a[4] =  0b0000010;
		a[5] =  0b0000100;
		a[6] =  0b0001000;
		break;
	case '0':
		a[0] =  0b0001100;
		a[1] =  0b0010010;
		a[2] =  0b0010010;
		a[3] =  0b0010010;
		a[4] =  0b0010010;
		a[5] =  0b0010010;
		a[6] =  0b0001100;
		break;
	case ' ':
		a[0] =  0b0000000;
		a[1] =  0b0000000;
		a[2] =  0b0000000;
		a[3] =  0b0000000;
		a[4] =  0b0000000;
		a[5] =  0b0000000;
		a[6] =  0b0000000;
		break;
	case '-':
		a[0] =  0b0000000;
		a[1] =  0b0000000;
		a[2] =  0b0000000;
		a[3] =  0b0011110;
		a[4] =  0b0000000;
		a[5] =  0b0000000;
		a[6] =  0b0000000;
		break;
	case '+':
		a[0] =  0b0000000;
		a[1] =  0b0001000;
		a[2] =  0b0001000;
		a[3] =  0b0111110;
		a[4] =  0b0001000;
		a[5] =  0b0001000;
		a[6] =  0b0000000;
		break;
	case '=':
		a[0] =  0b0000000;
		a[1] =  0b0000000;
		a[2] =  0b0011110;
		a[3] =  0b0000000;
		a[4] =  0b0011110;
		a[5] =  0b0000000;
		a[6] =  0b0000000;
		break;
	case '.':
		a[0] =  0b0000000;
		a[1] =  0b0000000;
		a[2] =  0b0000000;
		a[3] =  0b0000000;
		a[4] =  0b0000000;
		a[5] =  0b0000110;
		a[6] =  0b0000110;
		break;
	case '!':
		a[0] =  0b0001100;
		a[1] =  0b0001100;
		a[2] =  0b0001100;
		a[3] =  0b0001100;
		a[4] =  0b0000000;
		a[5] =  0b0000000;
		a[6] =  0b0001100;
		break;
	case ':':
		a[0] =  0b0000000;
		a[1] =  0b0001100;
		a[2] =  0b0001100;
		a[3] =  0b0000000;
		a[4] =  0b0001100;
		a[5] =  0b0001100;
		a[6] =  0b0000000;
		break;
	} 
}

ISR(TIMER0_OVF_vect)
{
	timer++;
}

void push_scroll(char b[],char l,long t)
{
	int i,j;
	char newl[BUFFER_SIZE];
	
	load_char(newl,l);
	
	//1 char space
	for (i=0;i<BUFFER_SIZE;i++)
	{
		b[i] = b[i] << 1;
	}
	print(b,t);


	for (j=0;j<5;j++)
	{
		for (i=0;i<BUFFER_SIZE;i++)
		{
			b[i] = b[i] << 1;
			
			b[i] |= (newl[i] & 0b0100000) >> 5 ;
			newl[i] = newl[i] << 1;
		}
		print(b,t);
	}
	load_char(b,l);
	print(b,t);
}

/* turns all to uppercase */
void up_case(char a[])
{
	int i=0;
	while (a[i] != 0)
	{
		if (a[i] >= 97 && a[i] <= 122)
			a[i] = a[i] - 32;
			i++;
	}
	
}

scroll_message(char a[],long scrollspeed)
{
	int i;
	char buffer[BUFFER_SIZE];
	if (a[0] != '\0')
	{
		
		load_char(buffer,' ');
		print(buffer,scrollspeed);
		for (i=0;i<strlen(a);i++)
		{
			push_scroll(buffer,a[i],scrollspeed);
		}
		push_scroll(buffer,' ',scrollspeed);
	}
	
}


int main(int argc, char **argv) {

TCCR0B = 0x05;
TIMSK0 |= (1 << TOIE0);
sei();

int i=0,j=0;
long scrollspeed;
char buffer[BUFFER_SIZE],r=0,c=0;
 /* Disable watchdog if enabled by bootloader/fuses */
 MCUSR &= ~(1 << WDRF);

 wdt_disable();

 /* Disable clock division */
 clock_prescale_set(clock_div_1);


/* Pin connection layout for the SUN MUG50A matrix and the bumble-b
1	B0
2	B1
3	B2
4	B3
5	B4
6	B5
7	B6
8	D0
9	D1
10	D2
11	D3
12	D4
13	D5
14	D6
*/
	//init the scan
  scan[0] =  0b0000001;
  scan[1] =  0b0000010;
  scan[2] =  0b0000100;
  scan[3] =  0b0001000;
  scan[4] =  0b0010000;
  scan[5] =  0b0100000;
  scan[6] =  0b1000000;
  

  DDRB = 0xFF; // all pins on port b outputs
  DDRD = 0xFF;
  
    for (i=0; i<7; i++) 
  {
	for (j=0; j<5; j++) 
	{
	  transb(scan[j],scan[i]);
	  
	  // put the output data on port B
	  //PORTB = PORTB << 1; // advance port D - shift the Hi-Zs/input to the left
	  PORTB = matrix[0];
	  PORTD = matrix[1];
	  _delay_ms(10);
	}
  }
scrollspeed =100;
//load_char(buffer,'G');
//print(buffer,scrollspeed);
char message[10];
strcpy(message,"guysoft");
up_case(message);
while(1)
{	scroll_message(message,scrollspeed);

}



 return 0;
}

