/*
mTouch con 16LF727
Manuel Jiménez - Nocturno 2009
www.micropic.es
*/
#include <16LF727.h>
#include <pruebas mtouch.h>
#define ANTIRREBOTES 1
#define SENSIBILIDAD 5
unsigned char indice;
unsigned long lectura[8]; // lectura de cada sensor
unsigned long promedio[8]; // promedio leído de cada sensor
unsigned long umbral; // umbral que debe superar para que se considere pulsado
unsigned long promedio_alto; // variable temporal de promedio alto
unsigned long promedio_bajo; // variable temporal de promedio bajo
typedef struct{ // Estructura de información de los sensores
unsigned char rebotes;
unsigned char Pulsado:1;
unsigned char SePulso:1;
unsigned char Soltado:1;
} TIPO_SENSOR;
TIPO_SENSOR Sensor[8];
/***********************************************************************************************
INICIALIZACIÓN
***********************************************************************************************/
void inicializacion() {
char i;
setup_oscillator(OSC_16MHZ);
for (indice=0; indice<8; indice++){ // Inicialización de variables
promedio[indice] = 0;
lectura[indice] = 0;
}
/* Utilizaremos estos 8 sensores:
CPS4: RB4
CPS5: RB5
CPS6: RA4
CPS7: RA5
CPS8: RD0
CPS9: RD1
CPS10: RD2
CPS11: RD3
*/
ANSELA = 0b00110000;
set_tris_a (0b11110111);
ANSELB = 0b00110000;
set_tris_b (0b01110001);
ANSELD = 0b00001111;
set_tris_d (0b11111111);
set_tris_c (0b11101001);
ANSELE = 0b00000000;
set_tris_e (0b00000000);
setup_timer_2(T2_DIV_BY_16,0xB4,15);// Timer2 activo, prescaler 1:16
setup_timer_1(T1_GATE_INVERTED); // Timer1 activo, asociado al sensor capacitivo y sin prescaler
T1GCON = 0b11100010; // Timer1 gate activo, y asociado al Timer2
CPSCON0 = 0b10001100; // Activamos los sensores capacitivos
CPSCON1 = 0x04; // Empezamos por el sensor nº 4, que es el primero de los que usamos
indice = 0;
TMR1GIF = 0; // Borramos el flag de interrupción
TMR1GIE = 1; // Activamos la interrupción del Timer1 Gate
enable_interrupts(GLOBAL); // Activamos la gestión de interrupciones
for(i=0; i<8; i++) Sensor[i] = 0; // Inicialización de variables
output_low(LED0); // Apagamos los leds
output_low(LED1);
output_low(LED2);
output_low(LED3);
output_low(LED4);
output_low(LED5);
output_low(LED6);
output_low(LED7);
}
/***********************************************************************************************
RUTINA DE INTERRUPCIÓN
***********************************************************************************************/
#INT_DEFAULT
void GestionDeInterrupciones() {
if (TMR1GIF && TMR1GIE) { // Interrupción del Timer1 Gate
TMR1GIF = 0; // Borramos el flag de interrupción
TMR1ON = 0; // Paramos el timer1
// Cálculo de la media móvil de los últimos 4 ciclos
lectura[indice] = promedio_alto = get_timer1() * 4;
promedio_bajo = promedio[indice] / 4;
umbral = promedio[indice]>>SENSIBILIDAD;
// Si ha pulsado, veremos que el Timer se ha acortado, por debajo del promedio - umbral
if (promedio_alto < promedio[indice] - umbral) {
// Chequeo repetitivo para evitar rebotes
if(Sensor[indice].rebotes < ANTIRREBOTES) Sensor[indice].rebotes++;
if(!Sensor[indice].SePulso && Sensor[indice].rebotes == ANTIRREBOTES) {
Sensor[indice].Pulsado = 1;
Sensor[indice].SePulso = 1;
}
} else {
// Si no ha pulsado y estamos en ciclo de rebotes
if(Sensor[indice].rebotes > 0) Sensor[indice].rebotes--;
if(Sensor[indice].SePulso && Sensor[indice].rebotes == 0) {
Sensor[indice].SePulso = 0;
Sensor[indice].Soltado = 1;
}
// Al promedio acumulado le restamos el valor antiguo y le metemos el nuevo
promedio[indice] += promedio_alto/4 - promedio_bajo;
}
set_timer1(0); // Iniciamos la cuenta en el Timer1
TMR1ON = 1; // Activamos nuevamente el Timer1
indice ++; // Pasamos al siguiente sensor
indice &= 0x07; // La máscara nos permite contar de 0 a 7
CPSCON1 = indice+4; // Sumamos 4 porque nuestros sensores son del 4 al 11
}
}
/***********************************************************************************************
PROGRAMA PRINCIPAL
***********************************************************************************************/
void main() {
unsigned char i;
inicializacion();
while (true) { // bucle infinito
for(i=0; i<8; i++) { // recorremos los 8 sensores
if(Sensor[i].Pulsado) { // se ha detectado pulsación
switch(i) { // encendemos el led que corresponda
case 0:
output_high(LED0);
break;
case 1:
output_high(LED1);
break;
case 2:
output_high(LED2);
break;
case 3:
output_high(LED3);
break;
case 4:
output_high(LED4);
break;
case 5:
output_high(LED5);
break;
case 6:
output_high(LED6);
break;
case 7:
output_high(LED7);
break;
}
Sensor[i].Pulsado = 0; // trabajo realizado, borramos el indicador
} else if(Sensor[i].Soltado) { // se ha quitado el dedo
switch(i) { // apagamos el led que corresponda
case 0:
output_low(LED0);
break;
case 1:
output_low(LED1);
break;
case 2:
output_low(LED2);
break;
case 3:
output_low(LED3);
break;
case 4:
output_low(LED4);
break;
case 5:
output_low(LED5);
break;
case 6:
output_low(LED6);
break;
case 7:
output_low(LED7);
break;
}
Sensor[i].Soltado = 0; // trabajo realizado, borramos el indicador
}
}
}
}