; Variables públicas
.globl _leds_matrix_len ; unsigned char
.globl _leds_matrix ; unsigned int[LEDS_MAX_COLS]
-.globl _leds_delay ; unsigned char
; Funciones públicas
.globl _leds_init ; void leds_init();
.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)
-LEDS_LOW = 0x0080
-LEDS_HIGH = 0x00c0
-DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
+LEDS_LOW = 0x0080 ; posición de xdata donde está el latch 1
+LEDS_HIGH = 0x00c0 ; posición de xdata donde está el latch 2
+DELAY_FACTOR = 0 ; base del contador para el retardo
+DELAY_BASE = 13 ; punto medio del retardo
+DELAY_DIVISOR = 3 ; divisor para la cantidad de columnas
; Á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::
+curr_col: ; Columna que se está dibujando actualmente
.ds 1
-delay:
- .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 r2, a ; tamaño en bytes de la matriz
; Cargo milisegundos
+ mov rcap2l, #-DELAY_FACTOR ; base del retardo
lcall _leds_delay_update
- mov delay, _leds_delay
; copio imagen por default de la ROM a la RAM
mov dptr, #DEFAULT_MATRIX
mov a, r0 ; para comparar
cjne a, ar2, proximo$ ; veo si quedan más bytes por leer
- ; cargo los capture registers
- mov rcap2l, #<(-INTERVAL) ; low byte del intervalo
- 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
; Primitiva de C:
; void leds_delay_update();
;
-; La fórmula utilizada es: (DELAY_BASE - (leds_matrix_len / 2)) * 0.1 ms
+; La fórmula utilizada es:
+; DELAY_FACTOR * (DELAY_BASE - (leds_matrix_len / DELAY_DIVISOR))
+; En realidad ya está cargado rcap2l DELAY_FACTOR (constante) y en rcap2h se
+; carga el resultado de:
+; DELAY_BASE - (leds_matrix_len / DELAY_DIVISOR)
; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
_leds_delay_update::
+ push b ; uso b, lo guardo
mov a, _leds_matrix_len
- clr c
- rrc a ; divido por 2
+ mov b, #DELAY_DIVISOR
+ div ab ; en a me queda leds_matrix_len / DELAY_DIVISOR
mov dpl, a
mov a, #DELAY_BASE
- subb a, dpl
- mov _leds_delay, a
+ subb a, dpl ; en a me queda DELAY_BASE - leds_matrix_len / DELAY_DIVISOR
+ jnb cy, 1$ ; Si leds_matrix_len / DELAY_DIVISOR > DELAY_BASE
+ mov a, #1 ; ponemos 1 para que no quede nulo el intervalo (o 'negativo')
+1$: ; Si no, seguimos como siempre
+ mov dpl, a ; complemento a la base
+ mov a, #0
+ subb a, dpl
+ mov rcap2h, a ; Cargo el nuevo retardo
+ pop b ; devuelvo b
+ 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
; void leds_timer2_isr() interrupt 5;
;
_leds_timer2_isr::
- ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
- djnz delay, 255$
-
- ; comenzamos realmente a leer la próxima columna
- mov delay, _leds_delay
+ ; limpiamos flag del timer2
+ clr tf2
; guardamos en el stack el estado actual de los registros que vamos a usar
push acc
pop psw
pop acc
-255$:
reti ; listo! seguimos viaje...
;.db 32
DEFAULT_MATRIX:
-; .dw 0b0000111111110000 ; columna 0
-; .dw 0b0011111111111100 ; columna 1
-; .dw 0b0111000000001110 ; columna 2
-; .dw 0b0110000000000110 ; columna 3
-; .dw 0b1100001100000011 ; columna 4
-; .dw 0b1100011000110011 ; columna 5
-; .dw 0b1100110000110011 ; columna 6
-; .dw 0b1100110000000011 ; columna 7
-; .dw 0b1100110000000011 ; columna 8
-; .dw 0b1100110000110011 ; columna 9
-; .dw 0b1100011000110011 ; columna 10
-; .dw 0b1100001100000011 ; columna 11
-; .dw 0b0110000000000110 ; columna 12
-; .dw 0b0111000000001110 ; columna 13
-; .dw 0b0011111111111100 ; columna 14
-; .dw 0b0000111111110000 ; columna 15
-
- .dw 0b0000011111100000
- .dw 0b0001111111111000
- .dw 0b0011100000011100
- .dw 0b0111110000000110
- .dw 0b0110111000000110
- .dw 0b1100011100000011
- .dw 0b1100001110000011
- .dw 0b1111111111111111
- .dw 0b1111111111111111
- .dw 0b1100001110000011
- .dw 0b1100011100000011
- .dw 0b0110111000000110
- .dw 0b0111110000000110
- .dw 0b0011100000011100
- .dw 0b0001111111111000
- .dw 0b0000011111100000
+ .dw 0b0000111111110000 ; columna 0
+ .dw 0b0011111111111100 ; columna 1
+ .dw 0b0111000000001110 ; columna 2
+ .dw 0b0110000000000110 ; columna 3
+ .dw 0b1100001100000011 ; columna 4
+ .dw 0b1100011000110011 ; columna 5
+ .dw 0b1100110000110011 ; columna 6
+ .dw 0b1100110000000011 ; columna 7
+ .dw 0b1100110000000011 ; columna 8
+ .dw 0b1100110000110011 ; columna 9
+ .dw 0b1100011000110011 ; columna 10
+ .dw 0b1100001100000011 ; columna 11
+ .dw 0b0110000000000110 ; columna 12
+ .dw 0b0111000000001110 ; columna 13
+ .dw 0b0011111111111100 ; columna 14
+ .dw 0b0000111111110000 ; columna 15
+
+; .dw 0b0000011111100000
+; .dw 0b0001111111111000
+; .dw 0b0011100000011100
+; .dw 0b0111110000000110
+; .dw 0b0110111000000110
+; .dw 0b1100011100000011
+; .dw 0b1100001110000011
+; .dw 0b1111111111111111
+; .dw 0b1111111111111111
+; .dw 0b1100001110000011
+; .dw 0b1100011100000011
+; .dw 0b0110111000000110
+; .dw 0b0111110000000110
+; .dw 0b0011100000011100
+; .dw 0b0001111111111000
+; .dw 0b0000011111100000
; .dw 0b1111000000001111 ; columna 0
; .dw 0b1100000000000011 ; columna 1