static void write_reg(unsigned char reg, unsigned char wr_data)
{
+ leds_lock();
// Select register address.
ADDR_PORT &= ~ADDR_PORT_MASK;
ADDR_PORT |= reg;
// Set register data port as input again.
DATA_PORT = DATA_PORT_MASK;
+ leds_unlock();
}
static unsigned char read_reg(unsigned char reg)
{
+ leds_lock();
// Select register address.
ADDR_PORT &= ~ADDR_PORT_MASK;
ADDR_PORT |= reg;
IOR = 1;
NICE = 1;
+ leds_unlock();
return reg;
}
*((byte*) &elp_command) = udp_read_byte();
netdev_read_end();
- printb(*((byte*) &elp_command), 0x01);
-
// Si es un SET lo proceso
switch (elp_command.var)
{
i = udp_read_byte();
netdev_read_end();
// Verifico cantidad de columnas
- if ((LEDS_MIN_COLS < i) || (i < LEDS_MAX_COLS))
+ if ((i < LEDS_MIN_COLS) || (i > LEDS_MAX_COLS))
return 0;
leds_matrix_len = i;
netdev_read_start(leds_matrix_len * 2); // matriz
return len + 1 /* booleano de 1 byte */;
// Si es SET procesamos
netdev_read_start(1); // booleano de 1 byte
- //XXX if (udp_read_byte() == 0x00) // si viene 0 reanuda
- //XXX TR2 = 1;
- //XXX else
- if (udp_read_byte() != 0x00)
+ if (udp_read_byte() == 0x00) // si viene 0 reanuda
+ ET2 = 1;
+ else
{
- TR2 = 0;
+ ET2 = 0;
leds_write(0x0000); // Si pausa apaga leds
}
netdev_read_end();
case ELP_VAR_PAUSE:
netdev_write_start(1 /* booleano de 1 byte */);
- udp_write_byte(!TR2);
+ udp_write_byte(!ET2);
netdev_write_end();
break;
.globl _leds_write_low ; void leds_write_low(unsigned char);
.globl _leds_write_high ; void leds_write_high(unsigned char);
.globl _leds_delay_update ; void leds_delay_update();
+.globl _leds_lock ; void leds_lock();
+.globl _leds_unlock ; void leds_unlock();
.globl _leds_timer2_isr ; void leds_timer2_isr() interrupt 5;
; Constantes
-; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz)
-INTERVAL = 65000 ; 0.05ms (por el clock de 8MHz)
+INTERVAL = 666 ; 0.1ms (por el clock de 8MHz)
LEDS_LOW = 0x0080
LEDS_HIGH = 0x00c0
-DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
+DELAY_BASE = 11 ; 16 columnas anda bien con 28 - (len / 2) == 20
; Área de bancos de registros
.area REG_BANK_0 (REL,OVR,DATA)
; Variables es memoria RAM común
.area DSEG (DATA)
-_leds_matrix_len::
+_leds_matrix_len:: ; Cantidad de columnas de la matriz
.ds 1
-_leds_delay::
+_leds_delay:: ; Retardo de dibujado configurado
.ds 1
-delay:
+delay: ; Contador del retardo actual
+ .ds 1
+curr_col: ; Columna que se está dibujando actualmente
.ds 1
-curr_col:
; Variables en memoria RAM extendida indirecta (8052)
.area ISEG (DATA)
-_leds_matrix::
+_leds_matrix:: ; Matriz a dibujar
.ds LEDS_MAX_COLS * 2 ; 2 bytes por columna
+; Variables de bit
+.area BSEG (BIT)
+lock: ; Variable utilizada para el 'locking', indica si el timer
+ .ds 1 ; estaba andando al momento de lockear para que el unlock
+ ; pueda reactivarlo de ser necesario
; Configuramos el vector de interrupciones para atender el timer2
;.area INTV (ABS, CODE)
mov rcap2h, #>(-INTERVAL) ; high byte del intervalo
mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
- setb et2 ; habilito interrupcion timer2 (IE.5)
+ setb tr2 ; largo a correr el timer2
mov curr_col, #0 ; inicializo el contador de columna en 0
subb a, dpl
mov _leds_delay, a
ret
+
+
+; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2).
+; Primitiva de C:
+; void leds_lock();
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_lock::
+ mov c, et2 ; En lock me queda si está el timer andando o no.
+ mov lock, c
+ clr et2 ; Sea como sea, lo paro.
+ ret
+
+
+; Desbloquea el timer de los leds.
+; Primitiva de C:
+; void leds_unlock();
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_unlock::
+ jnb lock, 1$ ; Si no estába andando, no hago nada
+ setb et2 ; Si estaba andando lo prendo
+1$:
+ ret
; Manejador de la interrupción del timer2 para el uso de los leds.
; void leds_timer2_isr() interrupt 5;
;
_leds_timer2_isr::
+ ; limpiamos flag del timer2
+ clr tf2
; vemos si todavía hay que seguir esperando o si ya tenemos que leer
djnz delay, 255$
/** Actualiza el delay al recomendado según el tamaño de la matriz */
void leds_delay_update();
+/** Bloquea timer de leds cuando se accede a una zona crítica (P0 y/o P2). */
+void leds_lock();
+
+/** Desbloquea el timer de los leds.
+ * @precond Se llamó a leds_lock();
+ */
+void leds_unlock();
+
/** Atiende interrupción del timer2 para 'dibujar' la matriz */
void leds_timer2_isr() interrupt 5;
// Comienza a 'dibujar'
EA = 1; // Habilita interrupciones globalmente
- //XXX TR2 = 1; // Pone a correr el 'dibujado'
+ ET2 = 1; // Pone a correr el 'dibujado'
// Inicializo IP
ip_addr_local[0] = 10;
// Procesamos comando ELP y obtenemos tamaño de la
// respuesta
len = elp_read_process_command();
- printb(len, 0x02);
+ //printb(len, 0x02);
// Si el tamaño es 0, hubo error o no está soportado
if (!len)
goto drop;
- print(0x0004);
+ //print(0x0004);
// FIXME por ahora no tenemos forma de 'abortar' el
// comando si el checksum es incorrecto, lo verificamos
// por deporte.
if (!udp_checksum_ok())
goto drop;
- print(0x0008);
+ //print(0x0008);
// Terminamos recepción
netdev_recv_end();
- print(0x0010);
+ //print(0x0010);
// Respuesta
netdev_send_start();
eth_write_frame_header();
ip_packet_len = UDP_HEADER_SIZE + len;
- printb(ip_packet_len, 0x20);
+ //printb(ip_packet_len, 0x20);
ip_write_packet_header();
udp_dgram_len = len;
- printb(udp_dgram_len, 0x40);
+ //printb(udp_dgram_len, 0x40);
udp_write_dgram_header();
elp_write_response();
udp_write_checksum(ETH_HEADER_SIZE + IP_HEADER_SIZE);
netdev_send_end(ETH_HEADER_SIZE + IP_HEADER_SIZE
+ UDP_HEADER_SIZE + len);
- printb(ETH_HEADER_SIZE + IP_HEADER_SIZE
- + UDP_HEADER_SIZE + len, 0x80);
- //XXX
- if (elp_command.set && (elp_command.var == ELP_VAR_PAUSE))
- TR2 = 1;
}
}
continue;
/* IE */
sbit EA = 0xAF;
+sbit ET2 = 0xAD;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
/* IE */
sbit at 0xAF EA;
+sbit at 0xAD ET2;
sbit at 0xAC ES;
sbit at 0xAB ET1;
sbit at 0xAA EX1;