

//------------------------- Directivas para el compilador ------------------------

#zero_ram


#define simula 0


#if (!simula)
   #include <18f2550.h>
   #fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,PLL5,CPUDIV3,VREGEN
   #use delay(clock=48000000)
   #use rs232(STREAM=pc,baud=115200, xmit=PIN_C6, rcv=PIN_C7)
// Para la simulacion
#else
   #include <18f452.h>
   #fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT
   #use delay(clock=4000000)
   #use rs232(STREAM=lcd_keypad,baud=9600, xmit=PIN_C6, rcv=PIN_C7)
   #use rs232(STREAM=pc,baud=19200, xmit=PIN_C2, rcv=PIN_C1)
#endif
/////////////////



#use standard_io(b)


#define MMC_DEBUG PRINTF      // Activar esta linea para ver los mensajes DEBUG
//#define MMC_DEBUG(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)   // Anula esta linea para activar los mensajes DEBUG

#define MMC_CS    PIN_b2
#define MMC_CLK   PIN_B1
#define MMC_DI    PIN_B0
#define MMC_DO    PIN_B3
#define Buffer_Rs232_Size 2        // Buffer Interrupcion RS232 (Longitud Fija de los Paquetes recibidos VER: )
#define bkbhit (next_in!=next_out)  // Retorna 1(True) si es Diferente en caso contrario 0(False)

#include <mmc_spi.c>


int1 BufferRs232Full;               // esta Bandera indica si se ha llenado el buffer RS232
char buffermmc[512];
int     buffer[Buffer_Rs232_Size]; // Bufer del Puerto RS232
int    next_in       = 0;         // Almacena el Caracter Entrante por RS232
int    next_out      = 0;         // Almacena el Ultimo Caractes Recibido por RS232
unsigned byte seconds  = 0;         // Contador interno de segundos
char     Buffer_RS232[512];     // Almacena la Ultima Tecla Pulsada en el KEYPAD
char     MessageRs232[2];
char     Code_Recv_Rs232;
int8     Index_Buffer_KeyPad = 0;
int8     Index_Buffer_Rs232 = 0;
int8     _Count     = 0;            // Variable para Contadores de 0 a 255 Temporales

/*
struct {
   int size_MB;   // // Resutado de la multiplicacion
   char pnm[7];   // Nombre Tarjeta
   int8 mid;       // fabricante
   int16 oid;        // aplicacion
   int8 prv[2];       // revision
   int32 psn; // numero de serie
   int8 mdt[2];       // mes aņo fabricacion
}infommc;

*/
#define PARSE_U32(buf,index) 	(((unsigned int32)buf[index]) << 24) | (((unsigned int32)buf[index+1]) << 16) | (((unsigned int32)buf[index+2]) << 8) | ((unsigned int32)buf[index+3]);
#define PARSE_U16(buf,index)	(((unsigned int16)buf[index]) << 8) | ((unsigned int16)buf[index+1]);


void display_buffer(char * ptr, int32 size);
void MMC_get_volume_info();
int32 mmc_tran_speed( int8 ts );
void putcint(int x) { 
   putc(x); 
} 

#define Send_String_RS232(x,y,z) putc(0);\ 
putc(170);\ 
putcint(x);\ 
putc ( y ); \ 
if ( y ) \ 
      putc ( z ) 
#int_rda                            // Interrupcion RS232 al Recibir un Dato
void serial_isr() {
   int t;
#if (!simula)
   buffer[next_in]=fgetc(pc);               // Almacena el Caracter de Entrada para Comparar Posteriormente
#else
   buffer[next_in]=fgetc(lcd_keypad);               // Almacena el Caracter de Entrada para Comparar Posteriormente
#endif
   t=next_in;                                      // Almacena el Caracter de Entrada
   next_in=(next_in+1) % BUFFER_RS232_SIZE;
   if(next_in==next_out){                           //
     next_in=t;                                    // Buffer lleno
     BufferRs232Full=1;
   }
}
// FUNCION UTILIZADA POR LA INTERRUPCION DEL TECLADO
byte bgetc() {
   byte c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_RS232_SIZE;
   return(c);
}

main()
{
int16 size=0;
unsigned int32 address=0;
int *ptra;
int16 f;
int16 a=1;
int32 e,i,j,k,l;


ptra = &(buffermmc[0]);


enable_interrupts(int_rda);
enable_interrupts(global);


fprintf(pc, "\r\n\Rulando...........");
fprintf(pc, "\r\n 9 -> Muestra Ayuda ");

#if (simula!=0)
while(mmc_init()!=0){
   fprintf(pc, "\n\r MMC/SD init fault\n\r");
}
   fprintf(pc, "\n\r MMC/SD init ok\n\r");
#endif





   while(1){
      while(BufferRs232Full) {                        // Si el Buffer recibido de CHIP_MAIN esta lleno
         for(_count=0;_Count <= (Buffer_Rs232_Size - 2);_Count++)
            Buffer_RS232[_Count]=bgetc();             // Guarda el mensaje recibido por CHIP_MAIN
         BufferRs232Full=0;                           // Bajo la Bandera indicadora
         for(_Count=0;_Count <= Buffer_Rs232_Size - 2;_Count++)
            MessageRs232[_Count]=Buffer_RS232[_Count+1]; // Extrae el Mensaje menos el primer byte del comando

         MMC_DEBUG("\r\n Buffer_RS232->%s ",Buffer_RS232);
         fprintf(pc,  "\r\n Comando   -> %d ",Buffer_RS232[0]);
         MMC_DEBUG( "\r\n Mensaje   ->%s ", MessageRs232);

         disable_interrupts(int_rda);
         Switch (Buffer_RS232[0]){                       // Ejecuta el Comando Predefinidos Recibidos
            Case 48: //       0
               if(mmc_init()==0)
                  fprintf(pc, "\n\rmmc init ok\n\r");
               else
                  fprintf(pc, "\n\rmmc init fault\n\r");
                 break;
            Case 49: //       1
               if(mmc_write_block(address, 512, buffermmc)==0)
                  fprintf(pc, "\n\rwrite ok \n\r");
               else
                  fprintf(pc, "\n\rwrite fault \n\r");
               break;
            Case 50: //       2
                  for(f=0;f<=512;f++)
                     buffermmc[f]=0;
                    fprintf(pc, "\r\n Buffer borrado........... ");
               break;
            Case 51: //       3
                  address=address+512;
                  fprintf(pc, "\n\r Buffer address            -> %Ld a %Ld",address,address+512);
               break;
            Case 52: //       4
                  while(a) {
                     if(size!=512) {
                        buffermmc[size]=getc();
                        size++;
                     }
                     else
                        a=0;
                  }
                  size=0;
               break;
            Case 53: //       5
                if(mmc_read_block(address, 512,buffermmc)==0)
                     fprintf(pc, "\r\n Read ok\n\r");
               else
                  fprintf(pc, "\r\n Read fault");
               break;
            Case 54: //       6
               address=address-512;
               fprintf(pc, "\n\r Buffer address            -> %Ld a %Ld",address,address+512);
               break;
            Case 55: //       7

               break;
            Case 56: //       8
               display_buffer(buffermmc, 512);
               fprintf(pc, "\r\n Direccion       -> %Ld a %Ld",address,address+512);
               MMC_get_volume_info();
               break;
            Case 57: //       9
               fprintf(pc, "\r\n 0 + ENTER -> Inicia la tarjeta");
               fprintf(pc, "\r\n 1 + ENTER -> Escribe el Buffer en la tarjeta");
               fprintf(pc, "\r\n 2 + ENTER -> Borra el Buffer temporal");
               fprintf(pc, "\r\n 3 + ENTER -> Address +");
               fprintf(pc, "\r\n 4 + ENTER -> Escribe Buffer temporal ");
               fprintf(pc, "\r\n 6 + ENTER -> Address -");
               fprintf(pc, "\r\n 5 + ENTER -> Leer Buffer de la tarjeta");
               fprintf(pc, "\r\n 7 + ENTER -> Detecta la tarjeta");
               fprintf(pc, "\r\n 8 + ENTER -> Muestra el Buffer temporal");
               fprintf(pc, "\r\n 9 + ENTER -> Muestra esta ayuda ");
               fprintf(pc, "\n\r");
               ptra = &(buffermmc[0]);
               fprintf(pc, "\n\r Buffer address            -> %Ld a %Ld",address,address+512);
               MMC_DEBUG("\n\r Ptra points to            -> %ld",ptra);
               break;
            Default:
               ptra = &(buffermmc[0]);
               MMC_DEBUG("\n\rBuffer address            = %ld",&(buffermmc[0]));
               MMC_DEBUG("\n\rptra points to              = %ld",ptra);
               fprintf(pc, "\n\r");
               fprintf(pc, "\r\n\Comando  -> %u <- No Reconocido", Buffer_RS232[1]);
               BufferRs232Full=0;                           // Bajo la Bandera indicadora
               break;
        }
      enable_interrupts(int_rda);
      }
   }

}






void MMC_get_volume_info(){

#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1       */

   char buf[16];
   unsigned int32 megas;


   int8  mid;
	unsigned int16 oid;
	unsigned int8  pnm[7];   // Product name (we null-terminate)
	unsigned int8  prv;
	unsigned int32 psn;
	unsigned int8  mdt;


int i;

unsigned int8  csd_structure;
unsigned int8  spec_vers;
unsigned int8  taac;
unsigned int8  nsac;
unsigned int8  tran_speed;
unsigned int16 ccc;
unsigned int8  read_bl_len;
unsigned int8  read_bl_partial;
unsigned int8 write_blk_misalign;
unsigned int8  read_blk_misalign;
unsigned int8  dsr_imp;
unsigned int16 c_size;
unsigned int8  vdd_r_curr_min;
unsigned int8 vdd_r_curr_max;
unsigned int8  vdd_w_curr_min;
unsigned int8  vdd_w_curr_max;
unsigned int8 c_size_mult;
unsigned int8  wp_grp_size;
unsigned int8  wp_grp_enable;
unsigned int8  default_ecc;
unsigned int8  r2w_factor;
unsigned int8  write_bl_len;
unsigned int8  write_bl_partial;
unsigned int8  file_format_grp;
unsigned int8  copy;
unsigned int8  perm_write_protect;
unsigned int8  tmp_write_protect;
unsigned int8  file_format;
unsigned int8  ecc;

   // read the CSD register
   mmc_read_csd(buf);
         MMC_DEBUG("\r\n MMC CSD: ");
         for(i=0;i<16;i++)
            MMC_DEBUG("%X ",buf[i]);
   csd_structure      = (buf[0] & 0xc0) >> 6;
	spec_vers          = (buf[0] & 0x3c) >> 2;
	taac               = buf[1];
	nsac               = buf[2];
	tran_speed         = buf[3];
	ccc                = (((unsigned int16)buf[4]) << 4) | ((buf[5] & 0xf0) >> 4);
	read_bl_len        = buf[5] & 0x0f;
	read_bl_partial    = (buf[6] & 0x80) ? 1 : 0;
	write_blk_misalign = (buf[6] & 0x40) ? 1 : 0;
	read_blk_misalign  = (buf[6] & 0x20) ? 1 : 0;
	dsr_imp            = (buf[6] & 0x10) ? 1 : 0;
	c_size             = ((((unsigned int16)buf[6]) & 0x03) << 10) | (((unsigned int16)buf[7]) << 2) | (((unsigned int16)buf[8]) & 0xc0) >> 6;
	vdd_r_curr_min     = (buf[8] & 0x38) >> 3;
	vdd_r_curr_max     = buf[8] & 0x07;
	vdd_w_curr_min     = (buf[9] & 0xe0) >> 5;
	vdd_w_curr_max     = (buf[9] & 0x1c) >> 2;
	c_size_mult        = ((buf[9] & 0x03) << 1) | ((buf[10] & 0x80) >> 7);
	switch ( csd_structure ) {
	case CSD_STRUCT_VER_1_0:
	case CSD_STRUCT_VER_1_1:
//		csd->erase.v22.sector_size    = (buf[11] & 0x7c) >> 2;
//		csd->erase.v22.erase_grp_size = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
		break;
	case CSD_STRUCT_VER_1_2:
	default:
//		csd->erase.v31.erase_grp_size = (buf[11] & 0x7c) >> 2;
//		csd->erase.v31.erase_grp_mult = ((buf[11] & 0x03) << 3) | ((buf[12] & 0xe0) >> 5);
		break;
	}
	wp_grp_size        = buf[11] & 0x1f;
	wp_grp_enable      = (buf[12] & 0x80) ? 1 : 0;
	default_ecc        = (buf[12] & 0x60) >> 5;
	r2w_factor         = (buf[12] & 0x1c) >> 2;
	write_bl_len       = ((buf[12] & 0x03) << 2) | ((buf[13] & 0xc0) >> 6);
	write_bl_partial   = (buf[13] & 0x20) ? 1 : 0;
	file_format_grp    = (buf[14] & 0x80) ? 1 : 0;
	copy               = (buf[14] & 0x40) ? 1 : 0;
	perm_write_protect = (buf[14] & 0x20) ? 1 : 0;
	tmp_write_protect  = (buf[14] & 0x10) ? 1 : 0;
	file_format        = (buf[14] & 0x0c) >> 2;
	ecc                = buf[14] & 0x03;

    megas = c_size  >>(9-c_size_mult);

MMC_DEBUG("\r\n\ csd_structure=%d",csd_structure);
MMC_DEBUG("\r\n\ spec_vers=%d", spec_vers);
MMC_DEBUG("\r\n\ taac=%02x",taac);
MMC_DEBUG("\r\n\ nsac=%02x",nsac);
MMC_DEBUG("\r\n\ tran_speed=%02x",mmc_tran_speed(tran_speed));
MMC_DEBUG("\r\n\ ccc=%04x",ccc);
MMC_DEBUG("\r\n\ read_bl_len=%d",read_bl_len);
MMC_DEBUG("\r\n\ read_bl_partial=%d",read_bl_partial);
MMC_DEBUG("\r\n\ write_blk_misalign=%d",write_blk_misalign);
MMC_DEBUG("\r\n\ read_blk_misalign=%d",read_blk_misalign);
MMC_DEBUG("\r\n\ dsr_imp=%d",dsr_imp);
MMC_DEBUG("\r\n\ c_size=%ld",c_size);
MMC_DEBUG("\r\n\ vdd_r_curr_min=%d",vdd_r_curr_min);
MMC_DEBUG("\r\n\ vdd_r_curr_max=%d",vdd_r_curr_max);
MMC_DEBUG("\r\n\ vdd_w_curr_min=%d",vdd_w_curr_min);
MMC_DEBUG("\r\n\ vdd_w_curr_max=%d",vdd_w_curr_max);
MMC_DEBUG("\r\n\ c_size_mult=%d",c_size_mult);
MMC_DEBUG("\r\n\ wp_grp_size=%d",wp_grp_size);
MMC_DEBUG("\r\n\ wp_grp_enable=%d",wp_grp_enable);
MMC_DEBUG("\r\n\ default_ecc=%d",default_ecc);
MMC_DEBUG("\r\n\ r2w_factor=%d",r2w_factor);
MMC_DEBUG("\r\n\ write_bl_len=%d",write_bl_len);
MMC_DEBUG("\r\n\ write_bl_partial=%d",write_bl_partial);
MMC_DEBUG("\r\n\ file_format_grp=%d",file_format_grp);
MMC_DEBUG("\r\n\ copy=%d",copy);
MMC_DEBUG("\r\n\ perm_write_protect=%d",perm_write_protect);
MMC_DEBUG("\r\n\ tmp_write_protect=%d",tmp_write_protect);
MMC_DEBUG("\r\n\ file_format=%d",file_format);
MMC_DEBUG("\r\n\ ecc=%d",ecc);



   mmc_read_cid(buf);
   MMC_DEBUG("\r\n MMC CID: ");
   for(i=0;i<16;i++)
      MMC_DEBUG("%X ",buf[i]);
   mid= buf[0];
   switch (buf[0]){
      case 0x02:
         sprintf(mid,"%s","Toshiba");
         break;
      case 0x03:
         sprintf(mid,"%s","SanDisk");
         break;
      case 0x1c:
         sprintf(mid,"%s","Transcend");
         break;
      case 0x18:
         sprintf(mid,"%s","Lexar");
         break;
      case 0x27:
         sprintf(mid,"%s","Neus");
         break;
      default:
         break;
   }
   oid= PARSE_U16(buf,1);
   for ( i = 0 ; i < 6 ; i++ )
  		pnm[i] = buf[3+i];
   pnm[6] = '\0';
   prv= buf[8];
   psn= ((((unsigned int32)buf[9]) << 24) | (((unsigned int32)buf[10]) << 16) | (((unsigned int32)buf[11]) << 8) | ((unsigned int32)buf[12]));//PARSE_U32(data,11);
   mdt= buf[14];

   fprintf(pc, "\r\n Tamaņo de la tarjeta   -> %Ld MB",megas);
   fprintf(pc, "\r\n Velocidad              -> %Ld",mmc_tran_speed(tran_speed));
   fprintf(pc, "\r\n Fabricante             -> %s", mid);
   fprintf(pc, "\r\n Aplicacion             -> %Ld", oid);
   fprintf(pc, "\r\n Nombre de la tarjeta   -> %s", pnm);
   fprintf(pc, "\r\n Numero de Revision     -> %d.%d", (prv>>4),(prv&0xf));
   fprintf(pc, "\r\n Numero de serie        -> %Ld", psn);
   fprintf(pc, "\r\n Fabricada el           -> %d/%Ld", (mdt>>4), (mdt&0xf)+1997);
}


int32 mmc_tran_speed( int8 ts )
{

#define KBPS 1
#define MBPS 1000

static int32 ts_exp[] = { 100*KBPS, 1*MBPS, 10*MBPS, 100*MBPS, 0, 0, 0, 0 };
static int32 ts_mul[] = { 0, 1000, 1200, 1300, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 7000, 8000 };

	int32 rate;

   rate = ts_exp[(ts & 0x7)] * ts_mul[(ts & 0x78) >> 3];

	if ( rate <= 0 ) {
		fprintf(pc, "\r\n\ Error - unrecognized speed 0x%02x", ts);
		return 1;
	}
return rate;
}


void display_buffer(char * ptr, int32 size)
	{
	int32 i;
	int16 j;
	char * local;

	local = ptr;
	for (i=0; i < size; i++)
		{
		if (!(i % 16))
			{
			if (i)
				{
				for (j=0;j<16;j++)
					{
					if (*local < ' ')
						putc('.');
					else
						putc(*local);
					local++;
					}
				}
			fprintf(pc, "\r\n%4X - ",i);
			}
		fprintf(pc, "%X ",*ptr++);
		}

	for (j=0;j<16;j++)
		{
		if (*local < ' ')
			putc('.');
		else
			putc(*local);
		local++;
		}
	fprintf(pc, "\r\n");
	}

