; 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();
; Constantes
-INTERVAL = 666 ; 0.1ms (por el clock de 8MHz)
-LEDS_LOW = 0x0080
-LEDS_HIGH = 0x00c0
-DELAY_BASE = 11 ; 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)
.area DSEG (DATA)
_leds_matrix_len:: ; Cantidad de columnas de la matriz
.ds 1
-_leds_delay:: ; Retardo de dibujado configurado
- .ds 1
-delay: ; Contador del retardo actual
- .ds 1
curr_col: ; Columna que se está dibujando actualmente
.ds 1
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 tr2 ; largo a correr el timer2
; 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
_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$
-
- ; comenzamos realmente a leer la próxima columna
- mov delay, _leds_delay
; 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...