El programa tiene varias partes.
Empecemos por la idea original del programa.
Es realizar un buffer de lectura de la UART, es decir mientras llegue dato que se guarden en el buffer, esto lo hace por 10 segundos, por eso ese delay que tenes en el main.
De alli luego envia todos los datos.
Mientras esta en el delay no puede hacer otra cosa, la unica cosa que puede hacer es alguna interrupcion que lo saque de alli, por eso tenemos la recepcion:
#int_rda
void serial_isr() {
int t;
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
Pensa que "next_in" es el indice donde tiene que ir el dato en el buffer, esto te interesa unicamente para no sobreescribir algo que ya paso.
"next_out" por su parte, es para cuando sacas datos del buffer, te indica desde donde debes empezar, ya que puede ocurrir que no sea desde 0.
Luego revisa si el proximo valor a donde deberia ir el nuevo dato que recibio es el mismo que el que debe sacar, si son iguales no avanza el "next_in"
Ejemplo, tenes 10 valores maximos. next_out es 8, y next_in es 7 apenas comenzas, es decir esta LLENO, ya que si queres sacas tus datos debes sacarlos 8..9..0..1..2..3..4..5..6..7
Si tenemos esos valores, cuando entra a la interrupcion, se da cuenta que:
next_in=(next_in+1) % BUFFER_SIZE;
Le da 8, por lo tanto next_in lo vuelve a 7.
Aca esta un posible "problema", ya que si llegan mas datos siempre van a sobreescribir la ultima posicion, en ves de indicarte o tratar de solucionarlo de otra forma. Asi que el tamaño debe ser lo suficientemente grande como para que esto no ocurra.
............
Hasta aca ya recibimos todos los datos.. ahora solo queda enviarlos. Y eso lo hace luego del delay:
while(bkbhit)\\ necesito prescindir de cualquier intervención de teclado
putc( bgetc
() );\\ obtener la cadena pero en hexadecimal
bkbhit en realidad no es mas que (next_in!=next_out)
Por lo tanto dice que mientras el buffer tenga algo ejecute lo de adentro, cuando no tenga nada el buffer ( es decir next_in y next_out sean iguales) procedera a no ejecutar mas el putc.
bgetc, es una funcion que define mas arriba. Esta funcion es simple,
BYTE bgetc() {
BYTE c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
La funcion devuelve el valor del buffer a la que apunta next_out, y de paso actualiza next_out para la proxima ves que entre.
Vamos a un ejemplo mas practico
Recepcion:
Empezamos con next_in = next_out = 0
Se recibe 'H','o','l','a'
Nuestro buffer y variables quedarian asi:
buffer[] = {'H','o','l','a',0x00,.....,0x00} Supongo que se pusieron a 0 todos los valores antes
Next_in = 4 Indice 4 es el proximo a actualizar cuando se reciba algo, es decir el 5to elemento.
Next_out = 0
Si no llega nada mas y se procede a enviar quedaria asi:
buffer[] = {'H','o','l','a',0x00,.....,0x00} Supongo que se pusieron a 0 todos los valores antes
Next_in = 4 Indice 4 es el proximo a actualizar cuando se reciba algo, es decir el 5to elemento.
Next_out = 4 Sen envio desde 0 hasta 3, al llegar al 4 sale el while y entra nuevamente en el delay
Si llega 'P','e' ahora:
buffer[] = {'H','o','l','a','P','e',0x00,.....,0x00}
Next_in = 6
Next_out = 4
Observaras que no se borra lo anterior, pero al momento de "sacar" del buffer nuestro next_out nos dice que hay que sacar desde el indice 4, hasta que next_out == next_in.
Por eso si se va a enviar o leer, solo se envia 'P','e'.
Ahora si quedando Next_out en 6 tambien.
En resumen es CASI un buffer circular, si no fuera por la parte que sobreescribe cuando esta lleno.