#include <htc.h>
#define PORTBIT(adr, bit) ( (unsigned)(&adr)*8 + (bit) )
#define Idle_Low 1
#define Idle_High 2
#define PIC_CLK 4000000 //4MHz
#define TIMER_INIT_VALUE 56
/* =================================================================================
Global variables
================================================================================= */
static bit flag = 0; // esta variable la voy a usar para determinar cuando pasaron //los 5 segundos
static bit LED @ PORTBIT(PORTB, 1);
static bit polsador @ PORTBIT(PORTB, 0);
static char present_state = Idle_Low; // state variable
static char future_state = Idle_Low; // state variable
static char button;
static int timer_count = 0;
static void interrupt service_routine (void); // This is the interrupt service routine
void init_system (void);
void time_delay (unsigned int);
char output_logic(void);
char future_state_logic(void);
char read_inputs (void);
/* =================================================================================
Main function
================================================================================= */
void main(void)
{
init_system();
LED = 0;
while(1)
{
output_logic();
future_state_logic();
}
}
/* =================================================================================
Function definitions
================================================================================= */
//*****************************************************************************
//Future_state_logic routine
//*****************************************************************************
char future_state_logic(void)
{
char error = 0;
button = read_inputs();
switch (present_state)
{
case Idle_Low: if (button == 1)
{
future_state = Idle_High;
flag = 0; // borro el flag del tiempo
timer_count = 0; // inicializo el contador
}
else
future_state = Idle_Low;
break;
case Idle_High:
if (flag == 0) future_state = Idle_High; // si no pasaron 5s
else // si pasaron 5s
future_state = Idle_Low;
break;
default:
error = 1;
}
return (error);
}
//*****************************************************************************
//Output logic routine
//*****************************************************************************
char output_logic(void)
{
unsigned char error = 1;
switch (present_state)
{
case Idle_Low:
LED = 0;
error = 0;
break;
case Idle_High:
if (flag == 0) // si no pasaron 5s
{
LED = 1;
future_state = Idle_High;
}
else // si pasaron 5s
{
LED = 0;
future_state = Idle_Low;
}
error = 0;
break;
default:
error = 1;
LED = 0;
break;
}
return (error);
}
//*****************************************************************************
//Init operations
//*****************************************************************************
void init_system (void)
{
ADCON1 = 0x0F; // Todos los bits como digitales
TRISB = 1; // Todos los pones se comportaran como salidas menos RB0 2^0=1
INTEDG0 = 1; // Door switch rising edge starts an INT interrupt request
INT0IE = 1; //Enables the INT0 external interrupt
timer_count = 0; // Counting oscillator pulses.Increments at Fosc/4= 25us
//PSA = 1; //pre-scaler OFF.
T0PS3 = 1; // prescaler apagado (lo tube que poner así porque sino daba error)
T0CS = 0; // cuenta desde (Fosc/4)
TMR0IF = 0; // borro el flag de interrupcion del timer0
TMR0IE = 1; // habilito la interrupcion del timer0
GIE = 1;
}
//***************************************************************************
//Interrupt Service Routine (only for the generation of the FSM's CLK sisgnal
// using Timer0)
//***************************************************************************
static void interrupt service_routine (void)
{ //Interrupt is the key word here
if (TMR0IF)
{
TMR0 = 6; // asigno 6 para que cuente 250 ciclos
// cada cilco dura 1us (1/(Fosc/4))
if ((present_state == Idle_High) && (flag == 0))
timer_count++; // si esta encendido y no pasaron 5s, incrementar contador
present_state = future_state; // like a Data flip-flop
if (timer_count == 20000) flag = 1; // si pasaron 5s, activo el flag
// tiempo = timer_count * 250 uS
TMR0IF = 0; // clear interrupt flag
}
if (INT0IF)
{ //INT0 External Interrupt Flag bit
/* State register */
INT0IF = 0;
present_state = future_state;
}
}
//*****************************************************************************
//Scan inputs
//*****************************************************************************
char read_inputs (void)
{
char value = 0;
if (polsador == 0)
{
value = 1;
}
return (value);
}
//*****************************************************************************
//Time delay routine.
//*****************************************************************************
void time_delay(unsigned int delay)
{
unsigned int i;
for(i = 0; i <= delay ;i++)
{
NOP();
}
}