En realidad no me convence lo que te voy a pasar como para dejarlo definitivo, pero es para que tengas una idea de masomenos como podes hacerlo:
int DTMF_CMD;
int8 j=1;
int8 Temp;
int8 dtmf = 0;
char RX_DTMF[15];
char const ASCII[16] = {'D','1','2','3','4','5','6','7','8','9','0','*','#','A','B','C'};
// Interrupción para detectar el DTMF
#int_EXT
void EXT_isr(void){
DTMF_CMD = 0x0;
Temp = input_b(); // Leer todo PORTB
if (bit_test(Temp,1)) bit_set(DTMF_CMD,3); // Leer bit 1 (B1) de Temp y guardar en el bit 3 DTMF_CMD 3---
if (bit_test(Temp,2)) bit_set(DTMF_CMD,2); // Leer bit 2 (B2) de Temp y guardar en el bit 2 DTMF_CMD -2--
if (bit_test(Temp,3)) bit_set(DTMF_CMD,1); // Leer bit 3 (B3) de Temp y guardar en el bit 1 DTMF_CMD --1-
if (bit_test(Temp,4)) bit_set(DTMF_CMD,0); // Leer bit 4 (B4) de Temp y guardar en el bit 0 DTMF_CMD ---0
DTMF_CMD=ASCII[DTMF_CMD]; // Busca el ASCCI correspondiente
switch(dtmf)
{
case 0:
if(DTMF_CMD == '*'){
dtmf++;
RX_DTMF[0] = DTMF_CMD;
}
break;
case 1:
if(DTMF_CMD == '#' || j >= 9) { // Proteccion, la primera es cuando recibe el # sabeidno que termino, y la segunda es para que no supere la cantidad maxima de digitos
dtmf++;
RX_DTMF[9] = '\0';
j = 1;
}
else {
RX_DTMF[j++] = DTMF_CMD;
}
break;
case 2:
// Aca estaria completo y no haria nada hasta que se ponga en 0 dtmf
break;
}
}
// Loop principal
/******************* <<< Ciclo Principal >>> **********************************/
void main(void){
while(true){
if(dtmf >= 2) {
dtmf=0;
}
}
}
Respecto al codigo, es insensato guardar los '*' y '#', yo intente dejarlo como estaba, la otra es que podes prescindir del '#' ya que podes recibir hasta que se reciba otro '*'. Acomode el codigo para que funcione como lo tenias casi, pero no hace falta.
Y el checksum es muy simple, procedes a sumar todos los digitos, suponete que tenes:
"*A123456#"
En ves de enviar esto envias asi:
"*A123456C"
Donde la C es el checksum. Este valor lo calculas con un for y sumando todos los anteriores. Suponete esto:
int8 Checksum = 0;
char TX_DTMF[15] = "*A123456";
int8 i=0;
for(i=0; TX_DTMF!='\0';i++)
{
Checksum += TX_DTMF[i];
}
// Revisar si es ++i o i en esta que sigue
TX_DTMF[++i] = Checksum;
TX_DTMF[++i] = '\0';
Entonces en tu receptor vas a sumar todo menos el ultimo y restarle el ultimo, o sino para simplficar la parte del receptor podes hacer:
int8 Checksum = 0;
char TX_DTMF[15] = "*A123456";
int8 i=0;
for(i=0; TX_DTMF!='\0';i++)
{
Checksum += TX_DTMF[i];
}
// Revisar si es ++i o i en esta que sigue
TX_DTMF[++i] = ~Checksum + 1;
TX_DTMF[++i] = '\0';
Asi de esa forma en el receptor solo tenes que sumar TODO, y si es correcto deberia darte 0.
------------
PD: Ahora que se que queres hacer con el ordenado de los bits, lo podes hacer mas rapido.Aca tenes el codigo, como vos usas los bits xxxa aaax, (donde 'a' son los bits que me interesan) lo primero que hago es rotar y luego una AND asi quedan 0000 aaaa. Al pasarlos por la tabla
en ves de invertirlos, directamente uso ese indice y que me de como resultado los valores invertidos, por eso cambio la tabla. Estimo ahora que con 2 instrucciones haces lo del puerto A y luego la tabla queda fuera de discusión ya que antes no hablamos de la misma.
int DTMF_CMD;
int8 j=1;
int8 Temp;
int8 dtmf = 0;
char RX_DTMF[15];
char const ASCII[16] = {'D','8','4','#','2','0','6','B','1','9','5','A','3','*','7','C'};
// Interrupción para detectar el DTMF
#int_EXT
void EXT_isr(void){
DTMF_CMD = ASCII[(input_b() >> 1) & 0xF] ; // Leer todo PORTB
switch(dtmf)
{
case 0:
if(DTMF_CMD == '*'){
dtmf++;
RX_DTMF[0] = DTMF_CMD;
}
break;
case 1:
if(DTMF_CMD == '#' || j >= 9) { // Proteccion, la primera es cuando recibe el # sabeidno que termino, y la segunda es para que no supere la cantidad maxima de digitos
dtmf++;
RX_DTMF[9] = '\0';
j = 1;
}
else {
RX_DTMF[j++] = DTMF_CMD;
}
break;
case 2:
// Aca estaria completo y no haria nada hasta que se ponga en 0 dtmf
break;
}
}