#include <system.h>
#include <eeprom.h>

//Target PIC16F628 configuration word
#pragma DATA _CONFIG, 0x3F18

//Set clock frequency
#pragma CLOCK_FREQ	4000000

unsigned char message[60];
unsigned char data;
unsigned char address;

rom char* A_seq =  {0x7e,0x09,0x09,0x09,0x7e};
rom char* B_seq =  {0x7f,0x49,0x49,0x49,0x3e};
rom char* C_seq =  {0x3e,0x41,0x41,0x41,0x22};
rom char* D_seq =  {0x7f,0x41,0x41,0x41,0x3e};
rom char* E_seq =  {0x7f,0x49,0x49,0x49,0x41};
rom char* F_seq =  {0x7f,0x09,0x09,0x09,0x01};
rom char* G_seq =  {0x3e,0x41,0x41,0x49,0x7a};
rom char* H_seq =  {0x7f,0x08,0x08,0x08,0x7f};
rom char* I_seq =  {0x00,0x41,0x7f,0x41,0x00};
rom char* J_seq =  {0x20,0x40,0x41,0x3f,0x01};
rom char* K_seq =  {0x7f,0x08,0x14,0x22,0x41};
rom char* L_seq =  {0x7f,0x40,0x40,0x40,0x40};
rom char* M_seq =  {0x7f,0x02,0x04,0x02,0x7f};
rom char* N_seq =  {0x7f,0x02,0x04,0x08,0x7f};
rom char* O_seq =  {0x3e,0x41,0x41,0x41,0x3e};
rom char* P_seq =  {0x7f,0x09,0x09,0x09,0x06};
rom char* Q_seq =  {0x3e,0x41,0x51,0x21,0x5e};
rom char* R_seq =  {0x7f,0x09,0x19,0x29,0x46};
rom char* S_seq =  {0x46,0x49,0x49,0x49,0x31};
rom char* T_seq =  {0x01,0x01,0x7f,0x01,0x01};
rom char* U_seq =  {0x3f,0x40,0x40,0x40,0x3f};
rom char* V_seq =  {0x1f,0x20,0x40,0x20,0x1f};
rom char* W_seq =  {0x3f,0x40,0x38,0x40,0x3f};
rom char* X_seq =  {0x63,0x14,0x08,0x14,0x63};
rom char* Y_seq =  {0x03,0x04,0x78,0x04,0x03};
rom char* Z_seq =  {0x61,0x51,0x49,0x45,0x43};

rom char* a_seq = {0x30,0x4a,0x4a,0x4a,0x7c}; //a
rom char* b_seq = {0x7f,0x50,0x48,0x48,0x30}; //b
rom char* c_seq = {0x38,0x44,0x44,0x44,0x20}; //c
rom char* d_seq = {0x38,0x44,0x44,0x48,0x7f}; //d
rom char* e_seq = {0x38,0x54,0x54,0x54,0x18}; //e
rom char* f_seq = {0x08,0x7e,0x09,0x01,0x02}; //f
rom char* g_seq = {0x06,0x49,0x49,0x49,0x3f}; //g
rom char* h_seq = {0x7f,0x08,0x04,0x04,0x78}; //h
rom char* i_seq = {0x00,0x44,0x7d,0x40,0x00}; //i
rom char* j_seq = {0x20,0x40,0x44,0x3d,0x00}; //j
rom char* k_seq = {0x7f,0x10,0x28,0x44,0x00}; //k
rom char* l_seq = {0x00,0x41,0x7f,0x40,0x00}; //l
rom char* m_seq = {0x7c,0x04,0x08,0x04,0x78}; //m
rom char* n_seq = {0x7c,0x08,0x04,0x04,0x78}; //n
rom char* o_seq = {0x38,0x44,0x44,0x44,0x38}; //o
rom char* p_seq = {0x7c,0x14,0x14,0x14,0x08}; //p
rom char* q_seq = {0x08,0x14,0x14,0x18,0x7c}; //q
rom char* r_seq = {0x7c,0x08,0x04,0x04,0x08}; //r
rom char* s_seq = {0x48,0x54,0x54,0x54,0x20}; //s
rom char* t_seq = {0x04,0x3f,0x44,0x40,0x20}; //t
rom char* u_seq = {0x3c,0x40,0x40,0x20,0x7c}; //u
rom char* v_seq = {0x1c,0x20,0x40,0x20,0x1c}; //v
rom char* w_seq = {0x3c,0x40,0x30,0x40,0x3c}; //w
rom char* x_seq = {0x44,0x28,0x10,0x28,0x44}; //x
rom char* y_seq = {0x0c,0x50,0x50,0x50,0x3c}; //y
rom char* z_seq = {0x44,0x64,0x54,0x4c,0x44}; //z

rom char* n0_seq = {0x3e,0x51,0x49,0x45,0x3e};
rom char* n1_seq = {0x00,0x42,0x7f,0x40,0x00};
rom char* n2_seq = {0x42,0x61,0x51,0x49,0x46};
rom char* n3_seq = {0x22,0x41,0x49,0x49,0x36};
rom char* n4_seq = {0x18,0x14,0x12,0x7f,0x10};
rom char* n5_seq = {0x27,0x45,0x45,0x45,0x39};
rom char* n6_seq = {0x3e,0x49,0x49,0x49,0x30};
rom char* n7_seq = {0x01,0x71,0x09,0x05,0x03};
rom char* n8_seq = {0x36,0x49,0x49,0x49,0x36};
rom char* n9_seq = {0x06,0x49,0x49,0x29,0x1e};

rom char* exp_seq =  { 0x00,0x0,0x5f,0x0,0x0};
rom char* colon_seq= { 0x00,0x36,0x36,0x0,0x0};
rom char* space_seq ={ 0,0,0,0,0 };
rom char* heart_seq = {0x0c,0x1e,0x3c,0x1e,0x0c};
rom char* asterisk_seq = {0x2a,0x1c,0x7f,0x1c,0x2a};

bit oldVal;
int idx;
		
rom char *GetByteList(char c)
{

	switch(c)
	{
		case 1: return A_seq;
		case 2: return B_seq; 
		case 3: return C_seq; 
		case 4: return D_seq; 
		case 5: return E_seq; 
		case 6: return F_seq; 
		case 7: return G_seq; 
		case 8: return H_seq; 
		case 9: return I_seq; 
		case 10: return J_seq; 
		case 11: return K_seq; 
		case 12: return L_seq; 
		case 13: return M_seq; 
		case 14: return N_seq;
		case 15: return O_seq; 
		case 16: return P_seq; 
		case 17: return Q_seq; 
		case 18: return R_seq; 
		case 19: return S_seq; 
		case 20: return T_seq; 
		case 21: return U_seq; 
		case 22: return V_seq; 
		case 23: return W_seq; 
		case 24: return X_seq; 
		case 25: return Y_seq; 
		case 26: return Z_seq; 
		
		case 33: return a_seq;
		case 34: return b_seq; 
		case 35: return c_seq; 
		case 36: return d_seq; 
		case 37: return e_seq; 
		case 38: return f_seq; 
		case 39: return g_seq; 
		case 40: return h_seq; 
		case 41: return i_seq; 
		case 42: return j_seq; 
		case 43: return k_seq; 
		case 44: return l_seq; 
		case 45: return m_seq; 
		case 46: return n_seq;
		case 47: return o_seq; 
		case 48: return p_seq; 
		case 49: return q_seq; 
		case 50: return r_seq; 
		case 51: return s_seq; 
		case 52: return t_seq; 
		case 53: return u_seq; 
		case 54: return v_seq; 
		case 55: return w_seq; 
		case 56: return x_seq; 
		case 57: return y_seq; 
		case 58: return z_seq; 
		
		case 59: return n0_seq; 
		case 60: return n1_seq; 
		case 61: return n2_seq; 
		case 62: return n3_seq; 
		case 63: return n4_seq; 
		case 64: return n5_seq; 
		case 65: return n6_seq; 
		case 66: return n7_seq; 
		case 67: return n8_seq; 
		case 68: return n9_seq; 
		case 69: return exp_seq;
		case 70: return colon_seq; 
		case 71: return heart_seq;
		case 72: return asterisk_seq;
	}
	// Everything else is a space
	return space_seq;
};

void showData(const char data)
{
	if(data & 0b0000001) clear_bit(portb,3); else set_bit(portb,3);
	if(data & 0b0000010) clear_bit(porta,7); else set_bit(porta,7);
	if(data & 0b0000100) clear_bit(porta,6); else set_bit(porta,6);
	if(data & 0b0001000) clear_bit(portb,7); else set_bit(portb,7);
	if(data & 0b0010000) clear_bit(portb,6); else set_bit(portb,6);
	if(data & 0b0100000) clear_bit(portb,5); else set_bit(portb,5);
	if(data & 0b1000000) clear_bit(portb,4); else set_bit(portb,4);
}

void showMessage(const char *message, char count)
{
	char i;
	char j;
	char data;
	
	rom char *sequence;
	
	for(j=0; j<count; j++)
	{
		sequence = GetByteList(message[j]);
		for(i=0; i<5; i++)
		{
			// Display column
			data = sequence[i];
			showData(data);
			delay_us(200);
			delay_us(200);

			// All Off
			portb = 0xff;
			porta = 0xff;
			delay_us(200);
			delay_us(200);
		}
		// Space between letters.
		delay_ms(1);
	}
};

void programming()
{
	unsigned char data = 1;
	unsigned char i,j;
	unsigned char count;
	
	for(i=0; i<3;i++)
	{
		for(j=0;j<7;j++)
		{
			showData(data);
			data <<= 1;
			data |= 1;
			delay_ms(45);
		}
		for(j=0;j<7;j++)
		{
			data >>= 1;
			showData(data);
			delay_ms(45);
		}
	}
	
	while(!portb.1 || !portb.2); // Wait for both buttons to be released
	
	data = eeprom_read(address);
	showData(data);

	while(1)
	{
		count = 10;
		while(!portb.1 && count)
		{
			delay_ms(2);
			count--;
		}
		if(count == 0) // Held down for 20ms?
		{
			data++;
			if(data>0x7f) data = 0;
			showData(data);
			count = 80;
			while(!portb.1)
			{
				delay_ms(15);
				if(count) count--;
				if(count==0)
				{
					data++;
					if(data>73) data=0;
					showData(data);
					if(data==0 || data==16 || data ==32 || data==48 || data==64) 
					{
						while(!portb.1);
					}
				}
			}
		}

		if(!portb.2) // Button 2 is pressed
		{
			delay_ms(10);
			if(!portb.2) // Is it still pressed?
			{
				eeprom_write(address++,data);
				data = eeprom_read(address); 
				showData(data);
				while(!portb.2); // Wait for release
			}
		}
	}
}

void main( void )
{
	cmcon = 7; //disable comparators
	
	clear_bit( option_reg, 7 ); 

	//Configure port A
	trisa = 0x00;
	//Configure port B
	trisb = 0x07;  // RB0, 1, 2 are inputs.

	//Initialize port A
	porta = 0x00;
	//Initialize port B
	portb = 0x00;
	
	delay_ms(100);
	
	address = 0;
	while((data = eeprom_read(address)) != 0)
	{
		message[address++] = data;
	}	

	if(!portb.1 || !portb.2)
	{
		address = 0;
		programming();
	}
	else
	{
		//Endless loop
		while( 1 ) 
		{
			showMessage(message,address);
			//while(portb.0);
			//while(!portb.0);	
			delay_ms(7);
		};
	}
}
