.module leds
.optsdcc -mmcs51 --model-small
-; Variables globales
-.globl _leds_matrix
-.globl _leds_matrix_len
-.globl _leds_delay
-
-; Funciones globales
-.globl _leds_init
-.globl _leds_write
-.globl _leds_write0
-.globl _leds_write1
-.globl _leds_delay_update
+; Constantes "públicas"
+LEDS_MAX_COLS = 32 ; Cantidad máxima de columnas
+
+; 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_test ; void leds_test();
+.globl _leds_write ; void leds_write(unsigned int);
+.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_timer2_isr ; void leds_timer2_isr() interrupt 5;
+
; Constantes
; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz)
-INTERVAL = 66 ; 0.1ms (por el clock de 8MHz)
-LEDS0 = 0x0080
-LEDS1 = 0x00c0
-MAX_COLS = 64
-DELAY_BASE = 28
+INTERVAL = 33 ; 0.05ms (por el clock de 8MHz)
+LEDS_HIGH = 0x0080
+LEDS_LOW = 0x00c0
+DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
; Área de bancos de registros
.area REG_BANK_0 (REL,OVR,DATA)
delay:
.ds 1
curr_col:
-__stack: ; XXX
- .ds 1
; Variables en memoria RAM extendida indirecta (8052)
.area ISEG (DATA)
_leds_matrix::
- .ds MAX_COLS * 2 ; 2 bytes por columna
+ .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna
; Configuramos el vector de interrupciones para atender el timer2
-.area INTV (ABS, CODE)
- .org 0x0000 ; XXX
- ljmp _leds_init ; XXX
-
- .org 0x002b
- clr tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
- ljmp timer2_isr
+;.area INTV (ABS, CODE)
+; .org 0x002b
+; clr tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
+; ljmp timer2_isr
; Área de código del programa
;
; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
_leds_init::
- mov sp, #__stack ; XXX
; guardo registros que uso
push ar0
push ar1
push ar2
; leo de la ROM el tamaño por default
- mov dptr, #MAT_D_LEN
+ mov dptr, #DEFAULT_MATRIX_LEN
clr a
movc a, @a+dptr
mov _leds_matrix_len, a
mov delay, _leds_delay
; copio imagen por default de la ROM a la RAM
- mov dptr, #MAT_D
+ mov dptr, #DEFAULT_MATRIX
mov r0, #0 ; indice del "array" en la ROM
mov r1, #_leds_matrix ; dirección de memoria de la RAM
mov a, r0
-seguir$:
+proximo$:
movc a, @a+dptr ; leo de la ROM con el índice
mov @r1, a ; escribo en el puntero a la RAM
inc r1 ; incremento puntero
inc r0 ; incremento índice
mov a, r0 ; para comparar
- cjne a, ar2, seguir$ ; veo si quedan más bytes por leer
+ 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 ie, #0b10100000 ; habilito interrupcion timer 2
- ; bits de IE (interrupt enable) en 1:
- ; IE.7 (Global enable/disable)
- ; IE.5 (Enable timer 2 interrupt)
- mov t2con, #0b00000100 ; setup timer 2 (auto-reload y start)
+ mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
+ setb et2 ; habilito interrupcion timer2 (IE.5)
mov curr_col, #0 ; inicializo el contador de columna en 0
; Limpiamos stack
- push ar2
- push ar1
- push ar0
+ pop ar2
+ pop ar1
+ pop ar0
ret
+; Hace una prueba simple de los leds
+; Primitiva de C:
+; void leds_test();
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_test::
+ ; escribo patrones en los leds
+ mov dptr, #0xffff
+ acall _leds_write
+ acall sleep
+
+ mov dptr, #0xaaaa
+ acall _leds_write
+ acall sleep
+
+ mov dptr, #0x5555
+ acall _leds_write
+ acall sleep
+
+ mov dptr, #0x0000
+ acall _leds_write
+ acall sleep
+
+ ret
+
+
; Escribe en los leds.
; Primitiva de C:
; void leds_write(unsigned int);
;
; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
_leds_write::
+ ; guardamos en r0 la parte alta que imprimimos despues
+ push ar0
+ mov r0, dph
; parte baja
mov a, dpl ; de C me viene la parte baja del argumento en el dpl
- mov dptr, #LEDS0
+ mov dptr, #LEDS_LOW
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
; parte alta
- mov a, dph ; de C me viene la parte alta del argumento en el dph
- mov dptr, #LEDS1
+ mov a, r0 ; de C me viene la parte alta del argumento en el dph
+ mov dptr, #LEDS_HIGH
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
+ ; devolvemos r0
+ pop ar0
ret
; Escribe en los leds del primer latch.
; Primitiva de C:
-; void leds_write0(unsigned char);
+; void leds_write_low(unsigned char);
;
; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
-_leds_write0::
+_leds_write_low::
; parte baja
mov a, dpl ; de C me viene el argumento en el dpl
- mov dptr, #LEDS0
+ mov dptr, #LEDS_LOW
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
ret
; Escribe en los leds del segundo latch.
; Primitiva de C:
-; void leds_write1(unsigned char);
+; void leds_write_high(unsigned char);
;
; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
-_leds_write1::
+_leds_write_high::
; parte baja
mov a, dpl ; de C me viene el argumento en el dpl
- mov dptr, #LEDS1
+ mov dptr, #LEDS_HIGH
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
ret
ret
-; Manejador de la interrupción del timer2
-timer2_isr:
+; Manejador de la interrupción del timer2 para el uso de los leds.
+; Primitiva de C:
+; 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, fin$
+ djnz delay, 255$
; comenzamos realmente a leer la próxima columna
mov delay, _leds_delay
; vemos si hay que empezar a leer por la 1ra columna de nuevo
mov a, curr_col
- cjne a, _leds_matrix_len, continua$
+ cjne a, _leds_matrix_len, 1$
; hay que empezar de nuevo
mov curr_col, #0
mov a, curr_col ; dejamos en a la columna actual
-continua$:
+1$:
; multiplicamos por 2 porque hay 2 bytes por columna
clr c
rlc a
add a, r0 ; le sumo al puntero el offset actual segun la columna
mov r0, a
- ; imprimo en LEDS1
+ ; imprimo en LEDS_LOW
mov a, @r0 ; leo el contenido de la matriz
- mov dptr, #LEDS1
+ mov dptr, #LEDS_LOW
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
- ; imprimo en LEDS0
+ ; imprimo en LEDS_HIGH
inc r0 ; busco proximo byte de la columna
mov a, @r0 ; leo el contenido de la matriz
- mov dptr, #LEDS0
+ mov dptr, #LEDS_HIGH
cpl a ; complemento para ver encendidos los "1"
movx @dptr, a
pop psw
pop acc
-fin$:
+255$:
reti ; listo! seguimos viaje...
+; Provoca un retardo corto.
+; Usamos dpl y dph porque son "C-safe".
+sleep:
+ mov a, #0xff
+2$:
+ mov dph, #0xff
+1$:
+ mov dpl, #0xff
+ djnz dpl, .
+ djnz dph, 1$
+ djnz acc, 2$
+ ret
+
+
; Matriz por default
-MAT_D_LEN:
+DEFAULT_MATRIX_LEN:
.db 16
;.db 32
-MAT_D:
+DEFAULT_MATRIX:
.dw 0b0000111111110000 ; columna 0
.dw 0b0011111111111100 ; columna 1
.dw 0b0111000000001110 ; columna 2
.dw 0b0011111111111100 ; columna 14
.dw 0b0000111111110000 ; columna 15
-; .dw 0b0000111111110000 ; columna 0
-; .dw 0b0011111111111100 ; columna 1
-; .dw 0b0111000000001110 ; columna 2
-; .dw 0b0110000000000110 ; columna 3
-; .dw 0b1100110000000011 ; columna 4
-; .dw 0b1100011000110011 ; columna 5
-; .dw 0b1100001100110011 ; columna 6
-; .dw 0b1100001100000011 ; columna 7
-; .dw 0b1100001100000011 ; columna 8
-; .dw 0b1100001100110011 ; columna 9
-; .dw 0b1100011000110011 ; columna 10
-; .dw 0b1100110000000011 ; columna 11
-; .dw 0b0110000000000110 ; columna 12
-; .dw 0b0111000000001110 ; columna 13
-; .dw 0b0011111111111100 ; columna 14
-; .dw 0b0000111111110000 ; columna 15
-
-;MAT_D:
+ .dw 0b1111000000001111 ; columna 0
+ .dw 0b1100000000000011 ; columna 1
+ .dw 0b1000111111110001 ; columna 2
+ .dw 0b1001111111111001 ; columna 3
+ .dw 0b0011001111111100 ; columna 4
+ .dw 0b0011100111001100 ; columna 5
+ .dw 0b0011110011001100 ; columna 6
+ .dw 0b0011110011111100 ; columna 7
+ .dw 0b0011110011111100 ; columna 8
+ .dw 0b0011110011001100 ; columna 9
+ .dw 0b0011100111001100 ; columna 01
+ .dw 0b0011001111111100 ; columna 00
+ .dw 0b1001111111111001 ; columna 01
+ .dw 0b1000111111110001 ; columna 03
+ .dw 0b1100000000000011 ; columna 04
+ .dw 0b1111000000001111 ; columna 05
+
; .dw 0b0000001111100000 ; columna 0
; .dw 0b0000111110000000 ; columna 1
; .dw 0b0111111000000000 ; columna 2