Prototipo_SantaAna

Dependencies:   BatteryPanel_St_An Slave_St_An mbed GraphicLCD_St_An ThermalPrinter_St_An LimitSwtiches

main.cpp

Committer:
williequesada
Date:
2019-06-04
Revision:
0:a37ed180e6e3

File content as of revision 0:a37ed180e6e3:

#include    "mbed.h"
#include    <string>

#include    "BatteryPanel.h"
#include    "ThermalPrinter.h"
#include    "LimitSwitches.h"
#include    "GraphicLCD.h"
//#include    "KeyPad.h"
#include    "Slave.h"

#define     NO_KEY              0x00
#define     NO_DATA             0x87

#define     COMMAND_ON          0X70
#define     COMMAND_INIT        0X71
#define     COMMAND_GPRS        0X72
#define     COMMAND_DATA        0X73
#define     COMMAND_POST        0X74
#define     COMMAND_ANSWER      0X75
#define     COMMAND_SIGNAL      0X76
#define     COMMAND_CONNECT     0X77
#define     COMMAND_OFF         0X78
#define     HOSTING_STEP1       0x79
#define     HOSTING_STEP2       0x7A
#define     HOSTING_STEP3       0x7B
#define     HOSTING_STEP4       0x7C
#define     HOSTING_STEP5       0x7D
#define     HOSTING_STEP6       0x7E
#define     HOSTING_STEP7       0x7F
#define     HOSTING_STEP8       0x80
#define     HOSTING_STEP9       0x81
#define     HOSTING_STEP10      0x82
#define     HOSTING_STEP11      0x83
#define     HOSTING_OFF         0x84
#define     NEXT_STEP           0x85
#define     NEXT_SLEEP          0x86
#define     COMMAND_END         0X88

#define     USER_INIT           0xA0
#define     USER_PLACE          0xA1
#define     USER_CARD           0xA2
#define     USER_TIME           0xA3
#define     USER_DATA           0xA4
#define     USER_PRINT          0xA5
#define     USER_TICKET         0xA6
#define     USER_FINISH         0xA7
#define     USER_POST           0xA8
#define     USER_ANSWER         0xA9
#define     USER_INIT2          0xAA
#define     USER_INIT3          0xB0
#define     USER_INIT4          0xB1
#define     USER_CARD2          0xB2
#define     USER_INIT5          0xB3
#define     USER_CARD3          0xB4

#define     M_SISTEMA           0x40
#define     M_RED               0x41
#define     M_IMPRESORA         0x42
#define     M_TECLADO           0x43
#define     M_LECTORA           0X44
#define     M_INFORMACION       0x45
#define     M_OFF               0x46
#define     M_PARQUIMETRO       0x47
#define     M_MUNICIPIO         0x48
#define     M_PRECIO            0x49
#define     M_ATRAS             0x4A
#define     M_SENAL             0x4B
#define     M_HOSTING           0x4C
#define     M_CONEXION_SIM      0x4E
#define     M_PAPEL             0x4F
#define     M_IMPRESION         0x50
#define     M_CONEXION_IMP      0x51
#define     M_LECTURA           0x52
#define     M_CONEXION_LEC      0x53
#define     M_PRUEBA_TECLA      0x54

BATTERY_PANEL Charger(PF_9, PF_7, PG_1);
// BATTERY_PANEL Charger(AnalogBattery, AnalogPanel, ControlCarga);

GLCD         Screen(PD_8,PE_10,PD_9,PE_12,PE_8,PE_14,PE_7,PE_15,PE_9,PE_11,PF_15,PE_13,PF_13,PB_1,PF_14);
// CLASS     GLCD(D1,D2,D3,D4,D5,D6,D7,D8,CD,RESET,CE,WR,RD)

// KEYPAD       KeyPad(PF_0,PE_3,PF_1,PE_6,PE_5,PF_2,PE_4,PB_6);
// CLASS     KEYPAD(F1,F2,F3,F4,C1,C2,C3,C4);

PRINTER      Impresora(PC_10,PC_11,PE_0,PB_10,PB_0,PC_2);
// CLASS     PRINTER(TX,RX,PAPER,SELECT,RESET,POWER)

SLAVE        Slave(PD_5,PD_6,PD_7);
// CLASS     SLAVE(TX,RX,AWAKE)

SWITCHES     Doors(PC_4,PC_1);
// CLASS     SWITCHES(SENSOR1,SENSOR2)

RawSerial    CardReader(PC_12,PD_2,9600);
// Serial    CardReader(TX,RX,BAUT);

Serial       Computer(USBTX,USBRX,9600);

InterruptIn  Configuracion(USER_BUTTON);
DigitalOut   CardReaderPower(PF_3);//

DigitalOut   MAX232(PC_8);
DigitalOut   Keypad_F1(PF_0);
DigitalOut   Keypad_F2(PE_3);
DigitalOut   Keypad_F3(PF_1);
DigitalOut   Keypad_F4(PF_8);//
InterruptIn  Keypad_C1(PA_0);//PE_5
InterruptIn  Keypad_C2(PE_6);//PF_2
InterruptIn  Keypad_C3(PC_5);//PE_4
InterruptIn  Keypad_C4(PA_2);//PB_6

//-----------------------Conexiones GLCD T6963C---------------------------------
//          1  2       Vss Vss          Ti  Ti(NO Conectada)
//          3  4       Vcc Cte          Vc  Po
//          5  6       WR  RD           D14 D15
//          7  8       CE  CD           F12 F13
//          9  10      -V  RST          Po  E9
//          11 12      D0  D1           E11 F14
//          13 14      D2  D3           E13 F15
//          15 16      D4  D5           D8  D9
//          17 18      D6  D7           E8  E7
//          19 20      NC  NC
//
//-----------Conexiones Usadas---------  //-------Conexiones Usadas STM32-------
//              ____________             //             ___________
//               2  4  6  8              //             F8 F5 F2 F0
//               1  3  5  7              //             F9 F7 F3 F1
//              ____________             //             ___________
//                  APEM                 //                 APEM
//          Serial number 12470157       //         Serial number 12470157
//-------------------------------------  //-------------------------------------
//
//------------------------CONEXIONES FUJITSU SERIAL PRINTER---------------------
// Conector RS232C(ZHR-8)
//   _ _ _ _ _ _ _ _
//  ! ! ! ! ! ! ! ! !             1->RXD    2->TXD    3->DTR    4->GND
//   1 2 3 4 5 6 7 8              5->DST    6->SLCTIN 7->INPRM  8->AFT
//
// Conector Power(PHR-2)
//   _ _ _ _ _ _
//  ! ! ! ! ! ! !             1->VCC Logic Supply    2->GND Logic
//   1 2 3 4 5 6            4,3->GND Head/Motor    5,6->VCC Head/Motor

DigitalOut   LedMantenimiento(LED1);
DigitalOut   LedHosting(LED2);
DigitalOut   LedUsuario(LED3);

const char SOH=1;
const char EOT=4;
const char ADDR=0;
const char LEN=0;
const char CARD_POSITION='8';
const char DEV_RESET=127;
const char ARM_MODE='P';
const char ARM_DEBUG='p';
const char ARM_ABORT=27;
const char MAG_ISO_T2='R';
const char BBCA='=';
const char BBCE='U';
const char BBCF='u';
const char BBCG=30;
const char BBCI='z';
const char BBCK='W';
const char R_ACTION='^';
const char R_ERROR='*';
const char R_INVALID='!';
const char R_NO_DATA='+';
const char R_COMAND_ERROR='?';
const char R_START=':';
const char R_POSITION1='q';
const char R_POSITION2='s';
const char R_NO_MAG_CARD='>';
const char R_MAG_DETECT_ON='(';
const char R_MAG_DETECT_OFF=')';

char StateReader[7]= {'0','0','0','0','0','0','0'};
char CardReader_Buffer[255];
int  CardReader_Counter=0;

char Tecla;
char Tecla_Before;
char Comando;
char InByte;
uint32_t Inicio, Fin, Transcurrido;

char Tiempo[6];
char Importe[8];
char Espacio[6];
char HoraRespuesta[6]="00:00";
char HoraFinal[6]="00:00";
char Parquimetro[5]="1067";
char Municipio[10]="Santa Ana";//"San Jose";
char CodigoMunicipio[3]="01";
char NumeroRespuesta[7]="000000";
char FechaRespuesta[11]="00-00-0000";
char Track2[22]="5303105315252296=2108";
char Alarmas[7]="AAAAAA";
char PapelDisponible[5]="0000";
char Clave[4]= {'4','3','2','1'};
char RespuestaHosting[7]="      ";
char HoraHosting[7]="     ";
char Progreso[3];
int  Counter_Host=1318;
int  Precio=350;
int  TiempoMinutos;
int  Papel=4000;
int  Hostin_Conection=1320;
bool Alarm=0;
bool MantenimientoInterruption=0;
int  HoraHostingPantalla=1000;
int  MinutosTranscurrido=11;
int  Battery_State;
int  Battery_State_Before=1;
float Battery_Voltage;
float Panel_Voltage;


//LowPowerTicker Host;
//LowPowerTimer  BaseClock;
Ticker Host;
Timer  BaseClock;

void Keypad_Init()
{
    Tecla_Before=NO_KEY;
    Keypad_F1=0;
    Keypad_F2=0;
    Keypad_F3=0;
    Keypad_F4=0;
}

char KeyPad_Read(void)
{
    Keypad_F1=1;
    Keypad_F2=0;
    Keypad_F3=0;
    Keypad_F4=0;
    wait_us(10);
    if(Keypad_C1.read()) {
        if(Tecla_Before!='1') {
            Tecla_Before='1';
            return '1';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C2.read()) {
        if(Tecla_Before!='2') {
            Tecla_Before='2';
            return '2';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C3.read()) {
        if(Tecla_Before!='3') {
            Tecla_Before='3';
            return '3';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C4.read()) {
        if(Tecla_Before!='A') {
            Tecla_Before='A';
            return 'A';
        } else {
            return NO_KEY;
        }
    }

    Keypad_F1=0;
    Keypad_F2=1;
    Keypad_F3=0;
    Keypad_F4=0;
    wait_us(10);
    if(Keypad_C1.read()) {
        if(Tecla_Before!='4') {
            Tecla_Before='4';
            return '4';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C2.read()) {
        if(Tecla_Before!='5') {
            Tecla_Before='5';
            return '5';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C3.read()) {
        if(Tecla_Before!='6') {
            Tecla_Before='6';
            return '6';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C4.read()) {
        if(Tecla_Before!='B') {
            Tecla_Before='B';
            return 'B';
        } else {
            return NO_KEY;
        }
    }

    Keypad_F1=0;
    Keypad_F2=0;
    Keypad_F3=1;
    Keypad_F4=0;
    wait_us(10);
    if(Keypad_C1.read()) {
        if(Tecla_Before!='7') {
            Tecla_Before='7';
            return '7';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C2.read()) {
        if(Tecla_Before!='8') {
            Tecla_Before='8';
            return '8';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C3.read()) {
        if(Tecla_Before!='9') {
            Tecla_Before='9';
            return '9';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C4.read()) {
        if(Tecla_Before!='C') {
            Tecla_Before='C';
            return 'C';
        } else {
            return NO_KEY;
        }
    }

    Keypad_F1=0;
    Keypad_F2=0;
    Keypad_F3=0;
    Keypad_F4=1;
    wait_us(10);
    if(Keypad_C1.read()) {
        if(Tecla_Before!='F') {
            Tecla_Before='F';
            return 'F';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C2.read()) {
        if(Tecla_Before!='0') {
            Tecla_Before='0';
            return '0';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C3.read()) {
        if(Tecla_Before!='E') {
            Tecla_Before='E';
            return 'E';
        } else {
            return NO_KEY;
        }
    }
    if(Keypad_C4.read()) {
        if(Tecla_Before!='D') {
            Tecla_Before='D';
            return 'D';
        } else {
            return NO_KEY;
        }
    }

    Tecla_Before=NO_KEY;
    return NO_KEY;
}

void KeyPad_InterruptDisable()
{
    Keypad_C1.disable_irq();
    Keypad_C2.disable_irq();
    Keypad_C3.disable_irq();
    Keypad_C4.disable_irq();
}

void KeyPad_InterruptEnable()
{
    Keypad_C1.enable_irq();
    Keypad_C2.enable_irq();
    Keypad_C3.enable_irq();
    Keypad_C4.enable_irq();
    Keypad_F1=1;
    Keypad_F2=1;
    Keypad_F3=1;
    Keypad_F4=1;
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------
void PantallaInicio()
{
    Computer.printf("Pantala de Inicio\n");

    Screen.Limits();
    Screen.PutString(45,19,"Prueba E-Park");
    Screen.Show();
    wait_ms(2000);

    Screen.Limits();
    Screen.PutString(58,12,"Grupo Setex");
    Screen.PutString(65,34,"Costa Rica");
    Screen.Show();
    wait_ms(3000);
}

void AlarmasCall(int Periferico,bool Estado)
{
    // 1 -> Lector
    // 2 -> Impresora
    // 3 -> Papel
    // 4 -> Puerta1
    // 5 -> Puerta2
    // 6 -> Bateria
    if(Estado) {
        Alarmas[Periferico-1]='E';
        Alarm=1;
    } else {
        Alarmas[Periferico-1]='A';
    }
}

char GetTime(char Salida,uint32_t TimeOut)
{
    bool Salir;
    bool Finalizar;
    bool Agregar;
    bool Restar;
    int PositionTime=3;
    int Hora=PositionTime/6;
    int Minuto=(PositionTime%6)*10;
    int Costo=(PositionTime/3)*Precio;

    Tiempo[0]='0';
    Tiempo[1]=':';
    Tiempo[2]='3';
    Tiempo[3]='0';
    Tiempo[4]=' ';
    Tiempo[5]='\0';
    
    sprintf(Importe,"%i*",Costo);

    Screen.PutString(15,12,"Tiempo:");
    Screen.PutString(88,12,Tiempo);
    Screen.PutString(15,34,"Precio:");
    Screen.PutString(85,34,Importe);
    Screen.PutString(141,46,"Confirmar");
    Screen.Limits();
    Screen.Show();

    if(Computer.writeable()) {
        Computer.printf("Tiempo y precio \n");
        Computer.printf(Tiempo);
        Computer.printf(" ");
        Computer.printf(Importe);
        Computer.printf("\n");
    }
    Inicio=BaseClock.read_ms();
    Keypad_Init();
    while(true) {

        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            Screen.Clean();
            return USER_FINISH;
        }

        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                            // Se valida que se ingrese una tecla valida por el teclado
            Inicio=BaseClock.read_ms();

            Agregar=(Tecla=='E');
            if ((Agregar)&&(PositionTime<72)) {         // Sumar 30 minutos, maximos 12 horas
                PositionTime+=3;
            }
            Restar=((Tecla=='F')&&(PositionTime>3));    // Restar 10 minutos, minimo 30 minutos
            if (Restar) {
                PositionTime-=3;
            }
            Salir=(Tecla=='C');                         // Cancelar operacion
            if (Salir) {
                Screen.Clean();
                return USER_FINISH;
            }
            Finalizar=(Tecla=='D');                     // En caso de confirmacion
            if (Finalizar) {
                Screen.PutString(15,12,"Realizando");
                Screen.PutString(15,34,"Operacion...");
                Screen.PutChar(84,33,'!');
                Screen.Limits();
                Screen.Show();
                return Salida;
            }

            Hora=PositionTime/6;
            Minuto=(PositionTime%6)*10;
            Costo=(PositionTime/3)*Precio;
            if(Minuto==0) {                             // Calcular tiempo en horas y minutos
                sprintf(Tiempo,"%i:0%i",Hora,Minuto);
                sprintf(Importe,"%i*",Costo);
            } else {
                sprintf(Tiempo,"%i:%i",Hora,Minuto);
                sprintf(Importe,"%i*",Costo);
            }
            TiempoMinutos=PositionTime*10;

            //-------Mostrar en Patalla-------
            Screen.PutString(15,12,"Tiempo:");
            Screen.PutString(88,12,Tiempo);
            Screen.PutString(15,34,"Precio:");
            Screen.PutString(85,34,Importe);
            Screen.PutString(141,46,"Confirmar");
            Screen.Limits();
            Screen.Show();

            if(Computer.writeable()) {
                Computer.printf(Tiempo);
                Computer.printf(" ");
                Computer.printf(Importe);
                Computer.printf("\n");
            }
        }
    }
}

char GetPlace(char Salida,uint32_t TimeOut)
{
    bool    Numero;
    bool    Borrar;
    bool    Finalizar;
    bool    Salir;
    uint8_t PositionPlace=0;

    Espacio[0]='_';
    Espacio[1]=' ';
    Espacio[2]=' ';
    Espacio[3]=' ';
    Espacio[4]=' ';
    Espacio[5]='\0';

    Screen.Limits();
    Screen.PutString(15,12,"Numero de espacio:");
    Screen.PutChar(28,11,'!');
    Screen.PutString(15,34,Espacio);
    Screen.Show();

    if(Computer.writeable()) {
        Computer.printf("Obteniendo numero de espacio:\n");
        Computer.printf("%s \n",Espacio);
    }
    Inicio=BaseClock.read_ms();
    Keypad_Init();
    while(true) {

        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            Screen.Clean();
            return USER_FINISH;
        }

        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                                        // Se valida que se ingrese una tecla valida
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if ((Numero)&&(PositionPlace<4)) {                      //Agregar un digito
                Espacio[PositionPlace]=Tecla;
                PositionPlace++;
                Espacio[PositionPlace]='_';
                Espacio[4]=' ';
            }
            Borrar=(Tecla=='B')&&(PositionPlace>0);
            if (Borrar) {                                           //Borrar el ultimo digito
                Espacio[PositionPlace]=' ';
                PositionPlace--;
                Espacio[PositionPlace]='_';
                Espacio[4]=' ';
            }
            Salir=(Tecla=='C');                                     //Cancelar operacion
            if (Salir) {
                Screen.Clean();
                return USER_FINISH;
            }
            Finalizar=((Tecla=='D')&&(PositionPlace==4));           //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            if(PositionPlace==4) {                                 //Se debe confirmar cuando estan los 4 digitos
                Screen.Limits();
                Screen.PutString(15,12,"Numero de espacio:");
                Screen.PutChar(28,11,'!');
                Screen.PutString(15,34,Espacio);
                Screen.PutString(141,46,"Confirmar");
                Screen.Show();
            } else {
                Screen.Limits();
                Screen.PutString(15,12,"Numero de espacio:");
                Screen.PutChar(28,11,'!');
                Screen.PutString(15,34,Espacio);
                Screen.Show();
            }
            Computer.printf("%s\n",Espacio);
        }
    }
}


void Interrupt_CardReader()
{
    if(CardReader.readable()) {
        CardReader_Buffer[CardReader_Counter]=CardReader.getc();
        CardReader_Counter++;
    }
}

int ResetCard()
{
    CardReader_Counter=0;
    StateReader[0]='S';
    Computer.printf("\n Reset card reader");
    if(CardReader.writeable()) {
        CardReader.putc(SOH);           // 00000001
        CardReader.putc(ADDR);          // 00000000
        CardReader.putc(LEN);           // 00000000
        CardReader.putc(LEN);           // 00000000
        CardReader.putc(DEV_RESET);     // 01111111
        CardReader.putc(EOT);           // 00000100
        CardReader.putc(BBCI);          // 01111010
    }
    wait_ms(2000);
    for(int i=0; i<=CardReader_Counter; i++) {
        if(CardReader_Buffer[i]==R_START) {
            Computer.printf("\n START");            // Encendido
            StateReader[0]='A';
            AlarmasCall(1,0);
            return 1;
        }
        if(CardReader_Buffer[i]==R_INVALID) {
            Computer.printf("\n INVALID ");         // Comando Invalido
            StateReader[0]='N';
            AlarmasCall(1,1);
            return 0;
        }
        if(CardReader_Buffer[i]==R_ERROR) {
            Computer.printf("\n ERROR ");           // Error
            StateReader[0]='E';
            AlarmasCall(1,1);
            return 0;
        }
        if(CardReader_Buffer[i]==R_COMAND_ERROR) {
            Computer.printf("\n COMAND ERROR ");    // Error en comando
            StateReader[0]='C';
            AlarmasCall(1,1);
            return 0;
        }
    }
    AlarmasCall(1,1);
    return 0;
}

void DetectionCard(uint32_t TimeOut)
{
    CardReader_Counter=0;
    StateReader[1]='S';
    StateReader[2]='S';
    StateReader[3]='S';
    if(StateReader[0]=='A') {               // Se envia el comando Arm Debug
        Computer.printf("\n Introducir tarjeta");
        if(CardReader.writeable()) {
            CardReader.putc(SOH);
            CardReader.putc(ADDR);
            CardReader.putc(LEN);
            CardReader.putc(LEN);
            CardReader.putc(ARM_DEBUG);
            CardReader.putc(EOT);
            CardReader.putc(BBCF);
        }
        wait_ms(500);
        for(int i=0; i<=CardReader_Counter; i++) {
            if(CardReader_Buffer[i]==R_ACTION) {
                Computer.printf("\n ACTION ");      // Accion ejecutada
                StateReader[1]='A';
            }
            if(CardReader_Buffer[i]==R_INVALID) {
                Computer.printf("\n INVALID ");     // Comando Invalido
                StateReader[1]='N';
            }
            if(CardReader_Buffer[i]==R_ERROR) {
                Computer.printf("\n ERROR ");       // Error
                StateReader[1]='E';
            }
            if(CardReader_Buffer[i]==R_COMAND_ERROR) {
                Computer.printf("\n COMAND ERROR ");// Error en comando
                StateReader[1]='C';
            }
        }
        CardReader_Counter=0;

        Inicio=BaseClock.read_ms();
        while(CardReader_Counter==0) {       // Esperando introduccion de tarjeta
            Fin=BaseClock.read_ms();
            Transcurrido=Fin-Inicio;
            if(StateReader[1]=='C'||StateReader[1]=='E'||StateReader[1]=='N') {
                Computer.printf("\n Error en comando");
                break;
            }
            if(StateReader[1]=='S') {
                Computer.printf("\n Sin respuesta");
                break;
            }
            Tecla=KeyPad_Read();
            if(Tecla=='C') {
                Computer.printf("\n Cancelar operacion");
                if(CardReader.writeable()) {
                    CardReader.putc(SOH);
                    CardReader.putc(ADDR);
                    CardReader.putc(LEN);
                    CardReader.putc(LEN);
                    CardReader.putc(ARM_ABORT);
                    CardReader.putc(EOT);
                    CardReader.putc(BBCG);
                }
                break;
            }
            if(Transcurrido>TimeOut) {
                Computer.printf("\n Tiempo de respuesta");
                if(CardReader.writeable()) {
                    CardReader.putc(SOH);
                    CardReader.putc(ADDR);
                    CardReader.putc(LEN);
                    CardReader.putc(LEN);
                    CardReader.putc(ARM_ABORT);
                    CardReader.putc(EOT);
                    CardReader.putc(BBCG);
                }
                break;
            }
        }
        wait_ms(1000);
        for(int i=0; i<=CardReader_Counter; i++) {
            Computer.printf("%c",CardReader_Buffer[i]);
            if(CardReader_Buffer[i]==R_NO_MAG_CARD) {
                Computer.printf("\n Deteccion nula ");      // No se detecta banda magnetica
                StateReader[2]='N';
                StateReader[3]='N';
            }
            if(CardReader_Buffer[i]==R_MAG_DETECT_ON) {
                Computer.printf("\n Deteccion on ");        // Se inicia verificacion de banda
                StateReader[2]='A';
            }
            if(CardReader_Buffer[i]==R_MAG_DETECT_OFF) {
                Computer.printf("\n Deteccion off ");       // Se termina verificacion de banda
                StateReader[3]='A';
            }
            if(CardReader_Buffer[i]==R_ACTION) {
                Computer.printf("\n Action arm abort ");    // Accion ejecutada
                StateReader[1]='T';
            }
        }
    }
}

int PositionCard()
{
    CardReader_Counter=0;
    StateReader[4]='S';
    Computer.printf("\n Detectando tarjeta");
    if(CardReader.writeable()) {
        CardReader.putc(SOH);
        CardReader.putc(ADDR);
        CardReader.putc(LEN);
        CardReader.putc(LEN);
        CardReader.putc(CARD_POSITION);
        CardReader.putc(EOT);
        CardReader.putc(BBCA);
    }
    wait_ms(200);
    for(int i=0; i<=CardReader_Counter; i++) {
        Computer.printf("%c",CardReader_Buffer[i]);
        if(CardReader_Buffer[i]==R_POSITION1) {
            Computer.printf("\n Tarjeta en posicion incorrecta ");   // Mal colocada la tarjeta
            StateReader[4]='N';
            return 0;
        }
        if(CardReader_Buffer[i]==R_POSITION2) {
            Computer.printf("\n Tarjeta en posicion correcta ");     // Bien colocada la tarjeta
            StateReader[4]='A';
            return 1;
        }
    }
    return 0;
}

uint8_t ReadCard(uint32_t TimeOut)
{
    CardReader_Counter=0;
    StateReader[5]='S';
    StateReader[6]='S';
    if(StateReader[4]=='A') {
        Computer.printf("\n Retirar Tarjeta en un solo movimiento");
        if(CardReader.writeable()) {
            CardReader.putc(SOH);
            CardReader.putc(ADDR);
            CardReader.putc(LEN);
            CardReader.putc(LEN);
            CardReader.putc(ARM_MODE);
            CardReader.putc(EOT);
            CardReader.putc(BBCE);
        }
        wait_ms(300);
        for(int i=0; i<=CardReader_Counter; i++) {
            Computer.printf("%c",CardReader_Buffer[i]);
            if(CardReader_Buffer[i]==R_ACTION) {
                Computer.printf("\n ACTION ");      // Accion ejecutada
                StateReader[5]='A';
            }
            if(CardReader_Buffer[i]==R_INVALID) {
                Computer.printf("\n INVALID ");     // Comando Invalido
                StateReader[5]='N';
            }
            if(CardReader_Buffer[i]==R_ERROR) {
                Computer.printf("\n ERROR ");       // Error
                StateReader[5]='E';
            }
            if(CardReader_Buffer[i]==R_COMAND_ERROR) {
                Computer.printf("\n COMAND ERROR ");// Error en comando
                StateReader[5]='C';
            }
        }
        CardReader_Counter=0;
        Inicio=BaseClock.read_ms();
        Keypad_Init();
        while(CardReader_Counter==0) {       // Esperando introduccion de tarjeta
            Fin=BaseClock.read_ms();
            Transcurrido=Fin-Inicio;
            if(StateReader[5]=='C'||StateReader[5]=='E'||StateReader[5]=='N') {
                Computer.printf("\n Error en comando");
                break;
            }
            if(StateReader[5]=='S') {
                Computer.printf("\n Sin Respuesta");
                break;
            }
            if(Transcurrido>TimeOut) {
                Computer.printf("\n Tiempo de respuesta superado");
                if(CardReader.writeable()) {
                    CardReader.putc(SOH);
                    CardReader.putc(ADDR);
                    CardReader.putc(LEN);
                    CardReader.putc(LEN);
                    CardReader.putc(ARM_ABORT);
                    CardReader.putc(EOT);
                    CardReader.putc(BBCG);
                }
                StateReader[5]='T';
                break;
            }
            Tecla=KeyPad_Read();
            if(Tecla=='C') {
                Computer.printf("\n Cancelar operacion");
                if(CardReader.writeable()) {
                    CardReader.putc(SOH);
                    CardReader.putc(ADDR);
                    CardReader.putc(LEN);
                    CardReader.putc(LEN);
                    CardReader.putc(ARM_ABORT);
                    CardReader.putc(EOT);
                    CardReader.putc(BBCG);
                }
                StateReader[5]='T';
                return 2;
            }
        }
        wait_ms(200);
        for(int i=0; i<=CardReader_Counter; i++) {
            Computer.printf("%c",CardReader_Buffer[i]);
            Computer.printf("-%2X-",CardReader_Buffer[i]);
            if(CardReader_Buffer[i]==R_NO_MAG_CARD) {
                Computer.printf("\n DETECCION NULA ");      // No se detecta banda magnetica
                StateReader[6]='N';
                return 0;
            }
            if(CardReader_Buffer[i]==R_ACTION) {
                Computer.printf("\n TARJETA LEIDA ");       // Tarjeta leida
                StateReader[6]='A';
                return 1;
            }
            if(CardReader_Buffer[i]==R_INVALID) {
                Computer.printf("\n INVALID ");             // Comando Invalido
                StateReader[6]='N';
                return 0;
            }
            if(CardReader_Buffer[i]==R_ERROR) {
                Computer.printf("\n ERROR ");               // Error
                StateReader[6]='E';
            }
            if(CardReader_Buffer[i]==R_COMAND_ERROR) {
                Computer.printf("\n COMAND ERROR ");        // Error en comando
                StateReader[6]='C';
                return 0;
            }
        }
    }
    return 0;
}

uint8_t RecibeDataCard()
{
    if (StateReader[6]=='A') {
        CardReader_Counter=0;
        if(CardReader.writeable()) {
            CardReader.putc(SOH);               // 00000001
            CardReader.putc(ADDR);              // 00000000
            CardReader.putc(LEN);               // 00000000
            CardReader.putc(LEN);               // 00000000
            CardReader.putc(MAG_ISO_T2);        // 01010101
            CardReader.putc(EOT);               // 00000100
            CardReader.putc(BBCK);
        }
        wait_ms(200);
        for(int i=0; i<=CardReader_Counter; i++) {
            if(CardReader_Buffer[i]==R_NO_DATA) {
                Computer.printf("Sin lectura\n");
                return 2;
            }
            if(CardReader_Buffer[i]=='=') {
                Computer.printf("Datos leidos\n");
                for(int i=0; i<21; i++) {
                    Track2[i]=CardReader_Buffer[i+4];
                }
                Computer.printf("<%s>",Track2);
                return 1;
            }
        }
    }
    return 0;
}

int RetiroTarjeta(uint32_t TiempoFuera)
{
    Computer.printf("Retiro tarjeta\n");
    Inicio=BaseClock.read_ms();
    while(true) {
        if(PositionCard()==0) {
            return 1;
        } else {
            Screen.Limits();                 // Se pide al usuario por pantalla el retiro de la tarjeta
            Screen.PutString(15,12,"Retire tarjeta");
            Screen.Show();
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TiempoFuera) {
            StateReader[1]='T';
            return 0;
        }
    }
}

uint8_t IngresoTarjeta(uint32_t TimeOut)
{
    Computer.printf("Funcion ingreso de tarjeta\n");

    Inicio=BaseClock.read_ms();
    Keypad_Init();
    while(true) {
        if(PositionCard()) {
            Computer.printf("Tarjeta ingresada\n");
            StateReader[1]='A';
            StateReader[2]='A';
            StateReader[3]='A';
            return 1;
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            Computer.printf("Tiempo limite\n");
            StateReader[1]='T';
            StateReader[2]='N';
            StateReader[3]='N';
            return 0;
        }
        Tecla=KeyPad_Read();
        if(Tecla=='C') {
            Computer.printf("Operacion cancelada\n");
            StateReader[1]='T';
            StateReader[2]='N';
            StateReader[3]='N';
            return 2;
        }
    }
}

uint8_t GetCard(char Salida,uint32_t TimeOutEntrada,uint32_t TimeOutSalida)
{
    //CardReaderStatus=[Reset,ArmDebug,DetectionOn,DetectionOff,Position,Arm,Read]
    // C-> Command error
    // A-> Accepted
    // N-> Invalid
    // E-> Error
    // N-> No detection
    // S-> Without answer
    // T-> Time out

    Screen.Limits();                     // Se pide al usuario por pantalla la intrduccion de la tarjeta
    Screen.PutString(15,12,"Introduzca tarjeta");
    Screen.PutString(15,34,"debito o credito");
    Screen.PutChar(26,33,'!');
    Screen.PutChar(110,33,'!');
    Screen.Show();

    if(ResetCard()) {
        while(true) {

            uint8_t RespuestaIngresoTarjeta = IngresoTarjeta(TimeOutEntrada);
            if(RespuestaIngresoTarjeta==1) {
                Screen.Limits();
                Screen.PutString(15,12,"Retire tarjeta");
                Screen.Show();
            }
            if(RespuestaIngresoTarjeta==0) {
                Screen.PutString(15,12,"Sin deteccion");
                Screen.PutChar(111,11,'!');
                Screen.Limits();
                Screen.Show();
                wait(3);
                Screen.Clean();
                return USER_FINISH;
            }
            if(RespuestaIngresoTarjeta==2) {
                Screen.Clean();
                return USER_FINISH;
            }

            uint8_t RespuestaReadCard=ReadCard(TimeOutSalida);
            if(RespuestaReadCard==2) {
                Screen.Clean();
                return USER_FINISH;
            }


            // Se le la tarjeta al retirarse
            int DataResult=RecibeDataCard();    // Se corrobora que la informacion de la tajeta es la corre
            if(DataResult==0) {
                Screen.PutString(15,12,"Banda magnetica");
                Screen.PutChar(125,11,'!');
                Screen.PutString(15,34,"ilegible");
                Screen.Limits();
                Screen.Show();
                wait(2);
                if(RetiroTarjeta(7000)) {
                    Screen.Limits();
                    Screen.PutString(15,12,"Introduzca tarjeta");
                    Screen.PutString(15,34,"debito o credito");
                    Screen.PutChar(26,33,'!');
                    Screen.PutChar(110,33,'!');
                    Screen.Show();
                } else {
                    Screen.Clean();
                    return USER_FINISH;
                }
            }
            if(DataResult==1) {
                return Salida;
            }
            if(DataResult==2) {
                Screen.PutString(15,12,"Banda magnetica");
                Screen.PutChar(125,11,'!');
                Screen.PutString(15,34,"ilegible");
                Screen.Limits();
                Screen.Show();
                wait(2);
                if(RetiroTarjeta(7000)) {
                    Screen.Limits();
                    Screen.PutString(15,12,"Introduzca tarjeta");
                    Screen.PutString(15,34,"debito o credito");
                    Screen.PutChar(26,33,'!');
                    Screen.PutChar(110,33,'!');
                    Screen.Show();
                } else {
                    Screen.Clean();
                    return USER_FINISH;
                }
            }
        }
    } else {
        Screen.Limits();
        Screen.PutString(15,20,"Error");
        Screen.Show();
        wait(3);
        Screen.Clean();
        return USER_FINISH;
    }
}

uint8_t Continuar(uint8_t Salida,uint32_t TimeOut)
{
    Inicio=BaseClock.read_ms();
    while(true) {
        if(Slave.Answer()) {
            Computer.printf("Continuar\n");
            return Salida;
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            Computer.printf("Continuar tiempo\n");
            Screen.PutString(15,12,"Operacion");
            Screen.PutChar(84,11,'!');
            Screen.PutString(15,34,"no disponible");
            Screen.Limits();
            Screen.Show();
            wait(4);
            return USER_FINISH;
        }

    }
}
uint8_t Respuesta1(uint8_t Salida,uint32_t TimeOut)
{
    Screen.PutString(15,12,"Realizando");
    Screen.PutString(15,34,"Operacion...");
    Screen.PutChar(84,33,'!');
    Screen.Limits();
    Screen.Show();
    wait_ms(TimeOut);
    return Salida;
}
uint8_t Respuesta2(uint8_t Salida,uint32_t TimeOut)
{
    Inicio=BaseClock.read_ms();
    while(true) {
        if(Slave.Mensaje()) {
            Computer.printf("Available\n");
            wait_ms(100);
            break;
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            break;
        }
    }
    InByte=Slave.Recibe();
    Computer.printf("%c",InByte);
    if(InByte=='A') {
        Screen.PutString(15,12,"Operacion");
        Screen.PutChar(84,11,'!');
        Screen.PutString(15,34,"Aceptada");
        Screen.Limits();
        Screen.Show();
        wait_ms(1000);
        FechaRespuesta[9]=Slave.Recibe();
        FechaRespuesta[9]=Slave.Recibe();
        FechaRespuesta[8]=Slave.Recibe();
        FechaRespuesta[7]=Slave.Recibe();
        FechaRespuesta[6]=Slave.Recibe();
        FechaRespuesta[5]=Slave.Recibe();
        FechaRespuesta[4]=Slave.Recibe();
        FechaRespuesta[3]=Slave.Recibe();
        FechaRespuesta[2]=Slave.Recibe();
        FechaRespuesta[1]=Slave.Recibe();
        FechaRespuesta[0]=Slave.Recibe();
        HoraRespuesta[4]=Slave.Recibe();
        HoraRespuesta[4]=Slave.Recibe();
        HoraRespuesta[3]=Slave.Recibe();
        HoraRespuesta[2]=Slave.Recibe();
        HoraRespuesta[1]=Slave.Recibe();
        HoraRespuesta[0]=Slave.Recibe();
        NumeroRespuesta[5]=Slave.Recibe();
        NumeroRespuesta[5]=Slave.Recibe();
        NumeroRespuesta[4]=Slave.Recibe();
        NumeroRespuesta[3]=Slave.Recibe();
        NumeroRespuesta[2]=Slave.Recibe();
        NumeroRespuesta[1]=Slave.Recibe();
        NumeroRespuesta[0]=Slave.Recibe();
        Inicio=BaseClock.read_ms();
        while(true) {
            InByte=Slave.Recibe();
            if(InByte==NO_DATA) {
                break;
            }
            Fin=BaseClock.read_ms();
            Transcurrido=Fin-Inicio;
            if(Transcurrido>100) {
                break;
            }
        }
        Computer.printf("<%s> <%s> <%s>\n",FechaRespuesta,HoraRespuesta,NumeroRespuesta);
        return Salida;
    } else {
        Screen.PutString(15,12,"Operacion");
        Screen.PutString(15,34,"Rechazada");
        Screen.PutChar(84,11,'!');
        Screen.Limits();
        Screen.Show();
        wait_ms(3000);
        return USER_FINISH;
    }
}

void CalculoHoraFinal()
{

    int MinutoEstacionamiento=TiempoMinutos%60;
    int HoraEstacionamiento=TiempoMinutos/60;

    int HoraServicio=((uint8_t)HoraRespuesta[0]-48)*10+((uint8_t)HoraRespuesta[1]-48);
    int MinutoServicio=((uint8_t)HoraRespuesta[3]-48)*10+((uint8_t)HoraRespuesta[4]-48);

    if(HoraServicio<8){
        HoraServicio=8;
        MinutoServicio=0;
    }
    
    int MinutosTotal = MinutoServicio + MinutoEstacionamiento;
    int HorasTotal = HoraServicio + HoraEstacionamiento;

    while(MinutosTotal >= 60) {
        MinutosTotal = MinutosTotal - 60;
        HorasTotal = HorasTotal + 1;
    }
    if(HorasTotal>=24) {
        HorasTotal=HorasTotal-24;
    }

    if(MinutosTotal<10) {                             // Calcular tiempo en horas y minutos
        sprintf(HoraFinal,"%i:0%i",HorasTotal,MinutosTotal);
    } else {
        sprintf(HoraFinal,"%i:%i",HorasTotal,MinutosTotal);
    }

}

uint8_t Imprimir(uint8_t Salida)
{
    int PrinterState;
    PrinterState = Impresora.Power(1);
    Screen.PutString(15,12,"Imprimiendo");
    Screen.PutString(15,34,"Tiquete");
    Screen.Limits();
    Screen.Show();

    CalculoHoraFinal();
    if(PrinterState){
        PrinterState=Impresora.Reset();
    }

    if(PrinterState==0) {
        Screen.Limits();
        Screen.PutString(15,12,"Operacion aceptada");
        Screen.PutChar(84,11,'!');
        Screen.PutString(15,34,"Tiquete no disponible");
        Screen.Limits();
        Screen.Show();
        wait(2);
        Computer.printf("Error.\n");
        Impresora.End();
        AlarmasCall(2,1);
        wait(4);
    }
    if(PrinterState==2) {
        Screen.Limits();
        Screen.PutString(15,12,"Operacion aceptada");
        Screen.PutChar(84,11,'!');
        Screen.PutString(15,34,"Tiquete no disponible");
        Screen.Limits();
        Screen.Show();
        wait(2);
        Computer.printf("Error.\n");
        Impresora.End();
        AlarmasCall(2,1);
        wait(4);
    }
    if(PrinterState==1) {
        
        PrinterState=Impresora.Output(FechaRespuesta,HoraRespuesta,HoraFinal,Espacio,Tiempo,NumeroRespuesta,Importe);
        if(PrinterState==0) {
            Computer.printf("Alarma Output\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        PrinterState=Impresora.Paper(450);
        if(PrinterState==0) {
            Computer.printf("Alarma Papel\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        PrinterState=Impresora.Cutter(1);
        if(PrinterState==0) {
            Computer.printf("Alarma Cutter\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        Screen.PutString(15,12,"Retire");
        Screen.PutString(15,34,"Tiquete");
        Screen.Limits();
        Screen.Show();
        wait(1);
        
        PrinterState=Impresora.End();
        if(PrinterState==0) {
            Computer.printf("Alarma Cutter\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        } 
        wait(1);       
    }

    PrinterState=Impresora.Power(0);
    int TiquetesDisponibles=Papel-Impresora.Ticket(1);
    if(TiquetesDisponibles<200) {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,1);
    } else {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,0);
    }
    return Salida;
}


void Usuario_OperacionConsecutiva()
{
    uint8_t Comando=USER_INIT;
    if(Comando==USER_INIT) {
        Computer.printf("Usuario operacion consecutiva\n");
        Screen.On(HoraHostingPantalla);
        wait_ms(20);
        Screen.Init();
        Screen.Clean();
        BaseClock.reset();
        Comando=USER_PLACE;
    }

    if(Comando==USER_PLACE) {
        Computer.printf("Usuario espacio\n");
        CardReaderPower=1;
        Comando=GetPlace(USER_CARD,15000);
        if(Comando==USER_CARD) {
            Slave.Command(COMMAND_INIT);
        }
    }

    if(Comando==USER_CARD) {
        Computer.printf("Usuario tarjeta\n");
        Comando=GetCard(USER_TIME,20000,5000);
        if(Comando==USER_TIME) {
            Slave.Command(COMMAND_GPRS);
        }
    }

    if(Comando==USER_TIME) {
        Computer.printf("Usuario tiempo\n");
        CardReaderPower=0;
        Comando=GetTime(USER_DATA,15000);
        if (Comando==USER_FINISH){
            Slave.Command(COMMAND_END);
        }
        Comando=Continuar(Comando,7000);
    }

    if(Comando==USER_DATA) {
        Computer.printf("Usuario datos\n");
        Slave.Command(COMMAND_DATA);
        Slave.Send_User(Parquimetro,Municipio,TiempoMinutos,Espacio,Track2);
        Comando=Continuar(USER_POST,20000);
    }

    if(Comando==USER_POST) {
        Computer.printf("Usuario operacion\n");
        Slave.Command(COMMAND_POST);
        Comando=Respuesta1(USER_ANSWER,3000);
    }

    if(Comando==USER_ANSWER) {
        Computer.printf("Usuario respuesta\n");
        Slave.Command(COMMAND_ANSWER);
        Comando=Respuesta2(USER_PRINT,50000);
    }

    if(Comando==USER_PRINT) {
        Computer.printf("Usuario imprimiendo\n");
        Comando=Imprimir(USER_FINISH);
    }

    if(Comando==USER_FINISH) {
        Computer.printf("Usuario finalizar\n");
        Comando=Impresora.End();
        Screen.Clean();
        CardReaderPower=0;
        Impresora.Power(0);
        Screen.Off();
    }
}

void Usuario(uint8_t Entrada)
{
    uint8_t Comando=Entrada;
    if(Comando==USER_INIT) {
        Computer.printf("Usuario iniciar\n");
        Screen.On(HoraHostingPantalla);
        wait_ms(20);
        Screen.Init();
        Slave.Awake();
        Slave.Command(COMMAND_ON);
        //PantallaInicio();
        BaseClock.start();
        BaseClock.reset();
        Comando=USER_PLACE;
    }

    if(Comando==USER_INIT2) {
        Computer.printf("Usuario iniciar\n");
        BaseClock.start();
        BaseClock.reset();
        Comando=USER_PLACE;
    }
    
    if(Comando==USER_INIT3) {
        Computer.printf("Usuario iniciar\n");
        BaseClock.start();
        BaseClock.reset();
        Computer.printf("Usuario espacio\n");
        CardReaderPower=1;
        Comando=GetPlace(USER_CARD,15000);
    }
    
    if(Comando==USER_INIT4) {
        Computer.printf("Usuario iniciar\n");
        BaseClock.start();
        BaseClock.reset();
        Computer.printf("Usuario espacio\n");
        CardReaderPower=1;
        Comando=GetPlace(USER_CARD2,15000);
    }
    
    
    if(Comando==USER_INIT5) {
        Computer.printf("Usuario iniciar\n");
        BaseClock.start();
        BaseClock.reset();
        Computer.printf("Usuario espacio\n");
        CardReaderPower=1;
        Comando=GetPlace(USER_CARD2,15000);
        if(Comando==USER_CARD2) {
            Slave.Command(HOSTING_OFF);
        }
    }

    if(Comando==USER_PLACE) {
        Computer.printf("Usuario espacio\n");
        CardReaderPower=1;
        Comando=GetPlace(USER_CARD,15000);        
        if(Comando==USER_CARD) {
            Slave.Command(COMMAND_INIT);
        }
    }
    
    if(Comando==USER_CARD2) {
        Computer.printf("Usuario tarjetA 2\n");
        Comando=GetCard(USER_TIME,20000,5000);
    }

    if(Comando==USER_CARD) {
        Computer.printf("Usuario tarjeta\n");
        Comando=GetCard(USER_TIME,20000,5000);
        if(Comando==USER_TIME) {
            Slave.Command(COMMAND_GPRS);
        }
    }

    if(Comando==USER_TIME) {
        Computer.printf("Usuario tiempo\n");
        CardReaderPower=0;
        Comando=GetTime(USER_DATA,15000);
        if (Comando==USER_FINISH){
            Slave.Command(COMMAND_END);
        }
        Comando=Continuar(Comando,7000);
    }

    if(Comando==USER_DATA) {
        Computer.printf("Usuario datos\n");
        Slave.Command(COMMAND_DATA);
        Slave.Send_User(Parquimetro,Municipio,TiempoMinutos,Espacio,Track2);
        Computer.printf("Tiempo: -%i-\n",TiempoMinutos);
        Computer.printf("Parquimetro: -%s-\n",Parquimetro);
        Computer.printf("Municipio: -%s-\n",Municipio);
        Computer.printf("Espacio: -%s-\n",Espacio);
        Computer.printf("Tiempo: -%s-\n",Track2);
        Computer.printf("-%s-%s-%i-%s-%s-",Parquimetro,Municipio,TiempoMinutos,Espacio,Track2);
        Comando=Continuar(USER_POST,20000);
        if (Comando==USER_FINISH){
            Slave.Command(COMMAND_END);
        }
        
    }

    if(Comando==USER_POST) {
        Computer.printf("Usuario operacion\n");
        Slave.Command(COMMAND_POST);
        Comando=Respuesta1(USER_ANSWER,3000);
    }

    if(Comando==USER_ANSWER) {
        Computer.printf("Usuario respuesta\n");
        Slave.Command(COMMAND_ANSWER);
        Comando=Respuesta2(USER_PRINT,50000);
    }

    if(Comando==USER_PRINT) {
        Computer.printf("Usuario imprimiendo\n");
        Comando=Imprimir(USER_FINISH);
    }

    if(Comando==USER_FINISH) {
        Computer.printf("Usuario finalizar\n");
        Comando=Impresora.End();
        Screen.Clean();
        CardReaderPower=0;
        Impresora.Power(0);
        Screen.Off();
        Inicio=BaseClock.read_ms();
        Keypad_Init();
        while(true) {
            Fin=BaseClock.read_ms();
            Transcurrido=Fin-Inicio;
            if(Transcurrido>10000) {
                break;
            }
            Tecla=KeyPad_Read();
            if (Tecla!=NO_KEY) {
                Usuario_OperacionConsecutiva();
                Inicio=BaseClock.read_ms();
            }
        }
        Slave.Command(COMMAND_OFF);
    }
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------

void Interrupt_Mantenimiento()
{
    MantenimientoInterruption=1;
}

void M_PantallaConfiguracion()
{
    Computer.printf("Pantala modo configuracion\n");

    Screen.Limits();
    Screen.PutString(35,19,"Modo Configuracion");
    Screen.Show();
    wait_ms(1000);
}

uint8_t M_MenuConfiguracion(uint32_t Delay)
{

    int Selection=1;
    uint8_t Salida=M_SISTEMA;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.PutString(15,4,"Sistema");
    Screen.PutString(15,23,"Red");
    Screen.PutString(15,42,"Impresora");
    Screen.PutString(135,4,"Teclado");
    Screen.PutString(135,23,"Lectora");
    Screen.PutString(135,42,"Informacion");
    Screen.Show();

    Computer.printf("Sistema\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                     //Subir puntero
                Selection++;
                if(Selection==7) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                      //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=6;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Sistema\n");
                    Salida=M_SISTEMA;
                    break;
                case 2:
                    SelectionBox[0]=4;
                    SelectionBox[1]=26;
                    Computer.printf("Red\n");
                    Salida=M_RED;
                    break;
                case 3:
                    SelectionBox[0]=4;
                    SelectionBox[1]=45;
                    Computer.printf("Impresora\n");
                    Salida=M_IMPRESORA;
                    break;
                case 4:
                    SelectionBox[0]=124;
                    SelectionBox[1]=7;
                    Computer.printf("Teclado\n");
                    Salida=M_TECLADO;
                    break;
                case 5:
                    SelectionBox[0]=124;
                    SelectionBox[1]=26;
                    Computer.printf("Lectora\n");
                    Salida=M_LECTORA;
                    break;
                case 6:
                    SelectionBox[0]=124;
                    SelectionBox[1]=45;
                    Computer.printf("Informacion\n");
                    Salida=M_INFORMACION;
                    break;
            }

            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.PutString(15,4,"Sistema");
            Screen.PutString(15,23,"Red");
            Screen.PutString(15,42,"Impresora");
            Screen.PutString(135,4,"Teclado");
            Screen.PutString(135,23,"Lectora");
            Screen.PutString(135,42,"Informacion");
            Screen.Show();
        }
    }
}

uint8_t M_MenuSistema(uint32_t Delay)
{

    uint8_t Salida=M_PARQUIMETRO;
    int Selection=1;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    bool Atras;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.PutString(15,4,"Id Parquimetro");
    Screen.PutString(15,23,"Id Municipalidad");
    Screen.PutString(15,42,"Precio 10 mins");
    Screen.Show();
    Computer.printf("Id parquimetro\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                       //Subir puntero
                Selection++;
                if(Selection==4) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                        //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=3;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return M_ATRAS;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Id Parquimetro\n");
                    Salida=M_PARQUIMETRO;
                    break;
                case 2:
                    SelectionBox[0]=4;
                    SelectionBox[1]=26;
                    Computer.printf("Id Municipalidad\n");
                    Salida=M_MUNICIPIO;
                    break;
                case 3:
                    SelectionBox[0]=4;
                    SelectionBox[1]=45;
                    Computer.printf("Precio 10mins\n");
                    Salida=M_PRECIO;
                    break;
            }
            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.PutString(15,4,"Id Parquimetro");
            Screen.PutString(15,23,"Id Municipalidad");
            Screen.PutString(15,42,"Precio 10 mins");
            Screen.Show();
        }
    }
}

uint8_t M_MenuConexion(uint32_t Delay)
{
    uint8_t Salida=M_SENAL;
    int Selection=1;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    bool Atras;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.Rectangle(129,6,5,0);
    Screen.PutString(15,4,"Intensidad senal");
    Screen.PutString(15,23,"Prueba hosting");
    Screen.PutString(15,42,"Conexion red");
    Screen.Show();

    Computer.printf("Intensidad senal\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                    //Subir puntero
                Selection++;
                if(Selection==4) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                     //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=3;
                }
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return M_ATRAS;
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Intensidad senal\n");
                    Salida=M_SENAL;
                    break;
                case 2:
                    SelectionBox[0]=4;
                    SelectionBox[1]=26;
                    Computer.printf("Prueba hosting\n");
                    Salida=M_HOSTING;
                    break;
                case 3:
                    SelectionBox[0]=4;
                    SelectionBox[1]=45;
                    Computer.printf("Conexion red\n");
                    Salida=M_CONEXION_SIM ;
                    break;
            }
            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.Rectangle(129,6,5,0);
            Screen.PutString(15,4,"Intensidad senal");
            Screen.PutString(15,23,"Prueba hosting");
            Screen.PutString(15,42,"Conexion red");
            Screen.Show();
        }
    }
}

uint8_t M_MenuImpresora(uint32_t Delay)
{
    uint8_t Salida=M_PAPEL;
    int Selection=1;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    bool Atras;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.PutString(15,4,"Cambio de papel");
    Screen.PutString(15,23,"Tiquete de prueba");
    Screen.PutString(15,42,"Conexion impresora");
    Screen.Show();

    Computer.printf("Cambio de papel\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                    //Subir puntero
                Selection++;
                if(Selection==4) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                     //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=3;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return M_ATRAS;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Cambio de papel\n");
                    Salida=M_PAPEL;
                    break;
                case 2:
                    SelectionBox[0]=4;
                    SelectionBox[1]=26;
                    Computer.printf("Tiquete de prueba\n");
                    Salida=M_IMPRESION;
                    break;
                case 3:
                    SelectionBox[0]=4;
                    SelectionBox[1]=45;
                    Computer.printf("Conexion impresora\n");
                    Salida=M_CONEXION_IMP;
                    break;
            }
            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.PutString(15,4,"Cambio de papel");
            Screen.PutString(15,23,"Tiquete de prueba");
            Screen.PutString(15,42,"Conexion impresora");
            Screen.Show();
        }
    }
}

uint8_t M_MenuLectora(uint32_t Delay)
{
    uint8_t Salida=M_LECTURA;
    int Selection=1;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    bool Atras;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.PutString(15,4,"Prueba de lectura");
    Screen.PutString(15,23,"Conexion lectora");
    Screen.Show();

    Computer.printf("Prueba de lectura\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                    //Subir puntero
                Selection++;
                if(Selection==3) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                     //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=2;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return M_ATRAS;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Prueba de lectura\n");
                    Salida=M_LECTURA;
                    break;
                case 2:
                    SelectionBox[0]=4;
                    SelectionBox[1]=26;
                    Computer.printf("Conexion lectora\n");
                    Salida=M_CONEXION_LEC;
                    break;
            }

            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.PutString(15,4,"Prueba de lectura");
            Screen.PutString(15,23,"Conexion lectora");
            Screen.Show();
        }
    }
}

uint8_t M_MenuTeclado(long Delay)
{
    uint8_t Salida=M_PRUEBA_TECLA;
    int Selection=1;
    int SelectionBox[2]= {4,7};
    bool Arriba;
    bool Abajo;
    bool Finalizar;
    bool Salir;
    bool Atras;
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
    Screen.PutString(15,4,"Prueba de teclado");
    Screen.Show();
    Computer.printf("Prueba de teclado\n");

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>Delay) {
            return M_OFF;
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Arriba=(Tecla=='F');
            if (Arriba) {                    //Subir puntero
                Selection++;
                if(Selection==2) {
                    Selection=1;
                }
            }
            Abajo=(Tecla=='E');
            if (Abajo) {                     //Bajar puntero
                Selection--;
                if(Selection==0) {
                    Selection=1;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return M_OFF;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return M_ATRAS;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                return Salida;
            }
            switch (Selection) {
                case 1:
                    SelectionBox[0]=4;
                    SelectionBox[1]=7;
                    Computer.printf("Prueba de teclado\n");
                    Salida=M_PRUEBA_TECLA;
                    break;
            }
            Screen.Limits();
            Screen.Rectangle(SelectionBox[0],SelectionBox[1],8,8);
            Screen.PutString(15,4,"Prueba de teclado");
            Screen.Show();
        }
    }
}

uint8_t M_MenuInformacion()
{
    return M_INFORMACION;
}

void M_Parquimetro(uint32_t TimeOut)
{
    char ID_Actual[5];   //Lectura de valor en memoria
    sprintf(ID_Actual,"%s",Parquimetro);
    int SelectionLine1[4]= {99,32,9,0};
    int SelectionLine2[4]= {99,50,9,0};
    int Line=1;
    bool Numero;
    bool Arriba;
    bool Abajo;
    bool Salir;
    bool Atras;
    bool Finalizar;

    Inicio=BaseClock.read_ms();

    Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
    Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
    Screen.PutString(15,12,"Id Parquimetro");
    Screen.PutChar(100,34,ID_Actual[0]);
    Screen.PutChar(110,34,ID_Actual[1]);
    Screen.PutChar(120,34,ID_Actual[2]);
    Screen.PutChar(130,34,ID_Actual[3]);
    Screen.Limits();
    Screen.Show();
    Computer.printf("Id Parquimetro\n");
    Computer.printf("%s\n",ID_Actual);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            break;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if (Numero) {                     //Cambiar numero
                if((Tecla=='0')&&(Line==1)) {
                    ID_Actual[Line-1]='1';
                } else {
                    ID_Actual[Line-1]=Tecla;
                }
                Line++;
                if(Line==5) {
                    Line=1;
                }
                if(Line==0) {
                    Line=4;
                }
            }
            Arriba=(Tecla=='E');
            if (Arriba) {                    //Subir puntero
                Line++;
                if(Line==5) {
                    Line=1;
                }
            }
            Abajo=(Tecla=='F');
            if (Abajo) {                     //Bajar puntero
                Line--;
                if(Line==0) {
                    Line=4;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                break;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                break;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                sprintf(Parquimetro,"%s",ID_Actual);
                break;
            }
            switch (Line) {
                case 1:
                    SelectionLine1[0]=99;
                    SelectionLine2[0]=99;
                    break;
                case 2:
                    SelectionLine1[0]=109;
                    SelectionLine2[0]=109;
                    break;
                case 3:
                    SelectionLine1[0]=119;
                    SelectionLine2[0]=119;
                    break;
                case 4:
                    SelectionLine1[0]=129;
                    SelectionLine2[0]=129;
                    break;
            }
            //-------Mostrar en Patalla-------
            Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
            Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
            Screen.PutString(15,12,"Id Parquimetro");
            Screen.PutChar(100,34,ID_Actual[0]);
            Screen.PutChar(110,34,ID_Actual[1]);
            Screen.PutChar(120,34,ID_Actual[2]);
            Screen.PutChar(130,34,ID_Actual[3]);
            Screen.Limits();
            Screen.Show();
            Computer.printf("%s\n",ID_Actual);
        }
    }
}

void M_Municipio(uint32_t TimeOut)
{
    char CodigoMunicipio_Actual[3];   //Lectura de valor en memoria
    sprintf(CodigoMunicipio_Actual,"%s",CodigoMunicipio);

    int SelectionLine1[4]= {109,32,9,0};
    int SelectionLine2[4]= {109,50,9,0};
    int Line=1;
    bool Numero;
    bool Arriba;
    bool Abajo;
    bool Salir;
    bool Atras;
    bool Finalizar;

    Inicio=BaseClock.read_ms();

    Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
    Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
    Screen.PutString(15,12,"Id Municipalidad");
    Screen.PutChar(110,34,CodigoMunicipio_Actual[0]);
    Screen.PutChar(120,34,CodigoMunicipio_Actual[1]);
    Screen.Limits();
    Screen.Show();
    Computer.printf("Id Municipalidad\n");
    Computer.printf("%s\n",CodigoMunicipio_Actual);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            break;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if (Numero) {                     //Cambiar numero
                CodigoMunicipio_Actual[Line-1]=Tecla;
                Line++;
                if(Line==3) {
                    Line=1;
                }
                if(Line==0) {
                    Line=2;
                }
            }
            Arriba=(Tecla=='E');
            if (Arriba) {                    //Subir puntero
                Line++;
                if(Line==3) {
                    Line=1;
                }
            }
            Abajo=(Tecla=='F');
            if (Abajo) {                     //Bajar puntero
                Line--;
                if(Line==0) {
                    Line=2;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                break;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                break;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                sprintf(CodigoMunicipio,"%s",CodigoMunicipio_Actual);
                if((CodigoMunicipio[0]=='0')&&(CodigoMunicipio[1]=='1')) {
                    sprintf(Municipio,"San Jose");
                    Computer.printf("San Jose\n");
                }
                if((CodigoMunicipio[0]=='0')&&(CodigoMunicipio[1]=='2')) {
                    sprintf(Municipio,"Tibas");
                    Computer.printf("Tibas\n");
                }
                break;
            }
            switch (Line) {
                case 1:
                    SelectionLine1[0]=109;
                    SelectionLine2[0]=109;
                    break;
                case 2:
                    SelectionLine1[0]=119;
                    SelectionLine2[0]=119;
                    break;
            }
            //-------Mostrar en Patalla-------
            Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
            Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
            Screen.PutString(15,12,"Id Municipalidad");
            Screen.PutChar(110,34,CodigoMunicipio_Actual[0]);
            Screen.PutChar(120,34,CodigoMunicipio_Actual[1]);
            Screen.Limits();
            Screen.Show();
            Computer.printf("%s\n",CodigoMunicipio_Actual);
        }
    }
}

void M_Precio(uint32_t TimeOut)
{
    char Precio_Actual[5];   //Lectura de valor en memoria
    if(Precio>999) {
        sprintf(Precio_Actual,"%i",Precio);
    }
    if(Precio<1000) {
        sprintf(Precio_Actual,"0%i",Precio);
    }
    if(Precio<100) {
        sprintf(Precio_Actual,"00%i",Precio);
    }
    if(Precio<10) {
        sprintf(Precio_Actual,"000%i",Precio);
    }

    int SelectionLine1[4]= {99,32,9,0};
    int SelectionLine2[4]= {99,50,9,0};
    int Line=1;
    bool Numero;
    bool Arriba;
    bool Abajo;
    bool Salir;
    bool Atras;
    bool Finalizar;
    Inicio=BaseClock.read_ms();

    Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
    Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
    Screen.PutString(15,12,"Precio establecido");
    Screen.PutChar(100,34,Precio_Actual[0]);
    Screen.PutChar(110,34,Precio_Actual[1]);
    Screen.PutChar(120,34,Precio_Actual[2]);
    Screen.PutChar(130,34,Precio_Actual[3]);
    Screen.PutChar(140,34,'*');
    Screen.Limits();
    Screen.Show();
    Computer.printf("Precio establecido\n");
    Computer.printf("%s\n",Precio_Actual);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            break;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if (Numero) {                     //Cambiar numero
                Precio_Actual[Line-1]=Tecla;
                Line++;
                if(Line==5) {
                    Line=1;
                }
                if(Line==0) {
                    Line=4;
                }
            }
            Arriba=(Tecla=='E');
            if (Arriba) {                    //Subir puntero
                Line++;
                if(Line==5) {
                    Line=1;
                }
            }
            Abajo=(Tecla=='F');
            if (Abajo) {                     //Bajar puntero
                Line--;
                if(Line==0) {
                    Line=4;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                break;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                break;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                Precio=((uint8_t)Precio_Actual[0]-48)*1000+((uint8_t)Precio_Actual[1]-48)*100+((uint8_t)Precio_Actual[2]-48)*10+((uint8_t)Precio_Actual[3]-48);
                break;
            }
            switch (Line) {
                case 1:
                    SelectionLine1[0]=99;
                    SelectionLine2[0]=99;
                    break;
                case 2:
                    SelectionLine1[0]=109;
                    SelectionLine2[0]=109;
                    break;
                case 3:
                    SelectionLine1[0]=119;
                    SelectionLine2[0]=119;
                    break;
                case 4:
                    SelectionLine1[0]=129;
                    SelectionLine2[0]=129;
                    break;
            }
            //-------Mostrar en Patalla-------
            Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
            Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
            Screen.PutString(15,12,"Precio establecido");
            Screen.PutChar(100,34,Precio_Actual[0]);
            Screen.PutChar(110,34,Precio_Actual[1]);
            Screen.PutChar(120,34,Precio_Actual[2]);
            Screen.PutChar(130,34,Precio_Actual[3]);
            Screen.PutChar(140,34,'*');
            Screen.Limits();
            Screen.Show();
            Computer.printf("%s\n",Precio_Actual);
        }
    }
}

void M_IntensidadSenal()
{
    char Senal[]="000";
    Slave.Command(COMMAND_SIGNAL);
    Screen.Rectangle(129,14,5,0);
    Screen.PutString(15,12,"Intensidad senal");
    Screen.PutString(15,34,"Conectando...");
    Screen.Limits();
    Screen.Show();
    Computer.printf("Conectando...\n");
    wait(3);

    Inicio=BaseClock.read_ms();
    while(true) {
        if(Slave.Available()) {
            Computer.putc('A');
            wait_ms(200);
            break;
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>20000) {
            Computer.putc('E');
            break;
        }
    }
    InByte=Slave.Recibe();
    if(InByte=='A') {
        Senal[2]=Slave.Recibe();
        Senal[1]=Slave.Recibe();
        Senal[0]=Slave.Recibe();
        Screen.Rectangle(129,14,5,0);
        Screen.PutString(15,12,"Intensidad senal");
        Screen.PutString(15,34,"CSQ:");
        Screen.PutChar(70,34,Senal[0]);
        Screen.PutChar(80,34,Senal[1]);
        Screen.PutChar(92,34,'.');
        Screen.PutChar(96,34,Senal[2]);
        Screen.Limits();
        Screen.Show();
        Computer.printf("CSQ: %s\n",Senal);
        wait(3);
    } else {
        Screen.Rectangle(129,14,5,0);
        Screen.PutString(15,12,"Intensidad senal");
        Screen.PutString(15,34,"Error.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Error\n");
        wait(3);
    }
}
void M_ConexionSim900()
{
    Screen.PutString(15,12,"Conexion red");
    Screen.PutString(15,34,"Conetando...");
    Screen.Limits();
    Screen.Show();
    Computer.printf("Conectando...\n");

    Slave.Command(COMMAND_CONNECT);
    while(true) {
        if(Slave.Available()) {
            wait_ms(200);
            break;
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>20000) {
            Computer.putc('E');
            break;
        }
    }
    InByte=Slave.Recibe();
    if(InByte=='A') {
        Screen.PutString(15,12,"Conexion red");
        Screen.PutString(15,34,"Conectado.");
        Screen.Limits();
        Screen.Show();
        wait(3);
    } else {
        Screen.PutString(15,12,"Conexion red");
        Screen.PutString(15,34,"Error.");
        Screen.Limits();
        Screen.Show();
        wait(3);
    }
}

void M_PruebaTiquete()
{
    Screen.PutString(15,12,"Tiquete de prueba");
    Screen.PutString(15,34,"Conectando...");
    Screen.Limits();
    Screen.Show();
    wait(1);
    Computer.printf("Conectando...\n");

    Impresora.Power(1);
    wait_ms(1000);
    Comando=Impresora.Reset();

    if(Comando==2) {
        Screen.PutString(15,12,"Tiquete de prueba");
        Screen.PutString(15,34,"Error.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Error\n");

        Impresora.End();
        AlarmasCall(2,1);
        wait(3);
    }
    if(Comando==1) {
        Screen.PutString(15,12,"Tiquete de prueba");
        Screen.PutString(15,34,"Imprimiendo...");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Imprimiendo...\n");

        Comando=Impresora.Output(FechaRespuesta,"00:00","00:00","0000","00:00","000000","0000*");
        if(Comando==0) {
            Computer.printf("Alarma Output\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        Comando=Impresora.Paper(600);
        if(Comando==0) {
            Computer.printf("Alarma Papel\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        Comando=Impresora.Cutter(1);
        if(Comando==0) {
            Computer.printf("Alarma Cutter\n");
            AlarmasCall(2,1);
        } else {
            AlarmasCall(2,0);
        }

        Screen.PutString(15,12,"Tiquete de prueba");
        Screen.PutString(15,34,"Retire.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Retire\n");
        wait(1);
        Comando=Impresora.End();
        wait(2);
    }
    if(Comando==0) {
        Screen.PutString(15,12,"Tiquete de prueba");
        Screen.PutString(15,34,"Error.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Error\n");
        Comando=Impresora.End();
        AlarmasCall(2,1);
        wait(3);
    }
    Impresora.Power(0);

    int TiquetesDisponibles=Papel-Impresora.Ticket(1);
    if(TiquetesDisponibles<200) {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,1);
    } else {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,0);
    }
}

void M_ConexionImpresora()
{
    Screen.PutString(15,12,"Conexion impresora");
    Screen.PutString(15,34,"Conectando...");
    Screen.Limits();
    Screen.Show();
    Computer.printf("Conectando...\n");

    Impresora.Power(1);
    wait_ms(1000);
    Comando=Impresora.Reset();

    if(Comando==2) {
        Screen.PutString(15,12,"Conexion impresora");
        Screen.PutString(15,34,"Desconectada.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Desconectada\n");
        Impresora.End();
        AlarmasCall(2,1);
        wait(3);
    }
    if(Comando==1) {
        Screen.PutString(15,12,"Conexion impresora");
        Screen.PutString(15,34,"Conectada.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Conectada\n");
        Comando=Impresora.End();
        AlarmasCall(2,0);
        wait(3);
    }
    if(Comando==0) {
        Screen.PutString(15,12,"Conexion impresora");
        Screen.PutString(15,34,"Conectada error.");
        Screen.Limits();
        Screen.Show();
        Computer.printf("Error\n");
        Comando=Impresora.End();
        AlarmasCall(2,1);
        wait(3);
    }
    Impresora.Power(0);
}

void M_CambioPapel(uint32_t TimeOut)
{
    char Papel_Actual[5];   //Lectura de valor en memoria
    if(Papel>999) {
        sprintf(Papel_Actual,"%i",Papel);
    }
    if(Papel<1000) {
        sprintf(Papel_Actual,"0%i",Papel);
    }
    if(Papel<100) {
        sprintf(Papel_Actual,"00%i",Papel);
    }
    if(Papel<10) {
        sprintf(Papel_Actual,"000%i",Papel);
    }

    int SelectionLine1[4]= {99,32,9,0};
    int SelectionLine2[4]= {99,50,9,0};
    int Line=1;
    bool Numero;
    bool Arriba;
    bool Abajo;
    bool Salir;
    bool Atras;
    bool Finalizar;

    Inicio=BaseClock.read_ms();

    Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
    Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
    Screen.PutString(15,12,"Cambio de papel");
    Screen.PutChar(100,34,Papel_Actual[0]);
    Screen.PutChar(110,34,Papel_Actual[1]);
    Screen.PutChar(120,34,Papel_Actual[2]);
    Screen.PutChar(130,34,Papel_Actual[3]);
    Screen.Limits();
    Screen.Show();
    Computer.printf("Cambio de papel\n");
    Computer.printf("%s\n",Papel_Actual);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            break;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if (Numero) {                     //Cambiar numero
                Papel_Actual[Line-1]=Tecla;
                Line++;
                if(Line==5) {
                    Line=1;
                }
                if(Line==0) {
                    Line=4;
                }
            }
            Arriba=(Tecla=='E');
            if (Arriba) {                    //Subir puntero
                Line++;
                if(Line==5) {
                    Line=1;
                }
            }
            Abajo=(Tecla=='F');
            if (Abajo) {                     //Bajar puntero
                Line--;
                if(Line==0) {
                    Line=4;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                break;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                break;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                Papel=((uint8_t)Papel_Actual[0]-48)*1000+((uint8_t)Papel_Actual[1]-48)*100+((uint8_t)Papel_Actual[2]-48)*10+((uint8_t)Papel_Actual[3]-48);
                int TiquetesDisponibles=Papel-Impresora.Ticket(1);
                if(TiquetesDisponibles<200) {
                    sprintf(PapelDisponible,"%i",TiquetesDisponibles);
                    AlarmasCall(3,1);
                } else {
                    sprintf(PapelDisponible,"%i",TiquetesDisponibles);
                    AlarmasCall(3,0);
                }
                break;
            }
            switch (Line) {
                case 1:
                    SelectionLine1[0]=99;
                    SelectionLine2[0]=99;
                    break;
                case 2:
                    SelectionLine1[0]=109;
                    SelectionLine2[0]=109;
                    break;
                case 3:
                    SelectionLine1[0]=119;
                    SelectionLine2[0]=119;
                    break;
                case 4:
                    SelectionLine1[0]=129;
                    SelectionLine2[0]=129;
                    break;
            }
            //-------Mostrar en Patalla-------
            Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
            Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
            Screen.PutString(15,12,"Cambio de papel");
            Screen.PutChar(100,34,Papel_Actual[0]);
            Screen.PutChar(110,34,Papel_Actual[1]);
            Screen.PutChar(120,34,Papel_Actual[2]);
            Screen.PutChar(130,34,Papel_Actual[3]);
            Screen.Limits();
            Screen.Show();
            Computer.printf("%s\n",Papel_Actual);
        }
    }
}
void M_PruebaTeclado(uint32_t TimeOut)
{
    bool Numero;
    int  Line=0;
    char Secuencia[16]= {'1','2','3','A','4','5','6','B','7','8','9','C','F','0','E','D'};
    char SecuenciaSelect[2];
    SecuenciaSelect[0]='1';
    SecuenciaSelect[1]='\0';
    Inicio=BaseClock.read_ms();

    Screen.Limits();
    Screen.PutString(15,12,"Prueba de teclado");
    Screen.PutString(15,34,">    <");
    Screen.PutString(33,34,SecuenciaSelect);
    Screen.Show();
    Computer.putc(SecuenciaSelect[0]);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            Screen.Limits();
            Screen.PutString(15,12,"Prueba de teclado");
            Screen.PutString(15,34,"Error.");
            Screen.Show();
            Computer.printf("\nError\n");
            wait(3);
        }
        Tecla = KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla==Secuencia[Line]);
            if (Numero) {                     //Cambiar numero
                Line++;
                SecuenciaSelect[0]=Secuencia[Line];
            }

            if (Line>15) {                     //Cambiar numero
                Screen.Limits();
                Screen.PutString(15,12,"Prueba de teclado");
                Screen.PutString(15,34,"Aprobada.");
                Screen.Show();
                Computer.printf("\nAprobada\n");
                wait(3);
                break;
            }

            Screen.Limits();
            Screen.PutString(15,12,"Prueba de teclado");
            Screen.PutString(15,34,">    <");
            Screen.PutString(33,34,SecuenciaSelect);
            Screen.Show();
            Computer.putc(SecuenciaSelect[0]);
        }
    }

}

void M_ConexionLectora()
{
    CardReaderPower=1;
    Screen.Limits();
    Screen.PutString(15,12,"Conexion lectora");
    Screen.PutString(15,34,"Conectando...");
    Screen.Show();
    Computer.printf("Conectando...\n");
    wait(2);
    CardReader_Counter=0;
    if(CardReader.writeable()) {
        CardReader.putc(SOH);           // 00000001
        CardReader.putc(ADDR);          // 00000000
        CardReader.putc(LEN);           // 00000000
        CardReader.putc(LEN);           // 00000000
        CardReader.putc(DEV_RESET);     // 01111111
        CardReader.putc(EOT);           // 00000100
        CardReader.putc(BBCI);          // 01111010
    }
    int RespuestaConexion;
    wait_ms(2000);
    if(CardReader_Counter>0) {
        for(int i=0; i<=CardReader_Counter; i++) {
            if(CardReader_Buffer[i]==R_START) {
                RespuestaConexion=1;
                AlarmasCall(1,0);
            }
            if(CardReader_Buffer[i]==R_INVALID) {
                RespuestaConexion=2;
                AlarmasCall(1,1);
            }
            if(CardReader_Buffer[i]==R_ERROR) {
                RespuestaConexion=2;
                AlarmasCall(1,1);
            }
            if(CardReader_Buffer[i]==R_COMAND_ERROR) {
                RespuestaConexion=2;
                AlarmasCall(1,1);
            }
        }
    } else {
        RespuestaConexion=0;
        AlarmasCall(1,1);
    }

    if(RespuestaConexion==0) {
        Screen.Limits();
        Screen.PutString(15,12,"Conexion lectora");
        Screen.PutString(15,34,"Desconectada.");
        Screen.Show();
        Computer.printf("Desconectada\n");
        wait(3);
    }
    if(RespuestaConexion==1) {
        Screen.Limits();
        Screen.PutString(15,12,"Conexion lectora");
        Screen.PutString(15,34,"Conectada.");
        Screen.Show();
        Computer.printf("Conectada\n");
        wait(3);
    }
    if(RespuestaConexion==2) {
        Screen.Limits();
        Screen.PutString(15,12,"Conexion lectora");
        Screen.PutString(15,34,"Conectada error.");
        Screen.Show();
        Computer.printf("Conectada error\n");
        wait(3);
    }
    CardReaderPower=0;
}

int M_RetiroTarjeta(uint32_t TiempoFuera)
{
    Computer.printf("Retiro tarjeta\n");
    Inicio=BaseClock.read_ms();
    while(true) {
        if(PositionCard()==0) {
            return 1;
        } else {
            Screen.Limits();                 // Se pide al usuario por pantalla el retiro de la tarjeta
            Screen.PutString(15,12,"Prueba de lectura");
            Screen.PutString(15,34,"Retire tarjeta.");
            Screen.Show();
        }
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TiempoFuera) {
            StateReader[1]='T';
            return 0;
        }
    }
}

void M_PruebaLectora()
{
    CardReaderPower=1;
    Screen.PutString(15,12,"Prueba de lectura");
    Screen.PutString(15,34,"Conectando...");
    Screen.Limits();                     // Se inicia el lector de tarjetas
    Screen.Show();
    wait(2);

    Screen.Limits();                     // Se pide al usuario por pantalla la intrduccion de la tarjeta
    Screen.PutString(15,12,"Prueba de lectura");
    Screen.PutString(15,34,"Introduzca tarjeta.");
    Screen.Show();

    if(ResetCard()) {
        while(true) {

            uint8_t RespuestaIngresoTarjeta = IngresoTarjeta(10000);
            if(RespuestaIngresoTarjeta==1) {
                Screen.Limits();
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"Retire tarjeta.");
                Screen.Show();
            }
            if(RespuestaIngresoTarjeta==0) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"Sin deteccion.");
                Screen.Limits();
                Screen.Show();
                wait(3);
                Screen.Clean();
                break;
            }
            if(RespuestaIngresoTarjeta==2) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"Error.");
                Screen.Limits();
                Screen.Show();
                wait(3);
                break;
            }

            uint8_t RespuestaReadCard=ReadCard(5000);
            if(RespuestaReadCard==2) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"Error.");
                Screen.Limits();
                Screen.Show();
                wait(3);
                break;
            }


            // Se le la tarjeta al retirarse
            int DataResult=RecibeDataCard();    // Se corrobora que la informacion de la tajeta es la corre
            if(DataResult==0) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"ilegible.");
                Screen.Limits();
                Screen.Show();
                wait(2);
                if(M_RetiroTarjeta(7000)) {
                    Screen.Limits();
                    Screen.PutString(15,12,"Prueba de lectura");
                    Screen.PutString(15,34,"Introduzca tarjeta");
                    Screen.Show();
                } else {
                    Screen.PutString(15,12,"Prueba de lectura");
                    Screen.PutString(15,34,"Error.");
                    Screen.Limits();
                    Screen.Show();
                    wait(3);
                    break;
                }
            }
            if(DataResult==1) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"Aprobada.");
                Screen.Limits();
                Screen.Show();
                Computer.printf("\nAprobada\n");
                wait(3);
                break;
            }
            if(DataResult==2) {
                Screen.PutString(15,12,"Prueba de lectura");
                Screen.PutString(15,34,"ilegible");
                Screen.Limits();
                Screen.Show();
                wait(2);
                if(M_RetiroTarjeta(7000)) {
                    Screen.Limits();
                    Screen.PutString(15,12,"Prueba de lectura");
                    Screen.PutString(15,34,"Introduzca tarjeta");
                    Screen.PutChar(26,33,'!');
                    Screen.PutChar(110,33,'!');
                    Screen.Show();
                } else {
                    Screen.PutString(15,12,"Prueba de lectura");
                    Screen.PutString(15,34,"Error.");
                    Screen.Limits();
                    Screen.Show();
                    wait(3);
                    break;
                }
            }
        }
    } else {
        Screen.PutString(15,12,"Prueba de lectura");
        Screen.PutString(15,34,"Error.");
        Screen.Limits();
        Screen.Show();
        wait(3);
    }
    CardReaderPower=0;    
}

void M_Informacion()
{
    int TiquetesDisponibles=Papel-Impresora.Ticket(1);
    if(TiquetesDisponibles<200) {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,1);
    } else {
        sprintf(PapelDisponible,"%i",TiquetesDisponibles);
        AlarmasCall(3,0);
    }

    Screen.PutString(15,4,"Transaccion:");
    Screen.PutString(129,4,FechaRespuesta);
    Screen.PutString(15,23,"Papel:");
    Screen.PutString(129,23,PapelDisponible);
    Screen.PutString(15,42,"Estado:");
    Screen.PutString(129,42,Alarmas);
    Screen.Limits();//AlarmasCall
    Screen.Show();
    wait(5);
}

bool M_ClaveIngreso(uint32_t TimeOut)
{
    char Clave_Actual[5]="))))";
    int SelectionLine1[4]= {99,32,8,0};
    int SelectionLine2[4]= {99,50,8,0};
    int Line=1;
    bool Numero;
    bool Arriba;
    bool Abajo;
    bool Salir;
    bool Atras;
    bool Finalizar;
    Inicio=BaseClock.read_ms();

    Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
    Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
    Screen.PutString(15,12,"Ingrese password");
    Screen.PutChar(100,34,Clave_Actual[0]);
    Screen.PutChar(110,34,Clave_Actual[1]);
    Screen.PutChar(120,34,Clave_Actual[2]);
    Screen.PutChar(130,34,Clave_Actual[3]);
    Screen.Limits();
    Screen.Show();
    Computer.printf("Ingrese password\n");
    Computer.printf("%s\n",Clave);

    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio;
        if(Transcurrido>TimeOut) {
            return 0;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) {                  // Se valida que se ingrese algo en el teclado
            Inicio=BaseClock.read_ms();

            Numero=(Tecla=='0')||(Tecla=='1')||(Tecla=='2')||(Tecla=='3')||(Tecla=='4')||(Tecla=='5')||(Tecla=='6')||(Tecla=='7')||(Tecla=='8')||(Tecla=='9');
            if (Numero) {                     //Cambiar numero
                Clave_Actual[Line-1]=Tecla;
                Line++;
                Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
                Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
                Screen.PutString(15,12,"Ingrese password");
                Screen.PutChar(100,34,Clave_Actual[0]);
                Screen.PutChar(111,34,Clave_Actual[1]);
                Screen.PutChar(122,34,Clave_Actual[2]);
                Screen.PutChar(133,34,Clave_Actual[3]);
                Screen.Limits();
                Screen.Show();
                if(Line==5) {
                    Line=1;
                }
                if(Line==0) {
                    Line=4;
                }
                wait_ms(100);
            }
            Arriba=(Tecla=='E');
            if (Arriba) {                    //Subir puntero
                Line++;
                if(Line==5) {
                    Line=1;
                }
            }
            Abajo=(Tecla=='F');
            if (Abajo) {                     //Bajar puntero
                Line--;
                if(Line==0) {
                    Line=4;
                }
            }
            Salir=(Tecla=='C');              //Cancelar Operacion
            if (Salir) {
                return 0;
            }
            Atras=(Tecla=='B');
            if (Atras) {                     //Atras en menu
                return 0;
            }
            Finalizar=(Tecla=='D');          //En caso de confirmacion
            if (Finalizar) {
                if((Clave_Actual[0]==Clave[0])&&(Clave_Actual[1]==Clave[1])&&(Clave_Actual[2]==Clave[2])&&(Clave_Actual[3]==Clave[3])) {
                    return 1;
                } else {
                    return 0;
                }
            }
            switch (Line) {
                case 1:
                    SelectionLine1[0]=99;
                    SelectionLine2[0]=99;
                    break;
                case 2:
                    SelectionLine1[0]=110;
                    SelectionLine2[0]=110;
                    break;
                case 3:
                    SelectionLine1[0]=121;
                    SelectionLine2[0]=121;
                    break;
                case 4:
                    SelectionLine1[0]=132;
                    SelectionLine2[0]=132;
                    break;
            }
            //-------Mostrar en Patalla-------
            Screen.Rectangle(SelectionLine1[0],SelectionLine1[1],SelectionLine1[2],SelectionLine1[3]);
            Screen.Rectangle(SelectionLine2[0],SelectionLine2[1],SelectionLine2[2],SelectionLine2[3]);
            Screen.PutString(15,12,"Ingrese password");
            Screen.PutChar(100,34,')');
            Screen.PutChar(111,34,')');
            Screen.PutChar(122,34,')');
            Screen.PutChar(133,34,')');
            Screen.Limits();
            Screen.Show();
            Computer.printf("%s\n",Clave);
        }
    }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------
void Interrupt_Host()
{
    Counter_Host++;
    MinutosTranscurrido++;
    Battery_State = Charger.Control();    
    if(Counter_Host>Hostin_Conection) {
        Alarm=1;       
        Counter_Host=0; 
    }
    if(MinutosTranscurrido>11){
            HoraHostingPantalla++;
            MinutosTranscurrido=0;
    }
    if((Battery_State==0)&&(Battery_State!=Battery_State_Before)){
        //AlarmasCall(6,1);
    }
    if((Battery_State==1)||(Battery_State==2)) {
        //AlarmasCall(6,0);
    }
    Computer.printf("\n-%i-%i-",HoraHostingPantalla,Battery_State);
    Panel_Voltage=Charger.PanelRead();
    Battery_Voltage=Charger.BatteryRead();
    Computer.printf("B:%.2f  P:%.2f\n",Battery_Voltage,Panel_Voltage);
    Battery_State_Before=Battery_State;
}

void H_EnviarPaso(uint8_t Entrada_Comando)
{
    switch (Entrada_Comando) {
        case 1:
            Slave.Command(HOSTING_STEP1);
            Progreso[0]=' ';
            Progreso[1]='1';
            Progreso[2]='0';
            break;
        case 2:
            Slave.Command(HOSTING_STEP2);
            Progreso[0]=' ';
            Progreso[1]='2';
            Progreso[2]='0';
            break;
        case 3:
            Slave.Command(HOSTING_STEP3);
            Progreso[0]=' ';
            Progreso[1]='3';
            Progreso[2]='0';
            break;
        case 4:
            Slave.Command(HOSTING_STEP4);
            Progreso[0]=' ';
            Progreso[1]='4';
            Progreso[2]='0';
            break;
        case 5:
            Slave.Command(HOSTING_STEP5);
            Progreso[0]=' ';
            Progreso[1]='5';
            Progreso[2]='0';
            break;
        case 6:
            Slave.Command(HOSTING_STEP6);
            Progreso[0]=' ';
            Progreso[1]='6';
            Progreso[2]='0';
            break;
        case 7:
            Slave.Command(HOSTING_STEP7);
            Progreso[0]=' ';
            Progreso[1]='7';
            Progreso[2]='0';
            break;
        case 8:
            Slave.Command(HOSTING_STEP8);
            Slave.Send_Hosting(Parquimetro,Municipio,Alarmas);
            Computer.printf("-%s-%s-%s-\n",Parquimetro,Municipio,Alarmas);
            Progreso[0]=' ';
            Progreso[1]='8';
            Progreso[2]='0';
            break;
        case 9:
            Slave.Command(HOSTING_STEP9);
            Progreso[0]=' ';
            Progreso[1]='9';
            Progreso[2]='0';
            break;
        case 10:
            Slave.Command(HOSTING_STEP10);
            Progreso[0]='1';
            Progreso[1]='0';
            Progreso[2]='0';
            break;
        case 11:
            Slave.Command(HOSTING_STEP11);
            Progreso[0]='1';
            Progreso[1]='0';
            Progreso[2]='0';
            break;
    }
}

void EsperarSim900(int TimeOut)
{
    Computer.printf("Espera sim900\n");
    Inicio=BaseClock.read_ms();
    Keypad_Init();     
    while(true) {
        Fin=BaseClock.read_ms();
        Transcurrido=Fin-Inicio; 
        if(Transcurrido>TimeOut) {
            Computer.printf("Espera sim900 salir\n");
            BaseClock.stop();
            break;
        }
        Tecla=KeyPad_Read();
        if (Tecla!=NO_KEY) { 
            Computer.printf("Espera sim900 teclado\n");
            Screen.On(HoraHostingPantalla);
            wait_ms(20);
            Screen.Init();
            PantallaInicio();
            Usuario(USER_INIT);
            Inicio=BaseClock.read_ms();         
        }
    }
}

void Hosting()
{
    uint8_t PasoHostingNum=1;
    H_EnviarPaso(PasoHostingNum);
    Computer.printf("Hosting iniciando\n");
    Computer.printf("Paso %i\n", PasoHostingNum);

    BaseClock.start();
    while(true) {
        if(PasoHostingNum>10) {
            Computer.printf("Paso final\n");
            Inicio=BaseClock.read_ms();
            while(true) {
                if(Slave.Mensaje()) {
                    wait_ms(75);
                    break;
                }
                Fin=BaseClock.read_ms();
                Transcurrido=Fin-Inicio;//49
                if(Transcurrido>10000) {
                    break;
                }
            }
            HoraHosting[4]=Slave.Recibe();
            HoraHosting[3]=Slave.Recibe();
            HoraHosting[2]=Slave.Recibe();
            HoraHosting[1]=Slave.Recibe();
            HoraHosting[0]=Slave.Recibe();
            HoraHosting[5]=Slave.Recibe();
            HoraHosting[5]='\0';
            RespuestaHosting[5]=Slave.Recibe();
            RespuestaHosting[4]=Slave.Recibe();
            RespuestaHosting[3]=Slave.Recibe();
            RespuestaHosting[2]=Slave.Recibe();
            RespuestaHosting[1]=Slave.Recibe();
            RespuestaHosting[0]=Slave.Recibe();
            //alertPQ response OK+390+11:42
            // pperez@gmail.com 4321
            // 34.211.174.1 port 3306  
            // Base de datos s0p0rt310          
            Computer.printf("-%s-\n",RespuestaHosting);
            Computer.printf("H-%s-H\n",HoraHosting);
            if(HoraHosting[2]==':'){
                HoraHostingPantalla=((uint8_t)HoraHosting[0]-48)*600+((uint8_t)HoraHosting[1]-48)*60+((uint8_t)HoraHosting[3]-48)*10 + ((uint8_t)HoraHosting[4]-48);
                Computer.printf("Mayor",HoraHostingPantalla);
            }

            Inicio=BaseClock.read_ms();
            while(true) {
                if(Slave.Answer()) {
                    wait_ms(50);
                    break;
                }
                Fin=BaseClock.read_ms();
                Transcurrido=Fin-Inicio;//49
                if(Transcurrido>10000) {
                    break;
                }
            }
            if((RespuestaHosting[0]=='O')&&RespuestaHosting[1]=='K') {
                Computer.printf("Alarmas aprobada\n");
                Alarm=false;
                break;
            } else {
                Computer.printf("Alarmas fallo\n");
                break;
            }
        }
        
        Tecla=KeyPad_Read();
        if(Tecla!=NO_KEY) {
            Screen.On(HoraHostingPantalla);
            wait_ms(20);
            Screen.Init();
            if(PasoHostingNum==1) {
                Computer.printf("Teclado encender Paso==1\n");
                Usuario(USER_INIT);
                break;
            }            
            if(PasoHostingNum<3) {
                Computer.printf("Teclado Paso<3\n");
                Usuario(USER_INIT2);
                break;
            }
            if(PasoHostingNum<6) {
                Computer.printf("Teclado Paso<6\n");
                Usuario(USER_INIT3);
                break;
            }
            if(PasoHostingNum==6) {
                Computer.printf("Teclado Paso==6\n");
                Usuario(USER_INIT4);
                break;
            }
            if(PasoHostingNum<=8) {
                Computer.printf("Teclado Paso<=8\n");
                Usuario(USER_INIT5);
                break;
            }
            if(PasoHostingNum<=10) {
                Computer.printf("Teclado Paso<=10\n");
                Usuario(USER_INIT5);
                break;
            }
            if(PasoHostingNum<=11) {
                Computer.printf("Teclado Paso<=11\n");
                PantallaInicio();
                Usuario(USER_INIT5);
            }
        }
        
        if (Slave.Answer()) {
            PasoHostingNum++;
            Computer.printf("Paso %i\n", PasoHostingNum);
            H_EnviarPaso(PasoHostingNum);
        }
    }
    Slave.Command(COMMAND_OFF);
}

void M_PruebaHosting()
{
    int Paso=1;
    int PasoSiguiente=1;

    while(true) {
        if (Paso==PasoSiguiente) {
            Computer.printf("Paso %i\n",Paso);
            H_EnviarPaso(Paso);
            Paso=Paso+1;
            if(Paso>11) {
                Computer.printf("Paso %i final\n",Paso);
                Inicio=BaseClock.read_ms();
                while(true) {
                    if(Slave.Mensaje()) {
                        wait_ms(75);
                        break;
                    }
                    Fin=BaseClock.read_ms();
                    Transcurrido=Fin-Inicio;//49
                    if(Transcurrido>10000) {
                        break;
                    }
                }
                HoraHosting[5]=Slave.Recibe();
                HoraHosting[4]=Slave.Recibe();
                HoraHosting[3]=Slave.Recibe();
                HoraHosting[2]=Slave.Recibe();
                HoraHosting[1]=Slave.Recibe();
                HoraHosting[0]=Slave.Recibe();
                RespuestaHosting[5]=Slave.Recibe();
                RespuestaHosting[4]=Slave.Recibe();
                RespuestaHosting[3]=Slave.Recibe();
                RespuestaHosting[2]=Slave.Recibe();
                RespuestaHosting[1]=Slave.Recibe();
                RespuestaHosting[0]=Slave.Recibe();
                
                Computer.printf("-%s-\n",RespuestaHosting);
                Computer.printf("-%s-\n",HoraHosting);

                Inicio=BaseClock.read_ms();
                while(true) {
                    if(Slave.Answer()) {
                        wait_ms(50);
                        break;
                    }
                    Fin=BaseClock.read_ms();
                    Transcurrido=Fin-Inicio;//49
                    if(Transcurrido>10000) {
                        break;
                    }
                }
                if((RespuestaHosting[0]=='O')&&RespuestaHosting[1]=='K') {
                    Computer.printf("Alarmas aprobada\n");
                    Screen.PutString(15,12,"Prueba hosting");
                    Screen.PutString(15,34,"Aprobada.");
                    Screen.Limits();
                    Screen.Show();
                    wait_ms(2000);
                    Alarm=false;
                    break;
                } else {
                    Computer.printf("Alarmas fallo\n");
                    Screen.PutString(15,12,"Prueba hosting");
                    Screen.PutString(15,34,"Error.");
                    Screen.Limits();
                    Screen.Show();
                    wait_ms(2000);
                    break;
                }
            }
            Screen.PutString(15,12,"Prueba hosting");
            Screen.PutString(15,34,"Progreso:");
            Screen.PutChar(105,34,Progreso[0]);
            Screen.PutChar(115,34,Progreso[1]);
            Screen.PutChar(125,34,Progreso[2]);
            Screen.PutChar(135,34,'%');
            Screen.Limits();
            Screen.Show();
        }
        if (Slave.Answer()) {
            PasoSiguiente=PasoSiguiente+1;
            Computer.printf("Next\n");
        }
    }
}

void Mantenimiento()
{
    Screen.On(HoraHostingPantalla);
    wait_ms(20);
    Screen.Init();
    BaseClock.start();
    M_PantallaConfiguracion();
    bool ClaveAceptada=M_ClaveIngreso(5000);
    while(ClaveAceptada) {
        Comando=M_MenuConfiguracion(30000);
        switch(Comando) {
            case M_SISTEMA:
                Computer.printf("--> Sistema\n");
                Comando=M_MenuSistema(30000);
                if(Comando==M_PARQUIMETRO) {
                    Computer.printf("--> Id parquimetro\n");
                    M_Parquimetro(30000);
                }
                if(Comando==M_MUNICIPIO) {
                    Computer.printf("--> Id municipalidad\n");
                    M_Municipio(30000);
                }
                if(Comando==M_PRECIO) {
                    Computer.printf("--> Precio 10mins\n");
                    M_Precio(30000);
                }
                break;

            case M_RED:
                Computer.printf("--> Red\n");
                Comando=M_MenuConexion(30000);
                if(Comando==M_SENAL) {
                    Computer.printf("--> Intensidad senal\n");
                    M_IntensidadSenal();
                }
                if(Comando==M_HOSTING) {
                    Computer.printf("--> Prueba hosting\n");
                    M_PruebaHosting();
                }
                if(Comando==M_CONEXION_SIM) {
                    Computer.printf("--> Conexion modulo\n");
                    M_ConexionSim900();
                }
                break;

            case M_IMPRESORA:
                Computer.printf("--> Impresora\n");
                Comando=M_MenuImpresora(30000);
                if(Comando==M_PAPEL) {
                    Computer.printf("--> Cambio de papel\n");
                    M_CambioPapel(30000);
                }
                if(Comando==M_IMPRESION) {
                    Computer.printf("--> Tiquete de prueba\n");
                    M_PruebaTiquete();
                }
                if(Comando==M_CONEXION_IMP) {
                    Computer.printf("--> Conexion impresora\n");
                    M_ConexionImpresora();
                }
                break;

            case M_TECLADO:
                Computer.printf("--> Teclado\n");
                Comando=M_MenuTeclado(30000);
                if(Comando==M_PRUEBA_TECLA) {
                    Computer.printf("--> Prueba de teclado\n");
                    M_PruebaTeclado(3000);
                }
                break;

            case M_LECTORA:
                Computer.printf("--> Lectora\n");
                Comando=M_MenuLectora(30000);
                if(Comando==M_LECTURA) {
                    Computer.printf("--> Prueba de lectura\n");
                    M_PruebaLectora();
                }
                if(Comando==M_CONEXION_LEC) {
                    Computer.printf("--> Conexion lectora\n");
                    M_ConexionLectora();
                }
                break;

            case M_INFORMACION:
                Comando=M_MenuInformacion();
                if(Comando==M_INFORMACION) {
                    Computer.printf("--> Informacion\n");
                    M_Informacion();
                }
                break;

            default:
                Comando=M_OFF;
        }

        if(Comando==M_OFF) {
            Computer.printf("Cerrando modo configuracion\n");
            Screen.Clean();
            MantenimientoInterruption=0;
            BaseClock.stop();
            Screen.Off();
            break;
        }
    }
    Screen.Clean();
    MantenimientoInterruption=0;
    Screen.Off();
    wait(1);
}

int main()
{
    Screen.On(HoraHostingPantalla);
    Screen.Init();
    Screen.Clean();
    Keypad_C1.rise(&KeyPad_InterruptDisable);
    Keypad_C2.rise(&KeyPad_InterruptDisable);
    Keypad_C3.rise(&KeyPad_InterruptDisable);
    Keypad_C4.rise(&KeyPad_InterruptDisable);
    Configuracion.rise(&Interrupt_Mantenimiento);
    CardReader.attach(&Interrupt_CardReader);
    Host.attach(&Interrupt_Host,5);//1800 30 minutos
    Computer.printf("Prototipo Completo\n");
    Screen.Off();
    while(1) {
        KeyPad_InterruptEnable();
        Doors.InterruptEnable();
        hal_sleep();
        Tecla=KeyPad_Read();
        if(Tecla!=NO_KEY) {
            LedUsuario=1;
            MAX232=0;
            Usuario(USER_INIT);
            EsperarSim900(5000);
            LedUsuario=0;
            MAX232=1;
        }
        if(MantenimientoInterruption) {
            LedMantenimiento=1;
            Mantenimiento();
            LedMantenimiento=0;
        }
        if(Doors.Read()>0) {
            Alarm=1;
            AlarmasCall((3+Doors.Read()),1);
        } else {
            AlarmasCall(4,0);
            AlarmasCall(5,0);
        }
        if(Alarm) {
            LedHosting=1;
            Hosting();
            EsperarSim900(5000);
            LedHosting=0;
        }
    }
}