;------------------------------------------------------------
; Nombre del Proyecto: video_18f452
; Fecha: 08/08/2008
; PIC: 18F452
; Cristal: 10 MHz PLLx4
; Velocidad de reloj: 40 Mhz
;------------------------------------------------------------
 
 ERRORLEVEL -220
 ERRORLEVEL -223

 PROCESSOR 18F452

 LIST    P=PIC18F452
 INCLUDE <P18F452.inc>

 ;Bytes de configuración, consultar: C18_Config_Settings_51537e.pdf para cambiar
 
 CONFIG OSCS=OFF, OSC=HSPLL, BORV=42, BOR=ON, PWRT=ON, WDTPS=128, WDT=OFF, CCP2MUX=OFF, DEBUG=OFF, LVP=OFF, STVR=ON
 CONFIG CP3=OFF, CP2=OFF, CP1=OFF, CP0=OFF, CPD=OFF, CPB=OFF, WRT3=OFF, WRT2=OFF, WRT1=OFF, WRT0=OFF
 CONFIG WRTD=OFF, WRTB=OFF, WRTC=OFF, EBTR3=OFF, EBTR2=OFF, EBTR1=OFF, EBTR0=OFF, EBTRB=OFF


;------------------------------------------------------------
;                  Declaración de Registros
;------------------------------------------------------------

contador        equ     0x00
contador2       equ     0x01
flags           equ     0x02                   ;Registro de banderas
dato_ram        equ     0x03                   ;Buffer de datos a cargar en alguna posición de la Ram


;------------------------------------------------------------
;                  Declaración de Bits
;------------------------------------------------------------

#define         sinc    LATA,5,0               ;pin de salida de sincronismo

horizontal      equ     0                      ;Indica que debe generar pulsos de sincronismo horizontal
ecualizacion    equ     1                      ;Indica que debe generar pulsos de ecualización
vertical        equ     2                      ;Indica que debe generar pulsos de sincronismo vertical
funciones       equ     3                      ;Indica que puede emular las funciones de una GLCD
campo           equ     4                      ;Indica que campo está mostrando 0=campo impar, 1=campor par
post            equ     5                      ;Indica que  pulsos de ecualización debe generar
                                               ;0=preecualización, 1=postecualización

;------------------------------------------------------------
;                  Declaración de Macros
;------------------------------------------------------------

sacar_y rotar   macro
                movff   INDF0,LATE             ;Mueve el dato apuntado por FSR0 al puerto E
                rrncf   INDF0,f,0              ;Rota el dato
                endm
                
Byte            macro
                sacar_y rotar                  ;Cada Byte es sacado al pin de video y rotado 8 veces
                sacar_y rotar
                sacar_y rotar
                sacar_y rotar
                sacar_y rotar
                sacar_y rotar
                sacar_y rotar
                movff   INDF0,LATE             ;Mueve el dato apuntado por FSR0 al puerto E
                rrncf   POSTINC0,f,0           ;Rota el registro de la ram e incrementa el puntero
                endm


;------------------------------------------------------------
;                        Inicio
;------------------------------------------------------------
                
                org     0x00
                goto    programa


;------------------------------------------------------------
;                      inicio de la interrupción por tmr0
;------------------------------------------------------------

                org     0x08                   ;Vector de interrupción sin prioridades
interrupcion    btg     sinc                   ;Invierte la señal de sincronismo
                BCF     INTCON,TMR0IF,0        ;Limpia la bandera de overflow del tmr0
                btfsc   flags,horizontal,0
                goto    sincro_h               ;Procesa los pulsos de sincronismo horizontal
                btfsc   flags,ecualizacion,0
                goto    sincro_e               ;Procesa los pulsos de pre y post ecualizacíon
                btfsc   flags,vertical,0
                goto    sincro_v               ;Procesa los pulsos de sincronismo vertical

media_linea     setf    TMR0H,0                ;TMR0 full -(tiempo del pulso de sinc - cant. de instr. desde btg sinc - offset)
                movlw   .226                   ;255-(47-14-4)
                movwf   TMR0L,0                ;Ajuste de tmr0 para 4,7 uS
                btfss   sinc                   ;Verifica si el pulso de sincronismo está en alto o en bajo
                retfie  1                      ;Retorna de la interrupción y repone W, STATUS y BSR
                setf    TMR0H,0
                movlw   .7                     ;255-(271-19-4)
                movwf   TMR0L,0                ;Ajuste de tmr0 para 27,1 uS
                bsf     flags,ecualizacion,0   ;El próximo paso son los pulsos de ecualización
                retfie  1
                
sincro_h        setf    TMR0H,0
                movlw   .221                   ;255-(47-9-4)
                movwf   TMR0L,0                ;Ajuste de tmr0 para 4,7 uS
                btfss   sinc                   ;Verifica si el pulso de sincronismo está en alto o en bajo
                retfie  1
                movlw   .253
                movwf   TMR0H,0                ;Ajuste de tmr0 para 58,9 uS
                movlw   .197
                movwf   TMR0L,0                ;(256*2)+(255-(589-15-4))
                bcf     flags,funciones,0
                incf    contador,f,0           ;Incrementa el contador de pulsos de sincronismo
                movlw   .253
                cpfslt  contador,0             ;Si el contador llegó a 253,
                goto    final_campo            ;se termina el campo
                movlw   .63
                cpfsgt  contador,0             ;Si el contador no llegó a 63 líneas,
                bsf     flags,funciones,0      ;puede cargar la ram
                movlw   .192
                cpfslt  contador,0             ;Si el contador superó las 192 líneas
                bsf     flags,funciones,0      ;puede cargar la ram
                btfsc   flags,funciones,0      ;Sinó debe mostrar los datos en pantalla
                retfie  1

salida_de_video movlw   .33                    ;Demora para centrar la imagen horizontalmente
                movwf   contador2,0
bucle_delay     decfsz  contador2,f,0
                goto    bucle_delay

                Byte                           ;1º Byte
                Byte                           ;2º
                Byte                           ;3º
                Byte                           ;4º
                Byte                           ;...
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte
                Byte                           ;16 Bytes cada línea horizontal

                nop
                bcf     LATE,0,0               ;Pone en bajo la salida de video
                btfsc   contador,0,0           ;Verifica si es una línea par o impar para repetir el patrón de dibujo
                retfie  1
                tstfsz  FSR0L,0                ;Si FSR0L vale cero se le resta 1 a FSR0H (borrow)
                incf    FSR0H,f,0              ;Sino queda igual
                decf    FSR0H,f,0
                movlw   .16
                subwf   FSR0L,f,0              ;Se restan 16 posiciones a FSR0L
                retfie  1

final_campo     clrf    contador,0             ;Se terminó el campo y se pone el contador a cero
                bcf     flags,horizontal,0     ;Se suprimen los pulsos de sincronismo horizontal
                lfsr    0,0x100                ;Le carga el valor del principio de la memoria de video al puntero
                btfsc   flags,campo,0          ;Si el campo es par
                bsf     flags,ecualizacion,0   ;se pone en alto la bandera de ecualización (próximos pulsos)
                btg     flags,campo,0          ;Se indica que campo vendrá a continuación (se invierte el bit)
                retfie  1

sincro_e        setf    TMR0H,0
                movlw   .247                   ;255-(23-11-4)
                movwf   TMR0L,0                ;Ajuste de tmr0 para 2,3 uS
                btfss   sinc                   ;Verifica si el pulso de sincronismo está en alto o en bajo
                retfie  1
                movlw   .254
                movwf   TMR0H,0
                movlw   .237                   ;256+255-(295-17-4)
                movwf   TMR0L,0                ;Ajuste de tmr0 para 29,5 uS
                incf    contador,f,0           ;Se incrementa el contador de pulsos de ecualización
                movlw   .6
                cpfseq  contador,0             ;Si llegó a 6 se cambian las banderas
                retfie  1
                clrf    contador,0             ;Se pone a cero el contador
                bcf     flags,ecualizacion,0   ;se suprimen los pulsos de ecualización
                btg     flags,post,0           ;Se indica que ecualización vendrá a continuación (se invierte el bit)
                btfss   flags,post,0           ;Si está finalizando la postecualización y el campo es par se debe agregar tiempo
                goto    post_ecua              ;Va a post_ecua
                bsf     flags,vertical,0       ;Sinó se habilitan los pulsos de sincronismo vertical
                retfie  1

post_ecua       bsf     flags,horizontal,0     ;Se habilitan los pulsos de sincronismo horizontal
                btfss   flags,campo,0          ;Si el campo es par se agrega media línea horizontal
                retfie  1                      ;Sinó retorna de la interrupción
                movlw   .253
                movwf   TMR0H,0                ;(2*256)+(255-(613-34-4))
                movlw   .192
                movwf   TMR0L,0                ;Ajuste de tmr0 para 61,3 uS
                retfie  1
                
sincro_v        setf    TMR0H,0                ;255-(271-14-4)
                movlw   .2
                movwf   TMR0L,0                ;Ajuste de tmr0 para 27,1 uS
                btfss   sinc                   ;Verifica si el pulso de sincronismo está en alto o en bajo
                retfie  1
                setf    TMR0H,0                ;255-(47-19-4)
                movlw   .231
                movwf   TMR0L,0                ;Ajuste de tmr0 para 4,7 uS
                incf    contador,f,0           ;Se incrementa el contador de pulsos verticales
                movlw   .6
                cpfseq  contador,0             ;Si llegó a los 6 pulsos
                retfie  1
                clrf    contador,0             ;Pone a cero el contador
                bsf     flags,ecualizacion,0   ;Se habilitan los pulsos de ecualización
                bcf     flags,vertical,0       ;y se suprimen los pulsos de sincronismo vertical
                retfie  1


;------------------------------------------------------------
;                      programa principal
;------------------------------------------------------------

programa        clrf    TRISA,0                ;Todos los puertos como salidas
                clrf    TRISB,0
                clrf    TRISC,0
                clrf    TRISD,0
                clrf    TRISE,0
                clrf    LATE,0                 ;Pone a cero el puerto E de 3 pines
                movlw   0x07                   ;Configura los puertos
                movwf   ADCON1,0               ;como E/S digitales
                bsf     sinc                   ;Pone en alto la salida de sincronismo
                lfsr    0,0x100                ;Carga el selector de registros 0 con el valor 0x100
                bcf     INTCON,GIE,0           ;Desactiva todas las interrupciones.

cuadros_patron  movlw   b'10101010'            ;Carga el dibujo a mostrar
                movwf   dato_ram,0             ;en la ram
                lfsr    1,0x100                ;Carga el selector de registros 1 con el valor 0x100
                movlw   .64                    ;64 bits de alto
                movwf   contador2,0
bucle_ext       movlw   .16                    ;16 Bytes de ancho (128 bits)
                movwf   contador,0
bucle_int       movff   dato_ram,POSTINC1      ;Carga el dato al registro apuntado por fsr1 e incrementa el puntero
                decfsz  contador,f,0           ;Decrementa el contador, si es cero termina el bucle interno
                goto    bucle_int
                comf    dato_ram,f,0           ;En la siguiente línea invierte el patrón del dibujo
                decfsz  contador2,f,0          ;Decrementa el contador2, si es cero termina el bucle externo
                goto    bucle_ext

                clrf    flags,0                ;Ninguna bandera activa
                bsf     flags,ecualizacion,0   ;solo la de ecualización
                setf    TMR0H,0                ;Primero se debe cargar TMR0H que es un buffer
                movlw   .232                   ;y se actualiza con la escritura de TMR0L
                movwf   TMR0L,0                ;Ajuste de TMR0 para 2,3 uS (0xFFE8)
                movlw   b'10100000'            ;Activa la interrupción por TMR0
                movwf   INTCON,0
                movlw   b'10001000'            ;Habilita TMR0 sin preescalado
                movwf   T0CON,0                ;Origen de la señal de reloj de tmr0 = reloj interno
                clrf    LATE,0                 ;Pone a cero la señal de video
                bcf     sinc                   ;Primer pulso de preecualización, pone en bajo dicho pin

bucle_princ     btfsc   flags,funciones,0      ;Si el flag está activo
                call    glcd                   ;realiza las funciones de una GLCD
                goto    bucle_princ

glcd            nop                            ;Proximamente....
                return

                end

