From 6add33161e732ed834469f217a7ba97200694d63 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Sun, 11 Dec 2005 22:47:25 +0000 Subject: [PATCH] =?utf8?q?Integra=20leds=20con=20modulo=20de=20red.=20El?= =?utf8?q?=20programa=20est=C3=A1=20ahora=20recibiendo=20datos=20de=20la?= =?utf8?q?=20red=20y=20poni=C3=A9ndolos=20en=20la=20matriz=20(a=20lo=20bru?= =?utf8?q?to,=20falta=20implementar=20bien=20el=20protocolo=20para=20confi?= =?utf8?q?gurar=20nuestro=20dispositivo=20por=20red).=20Pero=20toda=20la?= =?utf8?q?=20funcionalidad=20b=C3=A1sica-b=C3=A1sica=20est=C3=A1=20lista.?= =?utf8?q?=20De=20ahora=20en=20m=C3=A1s=20es=20empezar=20a=20dejar=20algun?= =?utf8?q?as=20cosas=20m=C3=A1s=20prolijas=20(varias)=20y=20corregir=20alg?= =?utf8?q?unos=20bugs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/Makefile | 78 +++++++++-- src/debug.h | 21 +-- src/leds.asm | 356 ++++++++++++++++++++++++++++++++++++++++++++++++ src/leds.h | 45 ++++++ src/main.c | 23 +++- src/reg51keil.h | 16 +++ src/reg51sdcc.h | 16 +++ 7 files changed, 524 insertions(+), 31 deletions(-) create mode 100644 src/leds.asm create mode 100644 src/leds.h diff --git a/src/Makefile b/src/Makefile index 1cdf384..b7ca284 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,35 +1,85 @@ +# Compilador CC=sdcc -LD=sdcc CFLAGS=-DDEBUG +# Assembler +AS=asx8051 +ASFLAGS=-plosgff + +# Linker +LD=aslink +LDFLAGS=-cn + +# Shell +SHELL=bash + +# Archivos +cmodules=main dp8390 eth ip udp +amodules=leds +modules=$(cmodules) $(amodules) + all: el.hex +debug.h: types.h leds.h + reg51.h: reg51sdcc.h netdev.h: types.h dp8390.h: types.h reg51.h netdev.h -dp8390.rel: dp8390.c dp8390.h - $(CC) $(CFLAGS) -c dp8390.c +eth.h: types.h + +ip.h: types.h + +udp.h: types.h + +dp8390.asm: dp8390.c dp8390.h debug.h eth.h +dp8390.rel: dp8390.asm + +eth.asm: eth.c eth.h netdev.h debug.h +eth.rel: eth.asm + +ip.asm: ip.c ip.h netdev.h debug.h +ip.rel: ip.asm + +udp.asm: udp.c udp.h ip.h netdev.h debug.h +udp.rel: udp.asm + +main.asm: main.c leds.h reg51.h netdev.h eth.h ip.h udp.h debug.h +main.rel: main.asm -eth.rel: eth.c eth.h netdev.h types.h - $(CC) $(CFLAGS) -c eth.c +leds.rel: leds.asm -ip.rel: ip.c ip.h netdev.h types.h - $(CC) $(CFLAGS) -c ip.c +el.hex: $(addsuffix .rel, $(modules)) + @echo -e \ + "-myuxi\n"\ + "-Y\n"\ + "-b CSEG = 0x0000\n"\ + "-b ISEG = 0x0080\n"\ + "-b BSEG = 0x0000\n"\ + "-k /usr/share/sdcc/lib/small\n"\ + "-k /usr/share/sdcc/lib/small\n"\ + "-l mcs51\n"\ + "-l libsdcc\n"\ + "-l libint\n"\ + "-l liblong\n"\ + "-l libfloat\n"\ + "$(addsuffix .rel\n, $(modules))"\ + "-e\n" | \ + $(LD) $(LDFLAGS) + @packihx main.ihx > el.hex + @$(RM) main.ihx -udp.rel: udp.c udp.h ip.h netdev.h types.h - $(CC) $(CFLAGS) -c udp.c +%.asm: + $(CC) $(CFLAGS) -c $< -main.rel: main.c netdev.h eth.h ip.h udp.h - $(CC) $(CFLAGS) -c main.c +%.rel: + $(AS) $(ASFLAGS) $< -el.hex: main.rel dp8390.rel eth.rel ip.rel udp.rel - $(LD) $(LDFLAGS) -o el.hex main.rel dp8390.rel eth.rel ip.rel udp.rel clean: - @rm -vf el.hex *.rel *.asm *.lst *.map *.lnk *.mem *.sym + @rm -vf el.hex *.rel $(addsuffix .asm, $(cmodules)) *.lst *.map *.lnk *.mem *.sym .PHONY: clean diff --git a/src/debug.h b/src/debug.h index 9d70530..73e989f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -18,22 +18,23 @@ } \ while (0) -#define print(w) \ - do \ - { \ - leds(w); \ - sleep(8); \ - } \ - while (0) - -#define printb(bh, bl) \ +#define print(w) \ do \ { \ - ledsb(bh, bl); \ + leds_write(w); \ sleep(8); \ } \ while (0) +#define printb(bh, bl) \ + do \ + { \ + leds_write_high(bh); \ + leds_write_low(bl); \ + sleep(8); \ + } \ + while (0) + #else // NO DEBUG #define sleep(t) ; diff --git a/src/leds.asm b/src/leds.asm new file mode 100644 index 0000000..bc729f1 --- /dev/null +++ b/src/leds.asm @@ -0,0 +1,356 @@ +; vim: set filetype=asx8051 et sw=4 sts=4 : + +; Módulo y opciones +.module leds +.optsdcc -mmcs51 --model-small + +; 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 = 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) + .ds 8 + ; Usamos siempre banco 0 + ar0 = 0x00 + ar1 = 0x01 + ar2 = 0x02 + ar3 = 0x03 + ar4 = 0x04 + ar5 = 0x05 + ar6 = 0x06 + ar7 = 0x07 + +; Variables es memoria RAM común +.area DSEG (DATA) +_leds_matrix_len:: + .ds 1 +_leds_delay:: + .ds 1 +delay: + .ds 1 +curr_col: + +; Variables en memoria RAM extendida indirecta (8052) +.area ISEG (DATA) +_leds_matrix:: + .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna + + +; Configuramos el vector de interrupciones para atender el timer2 +;.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 +.area CSEG (CODE) + +; Inicializa leds. +; Primitiva de C: +; void leds_init(); +; +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_init:: + ; guardo registros que uso + push ar0 + push ar1 + push ar2 + + ; leo de la ROM el tamaño por default + mov dptr, #DEFAULT_MATRIX_LEN + clr a + movc a, @a+dptr + mov _leds_matrix_len, a + clr c + rlc a ; multiplicamos por 2 porque hay 2 bytes por columna + mov r2, a ; tamaño en bytes de la matriz + + ; Cargo milisegundos + acall _leds_delay_update + mov delay, _leds_delay + + ; copio imagen por default de la ROM a la RAM + 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 +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, 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) + + mov curr_col, #0 ; inicializo el contador de columna en 0 + + ; Limpiamos stack + 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, #LEDS_LOW + cpl a ; complemento para ver encendidos los "1" + movx @dptr, a + ; parte alta + 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_write_low(unsigned char); +; +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_write_low:: + ; parte baja + mov a, dpl ; de C me viene el argumento en el dpl + 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_write_high(unsigned char); +; +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_write_high:: + ; parte baja + mov a, dpl ; de C me viene el argumento en el dpl + mov dptr, #LEDS_HIGH + cpl a ; complemento para ver encendidos los "1" + movx @dptr, a + ret + + +; Actualiza el retardo de la matriz según la cantidad de columnas +; Primitiva de C: +; void leds_delay_update(); +; +; La fórmula utilizada es: (DELAY_BASE - (leds_matrix_len / 2)) * 0.1 ms +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_delay_update:: + mov a, _leds_matrix_len + clr c + rrc a ; divido por 2 + mov dpl, a + mov a, #DELAY_BASE + subb a, dpl + mov _leds_matrix_len, a + ret + + +; 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, 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 + push psw + push ar0 + push dpl + push dph + + ; vemos si hay que empezar a leer por la 1ra columna de nuevo + mov a, curr_col + 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 + +1$: + ; multiplicamos por 2 porque hay 2 bytes por columna + clr c + rlc a + + ; uso r0 como puntero al comienzo de la matriz + mov r0, #_leds_matrix + add a, r0 ; le sumo al puntero el offset actual segun la columna + mov r0, a + + ; imprimo en LEDS_LOW + mov a, @r0 ; leo el contenido de la matriz + mov dptr, #LEDS_LOW + cpl a ; complemento para ver encendidos los "1" + movx @dptr, a + + ; imprimo en LEDS_HIGH + inc r0 ; busco proximo byte de la columna + mov a, @r0 ; leo el contenido de la matriz + mov dptr, #LEDS_HIGH + cpl a ; complemento para ver encendidos los "1" + movx @dptr, a + + ; avanzamos a la proxima columna + mov a, curr_col + inc a + mov curr_col, a + + ; sacamos nuestra basura del stack + pop dph + pop dpl + pop ar0 + pop psw + pop acc + +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 +DEFAULT_MATRIX_LEN: + .db 16 + ;.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 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 +; .dw 0b1111000000000000 ; columna 3 +; .dw 0b0111100000000000 ; columna 4 +; .dw 0b0011110000000000 ; columna 5 +; .dw 0b0001111000000000 ; columna 6 +; .dw 0b0000111100000000 ; columna 7 +; .dw 0b0000011110000000 ; columna 8 +; .dw 0b0000001111000000 ; columna 9 +; .dw 0b0000000111100000 ; columna 10 +; .dw 0b0000000011110000 ; columna 11 +; .dw 0b0000000001111000 ; columna 12 +; .dw 0b0000000000111100 ; columna 13 +; .dw 0b0000000000011110 ; columna 14 +; .dw 0b0000000000001111 ; columna 15 + +;end diff --git a/src/leds.h b/src/leds.h new file mode 100644 index 0000000..188978b --- /dev/null +++ b/src/leds.h @@ -0,0 +1,45 @@ +/* vim: set et sw=4 sts=4 : */ + +#ifndef _LEDS_H_ +#define _LEDS_H_ + +/** Cantidad máxima de columnas */ +#define LEDS_MAX_COLS 32 + +/** Tamaño de la matriz de leds, en cantidad de columnas */ +extern unsigned char leds_matrix_len; + +/** Matriz de leds, cada elemento del array es una columna */ +extern unsigned int leds_matrix[LEDS_MAX_COLS]; + +/** Retardo de refresco de la matriz (en múltiplos de 0.1ms) */ +extern unsigned char leds_delay; + +/** Inicializa leds + * + * El 'dibujado' de la matriz se puede controlar fácilmente parando y/o + * iniciando el timer2. Para comenzar a 'dibujar' la matriz sólo es necesario + * setear el bit TR2 del registro T2CON (y habilitar las interrupciones + * globalmente si aún no se hizo, bit EA del registro IE). + */ +void leds_init(); + +/** Realiza un testeo simple de los leds */ +void leds_test(); + +/** Escribe un word (16 bits) en la columna de leds */ +void leds_write(unsigned int); + +/** Escribe un byte en la parte baja de la columna de leds */ +void leds_write_low(unsigned char); + +/** Escribe un byte en la parte alta de la columna de leds */ +void leds_write_high(unsigned char); + +/** Actualiza el delay al recomendado según el tamaño de la matriz */ +void leds_delay_update(); + +/** Atiende interrupción del timer2 para 'dibujar' la matriz */ +void leds_timer2_isr() interrupt 5; + +#endif /* _LEDS_H_ */ diff --git a/src/main.c b/src/main.c index 60ed5db..f980df1 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include "debug.h" #include "leds.h" +#include "reg51.h" #include "netdev.h" #include "eth.h" #include "ip.h" @@ -9,16 +10,24 @@ void main(void) { - // Apagamos todos los leds - leds(0); + // Inicializamos leds + leds_init(); + + // Hacemos prueba simple de los leds + leds_test(); // Inicializamos dispositivo de red if (!netdev_init()) { - leds(0xFFFF); - while(1); // Si falla init nos quedamos bobos + // Si hubo un error, quedan prendidos todos los leds + leds_write(0xFFFF); + return; } + // Comienza a 'dibujar' + EA = 1; // Habilita interrupciones globalmente + TR2 = 1; // Pone a correr el 'dibujado' + // Inicializo IP ip_addr_local[0] = 10; ip_addr_local[1] = 10; @@ -30,7 +39,6 @@ void main(void) while (1) // Forever { - byte buf[64]; //XXX byte i; //XXX byte len; @@ -76,8 +84,9 @@ void main(void) // Nuestro protocolo, por ahora un simple echo! len = udp_dgram_len - UDP_HEADER_SIZE; netdev_read_start(len); + leds_matrix_len = len; for (i = 0; i < len; ++i) - buf[i] = udp_read_byte(); + leds_matrix[i] = udp_read_byte(); netdev_read_end(); if (!udp_checksum_ok()) goto drop; @@ -92,7 +101,7 @@ void main(void) udp_write_dgram_header(); netdev_write_start(len); for (i = 0; i < len; ++i) - udp_write_byte(buf[i]); + udp_write_byte(leds_matrix[i]); netdev_write_end(); udp_write_checksum(ETH_HEADER_SIZE+IP_HEADER_SIZE); netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len); diff --git a/src/reg51keil.h b/src/reg51keil.h index ed182bf..a40d8ab 100644 --- a/src/reg51keil.h +++ b/src/reg51keil.h @@ -23,6 +23,12 @@ sfr IE = 0xA8; sfr IP = 0xB8; sfr SCON = 0x98; sfr SBUF = 0x99; +/* 8052 */ +sfr T2CON = 0xC8; +sfr RCAP2L = 0xCA; +sfr RCAP2H = 0xCB; +sfr TL2 = 0xCC; +sfr TH2 = 0xCD; /* BIT Register */ /* PSW */ @@ -44,6 +50,16 @@ sbit IT1 = 0x8A; sbit IE0 = 0x89; sbit IT0 = 0x88; +/* T2CON (8052) */ +sbit TF2 = 0xCF; +sbit EXF2 = 0xCE; +sbit RCLK = 0xCD; +sbit TCLK = 0xCC; +sbit EXEN2 = 0xCB; +sbit TR2 = 0xCA; +sbit C_T2 = 0xC9; +sbit CP_RL2C = 0xC8; + /* IE */ sbit EA = 0xAF; sbit ES = 0xAC; diff --git a/src/reg51sdcc.h b/src/reg51sdcc.h index ca1bbaf..1710d8e 100644 --- a/src/reg51sdcc.h +++ b/src/reg51sdcc.h @@ -23,6 +23,12 @@ sfr at 0xA8 IE; sfr at 0xB8 IP; sfr at 0x98 SCON; sfr at 0x99 SBUF; +/* 8052 */ +sfr at 0xC8 T2CON; +sfr at 0xCA RCAP2L; +sfr at 0xCB RCAP2H; +sfr at 0xCC TL2; +sfr at 0xCD TH2; /* BIT Register */ /* PSW */ @@ -44,6 +50,16 @@ sbit at 0x8A IT1; sbit at 0x89 IE0; sbit at 0x88 IT0; +/* T2CON (8052) */ +sbit at 0xCF TF2; +sbit at 0xCE EXF2; +sbit at 0xCD RCLK; +sbit at 0xCC TCLK; +sbit at 0xCB EXEN2; +sbit at 0xCA TR2; +sbit at 0xC9 C_T2; +sbit at 0xC8 CP_RL2C; + /* IE */ sbit at 0xAF EA; sbit at 0xAC ES; -- 2.43.0