Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

24/09/2010 #1


Ayuda con codigo ASM para PIC
Hola gente del foro...

Estoy por construir el siguiente proyecto con PIC: http://users.skynet.be/fc052475/propellerclock/

Como verán este reloj emplea un control remoto infrarojo para comandar las funciones del reloj que cumple con el protocolo RC5 de philips. Ahora bien, yo usaría otro control remoto distinto al que usó el autor (control de un proyector). Mas precisamente, mi idea es emplear un control universal.

Les consulto, porque no poseo demasiado conocimientos de programación, si dejando el siguiente codigo fuente como está sin variaciones yo podría utilizar un control remoto universal para comandar al PIC teniendo en cuenta que dicho codigo fuente hace referencia a un control remoto de un proyector/cañon?. El codigo es el siguiente:


; Define RC5 address of Remote Control

RemoteAddr EQU 0x06

; Definition of Keys and key-codes on my remote control

NUM_0 EQU 0x00
NUM_1 EQU 0x01
NUM_2 EQU 0x02
NUM_3 EQU 0x03
NUM_4 EQU 0x04
NUM_5 EQU 0x05
NUM_6 EQU 0x06
NUM_7 EQU 0x07
NUM_8 EQU 0x08
NUM_9 EQU 0x09
FREEZE EQU 0x5D
PAUSE EQU 0x30
STANDBY EQU 0x0C
MUTE EQU 0x0D
HELP EQU 0x2F
TEXT EQU 0x0F
VOL_UP EQU 0x10
VOL_DN EQU 0x11
BRI_UP EQU 0x12
BRI_DN EQU 0x13
SAT_UP EQU 0x14
SAT_DN EQU 0x15
BAS_UP EQU 0x16
BAS_DN EQU 0x17
TRE_UP EQU 0x18
TRE_DN EQU 0x19
BAL_RI EQU 0x1A
BAL_LE EQU 0x1B
CON_UP EQU 0x1C
CON_DN EQU 0x1D
HUE_UP EQU 0x27
HUE_DN EQU 0x1F
SHA_UP EQU 0x4D
SHA_DN EQU 0x4E
PHA_UP EQU 0x48
PHA_DN EQU 0x49
ADJUST EQU 0x52
EXIT EQU 0x53
ADDR EQU 0x54
ASTRSK EQU 0x77
ENTER EQU 0x57
F1 EQU 0x6B
F2 EQU 0x6C
F3 EQU 0x6D
F4 EQU 0x6E
F5 EQU 0x6F
CUR_UP EQU 0x50
CUR_RI EQU 0x56
CUR_DN EQU 0x51
CUR_LE EQU 0x55

; Definition of Functions on the Propeller clock

SEC_UP EQU VOL_UP
SEC_DN EQU VOL_DN
MIN_UP EQU BAL_RI
MIN_DN EQU BAL_LE
HOUR_UP EQU CON_UP
HOUR_DN EQU CON_DN
DAY_UP EQU BRI_UP
DAY_DN EQU BRI_DN
MON_UP EQU SAT_UP
MON_DN EQU SAT_DN
YEAR_UP EQU HUE_UP
YEAR_DN EQU HUE_DN
INDEX_UP EQU PHA_UP
INDEX_DN EQU PHA_DN

BlueLine EQU F1
DigiTime EQU F2
DigiDate EQU F3
AnaTime EQU F4
TTicks EQU F5

DM EQU ASTRSK ;Demo Mode
TextMode EQU TEXT


Este codigo fuente es el que según su autor se debería modificar si se utilizara otro control remoto. Mi otra duda es si este codigo se debe modificar debido a que se utiliza otro control con direcciones distintas o si se modifica debido a la disposición de las teclas en el control? (que varian de un control a otro). Al pic le basta con recibir en su entrada infraroja el codigo RC5 y decodificar los comandos solamente, o este codigo hace referencia a un control con direcciones especificas?. Espero puedan ayudarme porque es lo unico que me falta definir para armarlo y por mas que he leido bastante no puedo comprender exactamente como hace el pic para leer los datos del control.
Por las dudas ya les digo que me he leido bien el protocolo RC5 y como funciona, mi problema ahora es la programación.

Agradezco a todos.

24/09/2010 #2

Avatar de ByAxel

Respuesta: Ayuda con codigo ASM para PIC
Hola.
Eso son solo declaraciones de variables o constantes, modificar algo no le hace nada al programa porque no sabemos que le hace si cambiamos algo, como usa esas variables y constantes??...

Pero igual, cual es la web?, que pic usa?... en mi opinión:

FREEZE EQU 0x5D
PAUSE EQU 0x30
STANDBY EQU 0x0C
ADJUST EQU 0x52

son los que llaman la atención pero no se sabe como es que lo usa el autor, mas info!!!.

saludos.
24/09/2010 #3

Avatar de el-rey-julien

Respuesta: Ayuda con codigo ASM para PIC
se debe modificar debido a que se utiliza otro control con direcciones distintas o si se modifica debido a la disposición de las teclas en el control?
tu mismo diste la respuesta
se debe modificar debido a que se utiliza otro control con direcciones distintas
no porque las teclas están en distinta posición,
saludos

ByAxel dijo: Ver Mensaje
Hola.
Eso son solo declaraciones de variables o constantes, modificar algo no le hace nada al programa porque no sabemos que le hace si cambiamos algo, como usa esas variables y constantes??...

Pero igual, cual es la web?, que pic usa?... en mi opinión:

FREEZE EQU 0x5D
PAUSE EQU 0x30
STANDBY EQU 0x0C
ADJUST EQU 0x52

son los que llaman la atención pero no se sabe como es que lo usa el autor, mas info!!!.

saludos.
lo que no explico el compañero es que la parte del asm del control remoto ,esta en otro asm que lo usa a modo de librería ,el que ay que modificar es uno que se llama ,,,,,,,,,,despues lo pongo ,de momento se me olvido como se llamaba el asm,,,

ya me acorde el asm a modificar en donde esta lo ''jugoso'' se llama Keys.asm
el rey julien saluda ,
PD:
que me corrija si estoy equivocado
el rey julien saluda 2
24/09/2010 #4


Respuesta: Ayuda con codigo ASM para PIC
Hola, gracias por la respuesta...

A ver, la pagina del proyecto es la que puse mas arriba, aqui va de nuevo: http://users.skynet.be/fc052475/propellerclock/

Ese codigo que puse mas arriba corresponde al Keys.asm, este codigo va "unido" a otro que se llama prop.asm que tiene definida todas las funciones del reloj. O sea, en el prop.asm se invoca al Keys.asm y a otro mas llamado CharGen.asm. Al final les adjunto un archivo comprimido con los 3 codigos fuente. Pero el que según su autor se debe modificar es el Keys.asm cuyo codigo fuente es el que publiqué mas arriba.

el-rey-julien: Tu respuesta me desanimo un poco, porque si hay que modificar el codigo asembler para el nuevo control estoy hasta las manos porque no manejo programación en asembler. Podrias indicarme como modificar el codigo para que acepte un control estandar (el de una tele supongamos) y asi emplear un control remoto del tipo universal?.

Mil gracias por sus respuestas.

Saludos.

PD: Si bien no se programar (pero alguna vez estudie programacion en visual y tengo una leve nocion), he leido los codigo fuente y me pude dar cuenta que son declaraciones de variables las del keys.asm. Se declaran las teclas del control que utiliza el autor y luego segun lo que interprete se asignan funciones a esas teclas para controlar funciones especificas del reloj.
Por otro lado, en el prop.asm encontré la parte en donde están las rutinas de incialización para la decodificación del protocolo RC5, pero repito, no se donde debo modificar para alterar las direcciones del control remoto. Sepan disculpar mi ignorancia.

Acá pongo el codigo fuente principal asi resulta mas comodo y no tener que descargar el fichero que dejé mas arriba:
Código:
;************************************************************************
; Following the example of Bob Blick's original propeler clock I made     *
; my own version of this fancy clock and have re-written the code from    *
; scratch. I used a bit more powerfull version of PIC cpu and added     *
; these features:                            *        
;  - the clock keeps time AND DATE                           *
;  - can display analog hands or digital time and mixed mode where    *
;    time is displayed as analog hands and digital date            *
;  - setting the time/date or switch mode is done by RC5 remote control    *
;  - possibility to display a message programmed in ROM or EEPROM    *        
;                                                                     *
;************************************************************************
;                                                                   *
;    Filename:        prop.asm                                            *
;    StartDate:     02/12/2001                                            *
;    LastUpdate:    09/02/2003                        *
;    File Version:  1.06                                                  *
;                                                                         *
;    Author:        Soubry Henk                                           *
;    Company:       Soubry Software Service                               *
;                                                                         *     
;                                                                         *
;************************************************************************
;                                                                        *
;    Files required: CharGen.asm                                          *
;                    Keys.asm                                                *
;                                                                         *
;                                                                         *
;************************************************************************
;                                                                         *
;    Notes:                                                               *
;        Pin assignment                                                    *
;              Port A                                                 *
;        0 = inner display led (because RB0 is index)        *                        
;               1 = analog outer led                       *                         
;               2 = Ir receiver                                           *
;               3 = OSC Calibration output                                *
;               4 = unused                                         *
;              Port B                             *
;        0 = index                                                    *
;               1..6 = Display led's (1=inner, 6=outer                    *
;               7 = analog inner led's                  *
;                                                                         *
;************************************************************************


    list    p=16f628            ; list directive to define processor
    #include <p16f628.inc>        ; processor specific variable definitions
    #include "CharGen.asm"
    #include "Keys.asm"
    
    __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _MCLRE_OFF & _LVP_OFF


;***** VARIABLE DEFINITIONS

; #define    MotorCounterClockWise    ; un-comment this line if motor is running counter clockwise
; #define     ReversTextScroll    ; un-comment this line if your text must scroll from left to right (e.g. Hebrew)

;Display memory
DispI        EQU     0x20      ; 40 bytes from 0x20 -> 0x48
DispII        EQU     0xA0      ; 80 bytes from 0xA0 -> 0xF0

;Vars in shared memory. This memory is available from any bank
  cblock    0x77
    Scratch        ; memory locations for general use
    Scratch2    ;
    Scratch3    ;
    Scratch4    ;                    
    w_temp        ; variable used for context saving 
    status_temp    ; variable used for context saving
    fsr_temp    ; variable used for context saving
    flags        ; all sorts of flags 
    flags2        ; 
  endc
    
;Vars for display timing routines and interrupts
  cblock    0x48
    PeriodCnt_H    ; 16 bit counter counts number of interrupt
    PeriodCnt_L    ; between index-puls (one revolution)
    StorePCnt1_H    ; first 16 bit storage for PeriodeCounter
    StorePCnt1_L    ;
    StorePCnt2_H    ; second 16 bit storage for PeriodeCounter
    StorePCnt2_L    ; 
    SubSec_H    ; 16 bit sub-second counter
    SubSec_L    ; there are 2500 sub-seconds in 1/2 second

    PixelWidth    ; Pixel-width = number of interrupts in one ON pixel
    PixelOff    ; 8 bit down-counter to time PixelWidth
            
    PixelPitch_H    ; PixelPitch = 16 bit number of interrupts between two pixel
    PixelPitch_L    ; 
    PixelPitch_F    ; Fraction of PixelPitch needed for accuracy and to avoid jitter

    NewPPitch_H    ; New pixel pitch calculated by main programm, will be
    NewPPitch_L    ; copied to PixelPithc by interrupt routine
    NewPPitch_F    ; 

    NextPixel_H    ; Next pixel @ PeriodCnt = NextPixel
    NextPixel_L    ;
    NextPixel_F    ;
    RoundedNext_L    ; RoundedNext = Round(NextPixel)
    RoundedNext_H    ;
        
    iFSR        ; copy of FSR used by interrupt routine
    DispOffset    ; Display offset compared to indexpuls

    TmrScroll    ; Count Down timer for scroll delay
    DemoCnt        ; Counter for demo mode

;Vars for time-keeping            
    Hour        ; looks obvious, doesn't it !
    Minute        ;
    Second2        ; 0..119 counting half seconds
    Day        ;
    Month        ;
    Year        ;
    DMon        ; days in current Month        
            
;Vars for building display-content
    timeticks    ; index for 5min time tick
    BCD        ; Binary coded decimal
    digitindex    ; index digit to display
    dotindex    ; index dot to display
    dpi        ; 0..119 display index for main program
    tdd        ; temporary display data
    PrevIndex    ; stores state of index

;Vars for RC5 decoding        
    RC5_flags    ;
    RC5_Tmr        ;
    RC5_BitCnt    ;
    RC5_Addr    ;
    RC5_Cmd        ;
    RC5_Cmd2    ; storage for previous cmd
            
  endc

    IF RC5_Cmd2 >= Scratch
        ERROR "To many variables used"
    ENDIF

; start a new block of vars in bank2
; these are vars for the char printing routines
  cblock    0x120
    ch_dot_point_H    ; pointer the the current dot# in a character    
    ch_dot_point_L    ; points the the chargenerator table
    ch_dot_index    ; index of dot# in a char, 0..5
    ch_num        ; char number
    ch_blanking    ; counter for blanking the display when scrolling text
  endc

;**********************************************************************
; give meaningfull names to the scratch locations

; for the 16bit/8bit divide routine
DIV_HI        EQU    Scratch    ; 16 bit Divisor
DIV_LO        EQU    Scratch2; needed for 16 bit / 8 bit division
DIV_Q        EQU    Scratch3; 
DIVISOR        EQU    Scratch4; Divisor

;**********************************************************************
; define Port bits
bIndexPuls    EQU    0
bOuterLED    EQU    1
bRC5inp        EQU    2
bCalibration    EQU    3

; define flag bits
bDigitStart    EQU    0
bNewPCnt    EQU    1
bNewTime    EQU    2
bNewPPitch    EQU    3
bShowHand    EQU    4
bShowDTime    EQU    5
bShowDDate    EQU    6
bShowTicks    EQU    7

; define flag2 bits
bText        EQU    4
bScrollOn    EQU    5
bDemo        EQU    6

;**********************************************************************

#define     IndexPuls    PORTB,bIndexPuls
#define     OuterLED    PORTA,bOuterLED
#define     RC5inp        PORTA,bRC5inp
#define        Calibration    PORTA,bCalibration

#define        digitstart    flags,bDigitStart
#define        NewPCnt        flags,bNewPCnt
#define        NewTime        flags,bNewTime
#define        NewPPitch    flags,bNewPPitch
#define        ShowHand    flags,bShowHand
#define        ShowDTime    flags,bShowDTime
#define        ShowDDate    flags,bShowDDate
#define        ShowTicks    flags,bShowTicks

#define     fOuterLED    flags2,bOuterLED
#define        fText        flags2,bText
#define        fScrollOn    flags2,bScrollOn
#define        fDemo        flags2,bDemo

#define        RC5_WaitStart    RC5_flags,0
#define        RC5_DataReady    RC5_flags,1
#define        RC5_prev_inp    RC5_flags,2
#define        RC5_Idle    RC5_flags,3
#define        RC5_HalfBit    RC5_flags,4
#define        RC5_ReSynced    RC5_flags,5
#define        PStorage    RC5_flags,6
#define        reserved    RC5_flags,7


;******************************************************************************
;    Define macro's to Save w and Status register during interrupt
;******************************************************************************
push    macro
    movwf    w_temp
    swapf    w_temp, f
    swapf    STATUS, w
    movwf    status_temp
    endm
;
;******************************************************************************
;    Define macro's to Reload w and Status register after interrupt
;******************************************************************************
pop    macro
    swapf    status_temp, w
    movwf    STATUS
    swapf    w_temp, w
    endm
;
;******************************************************************************
;    Define macro's for a Select - Case 
;******************************************************************************
select_w    macro 
sel_last    set 0                     ;setup variable only 
             endm 
case         macro   val
            xorlw   val ^ sel_last 
        btfsc    STATUS,Z
sel_last set val 
             endm 

;
;******************************************************************************
;    Define EEPROM content for initial message
;******************************************************************************

    ORG     0x2100           ; Start off EEPROM
    de    "  ===> This version of Bob Blick's Propeller Clock was build and programmed by Henk Soubry  ",0x83,0x84,"<===              "
    de    0x00


;**********************************************************************
        ORG     0x000           ; processor reset vector
        goto    main            ; go to beginning of program

        ORG     0x004           ; interrupt vector location        
        push            ; context switching        
        bcf    STATUS,RP0    ; select bank 0 for interrupt stuff
        bcf    STATUS,RP1    ; the 'pop' will restore current bank status
        
;**********************************************************************
        
INT_RB0        btfss    INTCON,INTF    ; interrupt on RB0?
        goto    INT_TMR0    ; nope, TMR0 is next

;----------    RB0 interrupt ! == Index Sensor
        movlw    0xff        ;
        movwf    TMR0        ; force TMR0 to 0xFF

        btfss    PStorage    ;
        goto    Store2        ; goto second storage
        movf    PeriodCnt_H,w    ; 
        movwf    StorePCnt1_H    ; StorePCnt = PeriodCnt
        movf    PeriodCnt_L,w    ;
        movwf    StorePCnt1_L    ;
        bcf    PStorage    ;
        goto    StoreDone    ;
Store2
        movf    PeriodCnt_H,w    ; 
        movwf    StorePCnt2_H    ; StorePCnt = PeriodCnt
        movf    PeriodCnt_L,w    ;
        movwf    StorePCnt2_L    ;
        bsf    PStorage    ;
StoreDone:    
        bsf    NewPCnt        ; signal new stored PeriodCount to main program
        clrf    PeriodCnt_H    ; PeriodCnt = 0
        clrf    PeriodCnt_L    ;
        clrf    NextPixel_H    ; Next_Pixel = 0 (thus now)
        clrf    NextPixel_L    ;
        clrf    NextPixel_F    ;
        clrf    RoundedNext_L    ; RoundedNext = 0
        clrf    RoundedNext_H    ;
        clrf    PixelOff    ; display next pixel no matter what.
        movf     DispOffset,w    ; iDispIndex = DispOffset
        movwf    iFSR        ;
        btfss    NewPPitch    ; is there a new value calculated by main prg?
        goto    lINT_RB0    ; no, continue
        movf    NewPPitch_H,w    ; PixelPitch = NewPPitch
        movwf    PixelPitch_H    ; 
        movf    NewPPitch_L,w    ; 
        movwf    PixelPitch_L    ; 
        movf    NewPPitch_F,w    ; 
        movwf    PixelPitch_F    ; 
        bcf    NewPPitch    ;
lINT_RB0
        bcf    INTCON,INTF    ; clear RB0 interrupt flag        
        goto    lDisp_1        ; do display routine but skip Period increment
;--------
INT_TMR0    btfss    INTCON,T0IF    ; Test if a TMR0 interrupt occured
        goto    INT_TMR2    ; nope, TMR2 is next
        
        bsf    TMR0,7        ; TMR0 = TMR0 + 128 => Test to double TMR0 speed

        incfsz    PeriodCnt_L,f    ; Increment 16-bit period counter
        goto    lDisp_1        ;
        incfsz    PeriodCnt_H,f    ;
        goto    lDisp_1        ; if overflow in MSB period counter = speed to low
        bsf    STATUS,RP0    ; Bank1
        movlw    0xFF        ; disable LED outputs
        movwf    TRISB        ;
        movlw    b'11110111'    ; leave PORTA.3 as output
        movwf    TRISA        ;
        bcf     STATUS,RP0    ; Bank0

lDisp_1        movf    RoundedNext_L,w    ; PeriodCnt = RoundedNextPixel ?
        xorwf    PeriodCnt_L,w    ;
        btfss    STATUS,Z    ;
        goto    lPixelOn    ; no, check if there is a pixel on
        movf    RoundedNext_H,w    ;
        xorwf    PeriodCnt_H,w    ;
        btfss    STATUS,Z    ;
        goto    lPixelOn    ; no,  check if there is a pixel on
                    ; yes, display next pixeldata
        movf    FSR,w        ; context saving
        movwf    fsr_temp    ;
        
        movf    iFSR,w        ; load new memory pointer in w
        movwf    FSR        ; load File Select register with Display Index
        movf    INDF,w        ; PortB = DisplayData(index)
        movwf    PORTB        ; 
        bcf    PORTA, 0    ; dispatch bit 0 to PORTA
        btfsc    INDF, 0
        bsf     PORTA, 0    
        
#ifdef MotorCounterClockWise
        decf    iFSR,w        ; increment i(nterrupt)FSR
        call    CheckDecrement    ; check correct progress of diplay memory pointer
#else
        incf    iFSR,w        ; increment i(nterrupt)FSR
        call    CheckIncrement    ; check correct progress of diplay memory pointer
#endif
        movwf    iFSR        ;                

        movf    fsr_temp,w    ; context recall
        movwf    FSR        ;

        movf    PixelPitch_F,w     ; NextPixel = NextPixel + PixelPitch
        addwf    NextPixel_F,f    ;
        btfss    STATUS,C    ;
        goto    no_overflow    ;
        incf    NextPixel_L,f    ; fraction overflow, add 1 to Low byte
        btfsc    STATUS,Z    ;
        incf    NextPixel_H,f    ; low byte roll-over, add 1 to High byte
no_overflow:    movf    PixelPitch_L,w    ;
        addwf    NextPixel_L,f    ;
        btfsc    STATUS,C    ;
        incf    NextPixel_H,f    ; low byte overflow, add 1 to High byte
        
        movf    NextPixel_L,w    ; RoundedNext = NextPixel
        movwf    RoundedNext_L    ;
        movf    NextPixel_H,w    ;
        movwf    RoundedNext_H    ;
        btfss    NextPixel_F,7    ; IF NextPixel_Fraction >= 128 then
        goto    NotRoundUp        ;        
        incf    RoundedNext_L,f    ; ROUND UP
        btfsc    STATUS,Z    ; 
        incf    RoundedNext_H,f    ;
NotRoundUp:
        movf    PixelWidth,w    ;
        movwf    PixelOff    ; PixelOff = PixelWidth    

        goto    lDispDone    ;    

lPixelOn    movf    PixelOff,w    ; Is there a pixel on?
        btfsc    STATUS,Z    ; PixelOff = 0 ?
        goto    lDispDone    ; no, jump

        decfsz    PixelOff,f    ; pixel is on, countdown
        goto    lDispDone    ;
        movlw    0x00
        movwf    PORTB        ; turn off display LED's
        bcf    PORTA,0        ; also turn of PortA LED
    
lDispDone        
        bcf    INTCON,T0IF    ; clear TMR0 interrupt flag before return

;--------
INT_TMR2    btfss    PIR1,TMR2IF    ; interrupt on TMR2?
        goto    INT_EXIT    ; nope, interrupt is done!        
                
        ; do the TMR2 stuff, we get here every 200uSec

        ; toggle PORTA.3, use scope or freq counter to calibrate to 2.5 kHz
        movf    PORTA,w        ;
        xorlw   1 << bCalibration    ;
        andlw    1 << bCalibration    ;
        bcf    Calibration    ; Toggle PORTA.3
        btfss    STATUS,Z    ; 
        bsf    Calibration    ;

        ; Text-scroll timer
        movf    TmrScroll,f    ; TmrScroll == 0 ?
        btfss    STATUS,Z    ;
        decf    TmrScroll,f    ; no, TmrScroll --

        ; real time sub-second counter
        incfsz    SubSec_L,f    ; Increment 16-bit Sub Second counter
        goto    lTime_1        ; stil counting
        incfsz    SubSec_H,f    ;
        goto    lTime_1        ; stil counting
        
        incf    Second2,f    ; 1/2 second has passed
        bsf    NewTime        ; signal new time to main program
        movlw    0x3C        ; reload counter SubSecond = 0x10000 - .2500 = 0xF63C
        movwf    SubSec_L    ;
        movlw    0xF6        ;
        movwf    SubSec_H    ;
        
lTime_1        ; start RC5 stuff here
        btfsc    RC5_DataReady    ;
        goto    lRC5_Exit    ;
        btfss    RC5_Idle    ;
        goto    lRC5_Not_Idle    ;
        decfsz    RC5_Tmr    ,f    ;
        goto    lRC5_Exit    ;        
        btfsc    RC5inp        ; test input
        bcf    RC5_Idle    ; input = high, cancel Idle state
        incf    RC5_Tmr,f    ; continue Idle state until input = high
        goto    lRC5_Exit    ;        
lRC5_Not_Idle    
        btfss    RC5_WaitStart    ;
        goto    lRC5_ReSync    ;
lRC5WaitStart    btfsc    RC5inp        ; test input
        goto    lRC5_Exit    ; no startbit
        bcf    RC5_WaitStart    ; start received
        movlw    .6        ;
        movwf    RC5_Tmr        ;
        movlw    .13        ; 13 bits to receive
        movwf    RC5_BitCnt    ;
        clrf     RC5_Addr    ;
        clrf    RC5_Cmd        ;
        goto    lRC5_Exit    ;
lRC5_ReSync                ;
        movf    PORTA,w        ;
        xorwf    RC5_flags,w    ;
        andlw    0x04        ;
        btfsc    STATUS,Z    ;
        goto    lRC5_no_sync    ;
        bsf    RC5_ReSynced    ;
        movlw    .6        ; re-sync the timer
        btfss    RC5_HalfBit    ;
        movlw    .2        ;
        movwf    RC5_Tmr        ;
        bcf    RC5_prev_inp    ; clear previous input
        btfsc    RC5inp        ;
        bsf    RC5_prev_inp    ;
        
lRC5_no_sync    btfsc    RC5_HalfBit    ;
        goto    lRC5_2nd_Half    ;

lRC5_1st_Half    decfsz    RC5_Tmr,f    ;
        goto    lRC5_Exit    ;    
        bcf    STATUS,C    ;
        btfsc    RC5inp        ;
        bsf    STATUS,C    ; C = RC5inp
        rlf    RC5_Cmd,f    ;
        rlf    RC5_Addr,f    ; 
        bsf    RC5_HalfBit    ; indicate that the first half bit is received
        bcf    RC5_ReSynced    ;
        movlw    .4        ;
        movwf    RC5_Tmr        ; reload timer 
        goto    lRC5_Exit
lRC5_2nd_Half   
        btfsc    RC5_ReSynced    ;
        goto    lReSyncOK    ;
        decfsz    RC5_Tmr,f    ;
        goto    lRC5_Exit    ; 
lRC5_Error    clrf    RC5_flags    ;
        bsf    RC5_WaitStart    ;
        bsf    RC5_Idle    ;
        movlw    .128        ;
        movwf    RC5_Tmr        ;
        goto    lRC5_Exit    ;        
lReSyncOK    
        ; test second bit half
        bcf    RC5_HalfBit    ;
        decfsz    RC5_BitCnt,f    ;
        goto    lRC5_Exit    ;
        rlf    RC5_Cmd,f    ; Shift bit right to compleet Addr
        rlf    RC5_Addr,f    ;
        rlf    RC5_Cmd,f    ;
        rlf    RC5_Addr,f    ;
        bcf    STATUS,C    ;
        btfss    RC5_Addr,6    ;
        bsf    STATUS,C    ; C = Inv Bit6 in RC5_Addr
        rrf    RC5_Cmd,f    ;
        bcf    STATUS,C    ;
        btfsc    RC5_Addr,5    ;
        bsf    STATUS,C    ; C = ToggleBit in RC5_Addr
        rrf    RC5_Cmd,f    ;
        movlw    0x1F        ;
        andwf    RC5_Addr,f    ;
        bsf    RC5_DataReady    ;
lRC5_Exit            
        bcf    PIR1,TMR2IF    ; clear TMR2 interrupt flag
;--------
INT_EXIT        
        pop            ; restore conext for main program
                    ; this will also restore bank selection
        retfie                  ; return from interrupt

;**********************************************************************

div16X8        ; DIV_HI and DIV_LO / DIVISOR.  result to DIV_Q
        ; remainder in DIV_LO
        ; does not deal with divide by 0 case

        clrf     DIV_Q
div_1
        movf     DIVISOR, W
        subwf     DIV_LO, F
        btfss     STATUS, C    ; if positive skip
        goto     div_borrow
        goto     div_2
div_borrow
        movlw     .1
        subwf     DIV_HI, F    ; DIV_HI = DIV_HI - 1
        btfss     STATUS, C    ; if no borrow occurred
        goto    div_done    
div_2
        incf DIV_Q, F
        goto div_1
div_done
        movf DIVISOR, W        ; re-add DIVISOR to DIV_LO to get
        addwf DIV_LO, F        ; remainder in DIV_LO
    
        retlw    0

CalcPixelPitch    ; thats a hard one. We have to divide by 120 !!!
        ; PixelPitch = PeriodCnt / 120
        
        movf     StorePCnt1_H,w    ; check if two period counters
        xorwf    StorePCnt2_H,w    ; are the same. If not, don't
        btfss    STATUS,Z    ; calculate new pixelpitch because
        goto    CalcDone    ; the rotation speed was not stable
        movf    StorePCnt1_L,w    ;
        xorwf    StorePCnt2_L,w    ;
        btfss    STATUS,Z    ;
        goto    CalcDone    ;        

        clrf    DIV_HI        ; Divisor = PeriodCount_H
        movf    StorePCnt1_H,w    ;
        movwf    DIV_LO        ; 
        movlw    .120
        movwf    DIVISOR
        
        call     div16X8
        
        movf    DIV_Q,w        ; store result in High byte
        movwf    NewPPitch_H    ;
        movf    DIV_LO,w    ; shift remainder to DIV_HI
        movwf    DIV_HI        ;
        movf    StorePCnt1_L,w    ;
        movwf    DIV_LO        ;
        
        call    div16X8
        
        movf    DIV_Q,w        ; store result in Low byte
        movwf    NewPPitch_L    ;
        movf    DIV_LO,w    ; shift remainder to DIV_HI
        movwf    DIV_HI        ;
        clrf    DIV_LO        ;
        
        call    div16X8

        movf    DIV_Q,w        ; store result in Fraction byte
        movwf    NewPPitch_F    ;

        ; start calculation for pixel width
        clrc            ; Clear Carry
        rrf    NewPPitch_L,w    ;
        movwf    PixelWidth    ; PixelWidth = NewPPitch_L / 2
        movwf    Scratch        ;
        clrc
        rrf    Scratch,f    ;
        clrc    
        rrf    Scratch,w    ; w = NewPPitch / 8
        addwf    PixelWidth,f    ; PixelWidth = NewPPitch * 5 / 8

        bsf    STATUS,RP0    ; Bank1
        movlw    0x01        ; 
        movwf    TRISB        ; PortB1..7 as output, PortB0 as input
        movlw    b'11110100'    ; Port A bit 0, 1 and 3 as output
        movwf    TRISA        ; Port A bit 2, 3, 4 as input
        bcf    STATUS,RP0    ; Bank0

        btfss    fOuterLED    ;
        bcf    OuterLED    ; set Port for Outerled equal to fOuterLED
        btfsc    fOuterLED    ;
        bsf    OuterLED    ;

NotON:
        bsf    NewPPitch    ; signal new Pitch value to interrupt routine
CalcDone:
        bcf    NewPCnt        ; clear flag        

        retlw     0

;******************************************************************************
;    Check correct progress of sec,min,hour,day,month,year
;******************************************************************************

TimeCheck    ; second variable is changed, check if an overflow
        ; is generated to minute, hour, day,...

        movlw    .120        ; 
        subwf    Second2,w    ; Second2 < 120 ? (counting 120 half seconds)
        btfss    STATUS,C        ; if second2 < 120 then c=0 (borrow)
        goto    lMinute        ; 
                    ; yes, Second >= 120
        movwf    Second2        ; Second = Second - 120
        incf    Minute,f    ; Minute = Minute + 1
lMinute        
        movlw    .60        ; 
        subwf    Minute,w    ; Minute < 60 ?
        btfss    STATUS,C        ; if Minute < 60 then c=0 (borrow)
        goto    lHour        ; 
                    ; yes, Minute >= 60
        movwf    Minute        ; Minute = Minute - 60
        incf    Hour,f        ; Hour = Hour + 1
lHour
        movlw    .24        ; 
        subwf    Hour,w        ; Hour < 24 ?
        btfss    STATUS,C        ; if Hour < 24 then c=1 (borrow)
        goto    lDay        ; 
                    ; yes, Hour >= 24
        movwf    Hour        ; Hour = Hour - 24
        incf    Day,f        ; Day = Day + 1
lDay        
        movlw    .32        ; DMon = 32
        movwf    DMon        
        movf    Month,w        ; 
        xorlw    .4        ; test for april
        btfsc    STATUS,Z    ;
        decf    DMon,f        ; Dmon = Dmon - 1 
        xorlw    .6 ^ .4        ; test for juni
        btfsc    STATUS,Z    ;
        decf    DMon,f        ; Dmon = Dmon - 1 
        xorlw    .9 ^ .6        ; test for september
        btfsc    STATUS,Z    ;
        decf    DMon,f        ; Dmon = Dmon - 1 
        xorlw    .11 ^ .9    ; test for november
        btfsc    STATUS,Z    ;
        decf    DMon,f        ; Dmon = Dmon - 1 
    
        xorlw    .2 ^ .11    ; Month = Februari ?
        btfss    STATUS,Z    ; 
        goto    lNotFeb        ; continue
        movlw    .29        
        movwf    DMon        ;
        btfsc    Year,0        ;
        goto    lNotFeb        ;
        btfsc    Year,1        ;
        goto    lNotFeb        ;
        incf    DMon,f        ; Year is LeapYear, inc DMon for Feb            
    
lNotFeb
        movf    DMon,w        ; w = DMon
        subwf    Day,w        ; Day < DMon ?
        btfss    STATUS,C        ; if Day < DMon then c=1 (borrow)
        goto    lMonth        ; 
        
        movwf    Day        ; Day = (Day - DMon)+1
        incf    Day,f        ; 
        incf    Month,f        ; Month = Month + 1
        
lMonth
        movlw    .13        ; 
        subwf    Month,w        ; Month < 13 ?
        btfss    STATUS,C        ; if Month < 13 then c=0 (borrow)
        goto    lYear        ; 
                    
        movwf    Month        ; Month = Month - 12
        incf    Month,f        ;
        incf    Year,f        ; Year = Year + 1
    
lYear        
        movlw    .100        ;
        subwf    Year,w        ; Year < 100 ?
        btfsc    STATUS,C    ; 
        clrf    Year        ;        

        bcf    NewTime        ;
        retlw     0


;******************************************************************************
;    Routines to display Time and Date
;******************************************************************************

; CHARACTER LOOKUP TABLE
; set=LED on, clear=LED off
Char_tbl1
       addwf   PCL,f

    DT  0x3E , 0x41 , 0x41 , 0x41 , 0x3E ; "0"
;    DT  0x3E , 0x45 , 0x49 , 0x51 , 0x3E ; "0"
    DT  0x00 , 0x21 , 0x7F , 0x01 , 0x00 ; "1"
    DT  0x21 , 0x43 , 0x45 , 0x49 , 0x31 ; "2"
    DT  0x42 , 0x41 , 0x51 , 0x69 , 0x46 ; "3"
    DT  0x0C , 0x14 , 0x24 , 0x7F , 0x04 ; "4"
    DT  0x72 , 0x51 , 0x51 , 0x51 , 0x4E ; "5"
    DT  0x1E , 0x29 , 0x49 , 0x49 , 0x06 ; "6"
    DT  0x40 , 0x47 , 0x48 , 0x50 , 0x60 ; "7"
    DT  0x36 , 0x49 , 0x49 , 0x49 , 0x36 ; "8"
    DT  0x30 , 0x49 , 0x49 , 0x4A , 0x3C ; "9"
    DT  0x00 , 0x36 , 0x36 , 0x00 , 0x00 ; ":"
    DT  0x00 , 0x00 , 0x00 , 0x00 , 0x00 ; " "
Char_tbl1_end

;-flipped digits upside down and mirrored
;-needed for the bottom display
Char_tbl2
       addwf   PCL,f
    DT 0x3E , 0x41 , 0x41 , 0x41 , 0x3E ; "0"    
    DT 0x00 , 0x40 , 0x7F , 0x42 , 0x00 ; "1"
    DT 0x46 , 0x49 , 0x51 , 0x61 , 0x42 ; "2"
    DT 0x31 , 0x4B , 0x45 , 0x41 , 0x21 ; "3"
    DT 0x10 , 0x7F , 0x12 , 0x14 , 0x18 ; "4"
    DT 0x39 , 0x45 , 0x45 , 0x45 , 0x27 ; "5"
    DT 0x30 , 0x49 , 0x49 , 0x4A , 0x3C ; "6"
    DT 0x03 , 0x05 , 0x09 , 0x71 , 0x01 ; "7"
    DT 0x36 , 0x49 , 0x49 , 0x49 , 0x36 ; "8"
    DT 0x1E , 0x29 , 0x49 , 0x49 , 0x06 ; "9"
    DT 0x00 , 0x08 , 0x08 , 0x08 , 0x00 ; "-"
    DT 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ; " "
Char_tbl2_end

    IF Char_tbl1 < 0x100
        ERROR "Tabel1 pages error"
        ENDIF

    IF Char_tbl2_end >= 0x200
        ERROR "Tabel2 pages error"
        ENDIF

;-------- Update Display memory with Hands

Hands        movlw    .30        ; difference in offset for hands and digital display
        subwf    dpi,w        ; scratch4 = dpi - 30
        btfss    STATUS,C    ; if scratch4 < 0 then 
        addlw    .120        ;    scratch4 = scartch4 + 120
        movwf    Scratch4    ; 

        movf    Second2,w    ;
        andlw    0xFE        ; filter out 1/2 second
        xorwf    Scratch4,w    ;
        btfsc    STATUS,Z    ;
        bsf    tdd,5    ;
        
        bcf    STATUS,C    ;
        rlf    Minute,w    ;
        xorwf    Scratch4,w    ;
        btfss    STATUS,Z    ;
        goto    lhour        ;
        movlw    B'10011111'    ;
        iorwf    tdd,f    ;    
        
lhour        movf    Hour,w        ;
        movwf    Scratch2    ; 
        bcf    STATUS,C    ; clear carry
        rlf    Scratch2,f    ; Scratch2 * 2
        rlf    Scratch2,f    ; Scratch2 * 2
        addwf    Scratch2,f    ; Scratch2 = 5 * hour
        rlf    Scratch2,f    ; Scratch2 = 10 * Hour
        movf    Minute,w    ; 
        movwf    Scratch        ; Scratch = minute
        movlw    .6        ;
l_hour_div6    subwf    Scratch,f    ;
        btfss    STATUS,C    ;
        goto    l_div6_done    ;
        incf    Scratch2,f    ; advance hour abit
        goto    l_hour_div6    ;
l_div6_done    movlw    .120        ; Scratch2 = (10 * Hour) + (Minute / 6)
l_120        subwf    Scratch2,f    ; 
        btfsc    STATUS,C    ; result > 0 ?
        goto    l_120
        addwf    Scratch2,w    ; result was negatif, re-add 120 and load it in w
        xorwf    Scratch4,w    ;
        btfss    STATUS,Z    ;
        return            ;
        movlw    B'10000001'    ;
        iorwf    tdd,f    ;    
        return

;-------- Update Display memory with Digital Time Display

DTime        movlw    .6        ;
        subwf    dpi,w        ;
        btfss    STATUS,C    ;
        return            ; display index < 6
        btfss    STATUS,Z    ;
        goto    l_DTime_1    ; display index > 6

        clrf    digitindex    ; display index = 6, load start parameters for
        clrf    dotindex    ; digit displaying

l_DTime_1    movlw    .54        ;
        subwf    dpi,w        ;
        btfsc    STATUS,C    ;
        return            ; display index >= 54 
        
        movf    dotindex,w    ;
        btfss    STATUS,Z    ;
        goto    l_DTime_3
        call    LoadBCDTime    ; dotindex = 0, load new digit
        movf    digitindex,w    ;
        btfss    STATUS,Z    ;
        goto    l_DTime_3
        movf    BCD,w        ; digit index = 0, 10 hour digit
        btfss     STATUS,Z    ;
        goto    l_DTime_3    ;
        movlw    0x37        ; 10 hour digit is zero, remove leading zero
        movwf    BCD        ; BCD = " "
l_DTime_3
        incf    dotindex,f    ;
        movlw    .6        ;
        xorwf    dotindex,w    ;
        btfss    STATUS,Z    ;
        goto    l_DTime_2    ; dotindex < 6, display data
        clrf    dotindex    ; dotindex = 6, reset dotindex and don't display 
        incf    digitindex,f    ; select next digit
        return            ; to get a gap between digits
l_DTime_2
        movf    BCD,w        ;
        bcf    PCLATH,1    ; set to page 0x100 for lookup
        bsf    PCLATH,0    
                call    Char_tbl1       ; get the dot pattern for this column
        movwf    tdd        ;
        incf    BCD,f        ;
        return            ;

;-------- Update Display memory with Digital Date Display

DDate        movlw    .66        ;
        subwf    dpi,w        ;
        btfss    STATUS,C    ;
        return            ; display index < 66
        btfss    STATUS,Z    ;
        goto    l_DDate_1    ; display index > 66

        clrf    digitindex    ; display index = 66, load start parameters for
        clrf    dotindex    ; digit displaying

l_DDate_1    movlw    .114        ;
        subwf    dpi,w        ;
        btfsc    STATUS,C    ;
        return            ; display index >= 114 
        
        movf    dotindex,w    ;
        btfsc    STATUS,Z    ;
        call    LoadBCDDate    ; dotindex = 0, load new digit

        incf    dotindex,f    ;
        movlw    .6        ;
        xorwf    dotindex,w    ;
        btfss    STATUS,Z    ;
        goto    l_DDate_2    ; dotindex < 6, display data
        clrf    dotindex    ; dotindex = 6, reset dotindex and don't display 
        incf    digitindex,f    ; select next digit
        return            ; to get a gap between digits
l_DDate_2
        movf    BCD,w        ;
        bcf    PCLATH,1    ; set to page 0x100 for lookup
        bsf    PCLATH,0    
                call    Char_tbl2       ; get the dot pattern for this column
        movwf    tdd        ;
        incf    BCD,f        ;
        return            ;
;--------
Conv2BCD    movwf    Scratch        ;
        clrf    Scratch2    ;
        movlw    .10        ;
l_bcd_1        subwf    Scratch,f    ;
        btfss    STATUS,C    ;
        goto    l_bcd_2
        incf    Scratch2,f    ;
        goto    l_bcd_1
l_bcd_2        addwf    Scratch,f    ;
        swapf    Scratch2,w    ;
        addwf    Scratch,w    ;
        return
;--------
LoadBCDDate    ; load BCD with date digits
        movf    digitindex,w    ;
        clrf    PCLATH
        bsf    PCLATH,1    ; set to page 0x200 for lookup
        addwf    PCL,f        ;
        goto    l_1year        ;
        goto    l_10year    ;
        goto    l_dot        ;
        goto    l_1mon        ;
        goto    l_10mon        ;
        goto    l_dot        ;
        goto    l_1day        ;
        goto    l_10day        ;

LoadBCDTime    ; load BCD with time digits
        movf    digitindex,w    ;
        clrf    PCLATH
        bsf    PCLATH,1    ; set to page 0x200 for lookup
        addwf    PCL,f        ;
        goto    l_10hour    ;
        goto    l_1hour        ;
        goto    l_dot        ;
        goto    l_10min        ;
        goto    l_1min        ;
        goto    l_dot        ;
        goto    l_10sec        ;
;        goto    l_1sec        ;

l_1sec        bcf    STATUS,C    ; Second2 / 2 = Second
        rrf    Second2,w    ;
        goto    l_convert    ;
l_1min        movf    Minute,w
        goto    l_convert    ;
l_1hour        movf    Hour,w
        goto    l_convert    ;
l_1day        movf    Day,w
        goto    l_convert    ;
l_1mon        movf    Month,w
        goto    l_convert    ;
l_1year        movf    Year,w
l_convert    call    Conv2BCD
        andlw    0x0F        ;
        movwf    BCD        ;        
        goto    l_mult5        ; multiply BCD by 5

l_10sec        bcf    STATUS,C    ; Second2 / 2 = Second
        rrf    Second2,w    ;
        goto    l_convert_swap    ;
l_10min        movf    Minute,w    ;
        goto    l_convert_swap    ;
l_10hour    movf    Hour,w
        goto    l_convert_swap    ;
l_10day        movf    Day,w
        goto    l_convert_swap    ;
l_10mon        movf    Month,w
        goto    l_convert_swap    ;
l_10year    movf    Year,w
l_convert_swap    call    Conv2BCD
        andlw    0xF0        ;        
        movwf    BCD        ;
        swapf    BCD,f        ;
        movf    BCD,w        ;
l_mult5        rlf    BCD,f        ; BCD x 2
        rlf    BCD,f        ; BCD x 2
        addwf    BCD,f        ; + BCD
        return        
                
l_dot        movlw    0x32        ; 0x0A * 5 = 0x32
        movwf    BCD        ;        
        return
        
;-------- Update Display memory with Time Ticks every 5 minutes

Ticks        movf    dpi,w        ;
        xorwf    timeticks,w    ;
        btfss    STATUS,Z    ;
        return
        bsf    tdd,6
        movlw    .10
        addwf    timeticks,f    ; set next tick @
        return

;******************************************************************************
;    Processing of RC5 command's, called by main program if a command is received
;******************************************************************************

ProcessRC5
        movf    RC5_Addr,w        ;        
        xorlw    RemoteAddr        ; test if RC5_Addr = RemoteAddr
        btfss    STATUS,Z        ; 
        goto    ProcessRC5Done        ;

        movf    RC5_Cmd,w        ;
        andlw    0x7F            ;    
        
        select_w
        case    NUM_0            ;
          clrf    Second2            ; Zero pressed => Seconds = 0
        case    SEC_UP            ;
          goto    IncSecond        ; Adjust time : Increment Seconds
        case    SEC_DN            ;
          goto    DecSecond        ; Adjust time : Decrement Seconds
        case    MIN_UP            ;
          incf    Minute,f        ; Adjust time : Increment Minutes
        case    MIN_DN            ;
          goto    DecMinute        ; Adjust time : Decrement Minutes
        case    HOUR_UP            ;
          goto    IncHour            ; Adjust time : Increment Hours
        case    HOUR_DN            ;
          goto    DecHour            ; Adjust time : Decrement Hours
        case    DAY_UP            ;
          goto    IncDay            ; Adjust Date : Increment Days
        case    DAY_DN            ;
          goto    DecDay            ; Adjust Date : Decrement Days
        case    MON_UP            ;
          goto    IncMonth        ; Adjust Date : Increment Month
        case    MON_DN            ;
          goto    DecMonth        ; Adjust Date : Decrement Month
        case    YEAR_UP            ;
          incf    Year,f            ; Adjust Date : Increment Year
        case    YEAR_DN
          goto    DecYear            ; Adjust Date : Decrement Year
        case    INDEX_UP        ;
          goto    DecDispOffset        ; Adjust index sensor Offset, rotate display left
        case    INDEX_DN        ;
          goto    IncDispOffset        ; Adjust index sensor Offset, rotate display right
        
        ; Toggle functions
        movf    RC5_Cmd,w        ;
        xorwf    RC5_Cmd2,f        ;
        btfsc    STATUS,Z        ;
        goto    ProcessRC5Done        ;
        andlw    0x7F            ;    

        select_w
        case    BlueLine         ;
          goto    ToggleOuterLed        ; Blue Line
        case    DigiTime        ;
          goto    ToggleTime        ; Digital Time
        case    DigiDate        ;
          goto    ToggleDate        ; Digital Date
        case    AnaTime            ;
          goto    ToggleAnalog        ; Analog Time
        case    TTicks            ;
          goto    ToggleTick        ; Analog Time Ticks
        case    DM            ;
          goto    ToggleDemo        ; Demo Mode
        case    TextMode        ;
          goto    ToggleText        ; Text Mode

ProcessRC5Done        
        movf    RC5_Cmd,w    ;
        movwf    RC5_Cmd2    ; 
        bsf    NewTime        ; force display update
        bcf    RC5_DataReady    ;
        return            ;
        
ToggleOuterLed    movlw    1 << bOuterLED    ;
        xorwf    flags2,f    ;
        bcf    OuterLED    ;
        btfsc    fOuterLED    ;
        bsf    OuterLED    ;
        goto    ProcessRC5Done    ;
        
ToggleTime    movlw    1 << bShowDTime    ;
        xorwf    flags,f        ;
        goto    ProcessRC5Done    ;
        
ToggleDate    movlw    1 << bShowDDate    ;
        xorwf    flags,f        ;
        goto    ProcessRC5Done    ;
        
ToggleAnalog    movlw    1 << bShowHand    ;
        xorwf    flags,f        ;
        goto    ProcessRC5Done    ;
        
ToggleTick    movlw    1 << bShowTicks    ;
        xorwf    flags,f        ;
        goto    ProcessRC5Done    ;
        
IncDispOffset    incf    DispOffset,w    ;
        call     CheckIncrement     ;
        movwf    DispOffset    ;                
        goto    ProcessRC5Done    ;

DecDispOffset    decf    DispOffset,w    ;
        call     CheckDecrement    ;
        movwf    DispOffset    ;                
        goto    ProcessRC5Done    ;
        
IncSecond    incf    Second2,f    ;
        incf    Second2,f    ;
        goto    ProcessRC5Done    ;
        
DecSecond    movlw    .2        ;
        subwf    Second2,f    ;
        btfsc    STATUS,C    ;    
        goto    ProcessRC5Done    ;
        movlw    .120        ;
        addwf    Second2,f    ;
DecMinute
        movlw    .1
        subwf    Minute,f    ;
        btfsc    STATUS,C    ;
        goto    ProcessRC5Done    ;
        movlw    .60        ;
        addwf    Minute,f    ;
DecHour
        movlw    .1
        subwf    Hour,f        ;
        btfsc    STATUS,C    ;
        goto    ProcessRC5Done    ;
        movlw    .24        ;
        addwf    Hour,f        ;
        goto    ProcessRC5Done    ;

IncHour        incf    Hour,f        ;
        movlw    .24        ;
        xorwf    Hour,w        ;
        btfsc    STATUS,Z    ;
        clrf    Hour        ;
        goto    ProcessRC5Done    ;

IncDay        decf    DMon,w        ;
        xorwf    Day,w        ;
             btfsc    STATUS,Z    ;
        clrf    Day        ;
        incf    Day,f        ;        
        goto    ProcessRC5Done    ;

DecDay        decfsz    Day,f        ;
        goto    ProcessRC5Done    ;
        decf    DMon,w        ;
        movwf    Day        ;
        goto    ProcessRC5Done    ;

IncMonth    movlw    .12        ;
        xorwf    Month,w        ;
        btfsc    STATUS,Z    ;
        clrf    Month        ;
        incf    Month,f        ;
        goto    ProcessRC5Done    ;

DecMonth    decfsz    Month,f        ;
        goto    ProcessRC5Done    ;
        movlw    .12        ;
        movwf    Month        ;
        goto    ProcessRC5Done    ;

DecYear        movlw    .1        ;
        subwf    Year,f        ;
        btfsc    STATUS,C    ;
        goto    ProcessRC5Done    ;
        movlw    .99        ;
        movwf    Year        ;
        goto    ProcessRC5Done    ;

ToggleText    call    TextON_OFF    ; Toggel Text mode
        goto    ProcessRC5Done    ;

ToggleDemo    movlw    1 << bDemo    ;
        xorwf    flags2,f    ;
        goto    ProcessRC5Done    ;

TextON_OFF    bcf    fScrollOn    ; Scrolling OFF
        movlw    1 << bText    ; toggle Text flag
        xorwf    flags2,f    ;
        btfss    fText        ; test Text flag
        goto    ProcessRC5Done    ;
        call    ClearDisplay    ;
        bsf    fScrollOn    ; Scrolling ON
        return
            
;******************************************************************************
;    Initialisation routines, called by main program
;******************************************************************************

InitRam
        clrf    PixelWidth    ;
        clrf    PixelOff    ;
        movlw    0x37        ; Initial Display Offset for my hardware !!!
        movwf    DispOffset    ;
        movwf    iFSR        ;

        movlw    0x3C        ; load counter SubSecond = 0x10000 - 2500 = 0xF63C
        movwf    SubSec_L    ;
        movlw    0xF6        ;
        movwf    SubSec_H    ;
        clrf    flags        ; clear all flags
        clrf    flags2        ;

        movlw    .12        ;why do clocks always start
        movwf    Hour        ;at 12:00 ?
        clrf    Minute
                clrf    Second2
        movlw    0x01
        movwf    Day
        movwf    Month
        movlw    Year
                
        clrf    RC5_flags    ; clear flags
        clrf    RC5_Tmr        ;
        bsf    RC5_WaitStart    ; RC5 is waiting for startbit
        return
        
;--------        
InitIO
        clrf    PORTA        ; all LED's OFF
        clrf    PORTB

        bcf    STATUS,IRP    ; Bank0.1 for FSR/INDF operations
        bcf    STATUS,RP1    ; 
        bsf    STATUS,RP0    ; Bank1
        movlw    0xFF        ;
        movwf    TRISA        ; set all is input
         bcf    TRISA, bCalibration    ; Set Calibration pin as output
         movwf    TRISB        ; outputs will be turned on if rotation is stable
        bcf    STATUS,RP0    ; Bank0

        movlw    0x07        ;
        movwf    CMCON        ; comparators OFF
        
        retlw    0
;--------        
InitTmr 
        clrf    INTCON        ; clear and dissable all possible interrupt flag
        clrf    PIR1        ; 

        movlw    b'00000101'    ; TMR2=ON, Prescaler = 1/4
        movwf    T2CON        ; 

        bsf    STATUS,RP0    ; Bank1
        clrf    PIE1        ; dissable all possible interrupt flag
        movlw    b'10011000'    ; set up timer. prescaler(bit3)bypassed, Int on falling Edge RB0
        movwf    OPTION_REG    ; send w to option.
        movlw    .249        ; TMR2 PR2=249
        movwf    PR2        ;
        bsf    PIE1,TMR2IE    ; enable Peripheral interrupt from TMR2
        bcf    STATUS,RP0    ; Bank0

        bsf    INTCON,T0IE    ; enable TMR0 interrupt
        bsf    INTCON,INTE    ; enable RB0 interrupt
        bsf    INTCON,PEIE    ; enable Peripheral interrupts
        bsf    INTCON,GIE    ; enable global interrupts

        clrf    TMR0        ; start timer
        return

;--------        
ClearDisplay
        movlw    0x20        ; set FSR to 0x20
        movwf    FSR        ;
cldisp
        clrf    INDF        ; clear display memory
        incf    FSR,f        ; 
        movlw    0x48
        xorwf    FSR,w        ; FSR = 0x48
        btfss    STATUS,Z    ; ??
        goto    cldisp_2    ; nope, jump
        movlw    0x58        ; w = 0x58
        addwf    FSR,f        ; FSR = FSR + 0x58 = 0xA0
cldisp_2
        movlw    0xF0        ; 
        xorwf    FSR,w        ; FSR = 0xF0
        btfss    STATUS,Z    ; ??
        goto    cldisp        ; nope, jump

        ; init stuff needed for Text Scroll function
        bsf    STATUS,RP1    ; jump to bank 2
              clrf    ch_dot_index    ; 
              clrf    ch_blanking    ;
              bcf    STATUS,RP1    ; return to bank 0
        bsf    STATUS,RP0    ; goto bank 1
        clrf    EEADR        ; inc address for next read
        bcf    STATUS,RP0    ; goto bank 0

        return

;******************************************************************************
;    Main program 
;******************************************************************************

main

        call InitIO        ; Initialise Ports
        call InitRam        ; Initialise Ram and flags
        call ClearDisplay    ; clear display content
        call InitTmr        ; Initialise Timers and interrupt

        bsf    ShowHand    ; turn analog hands on
        bsf    ShowDTime    ;
        bsf    ShowDDate    ;
        bsf    ShowTicks    ;
        bsf    OuterLED    ;
MainLoop
        btfsc    RC5_DataReady    ;
        call    ProcessRC5    ;

        btfss    fScrollOn    ;
        goto    NoScrolling    ;
        movf    TmrScroll,w    ;
        btfss    STATUS,Z    ;
        goto    NoScrolling    ;
        decf    TmrScroll,f    ; TmrScroll-- => 0 - 1 = 0xFF 
        call    ScrollText    ;

NoScrolling
        btfsc    NewPCnt        ; test Period counter flag
        call    CalcPixelPitch  ; calculate new pixel pitch

        btfss    NewTime        ; test new time flag
        goto    MainLoop    ;

; one second past. Do timecheck and if text=off, also a display update.
        call    TimeCheck    ;

        btfsc    fDemo        ;
        call    DemoMode    ;

        btfsc    fText        ; test Image flag
        goto      MainLoop    ; if Image flag SET, leave display-content unchanged

; start display memory update
        clrf    dpi        ; dpi = 0
        clrf    timeticks    ; keep index for 5 min timeticks
        bcf    digitstart    ; 
        movlw    0x20        ; start of display memory
        movwf    FSR
        bcf    digitstart    ;

lUpdateDisplay    
        
        clrf    tdd        ;

        btfsc    ShowDTime    ;
        call    DTime        ; Display digital Time
        
        btfsc    ShowDDate    ;
        call    DDate        ; Display digital Date
        
        btfsc    ShowHand    ;
        call    Hands    
        btfsc    ShowTicks    ;
        call    Ticks        ;
        
        movf    tdd,w        ; store data in 
        movwf    INDF        ; display memory
        
        incf    dpi,f        ;
        movlw    .120        ;
        xorwf    dpi,w        ;
        btfsc    STATUS,Z    ;
        goto      MainLoop    ;
        
        incf    FSR,f        ;
        movlw    0x48        ; for memory gap
        xorwf    FSR,w        ; FSR = 0x48
        btfss    STATUS,Z    ; ??
        goto    lUpdateDisplay    ; nope, jump
        movlw    0x58        ; w = 0x58
        addwf    FSR,f        ; FSR = FSR + 0x58 = 0xA0        
        goto    lUpdateDisplay
        
;******************************************************************************
;    Text display functions
;******************************************************************************

CharOffset    movwf    ch_dot_point_L        ; store ASC code
        clrf    ch_dot_point_H        ; clear high byte
        movlw    .32            ; asc code - 32 
        subwf    ch_dot_point_L,f    ; 
        btfss    STATUS,C        ; ASC < 32 ? Invalid code, 
        clrf    ch_dot_point_L        ; relpace with CHR(32) = " "
        movlw    .127            ;
        subwf    ch_dot_point_L,w    ;
        btfsc    STATUS,C        ; ASC >= 127 ? Invalid code,
        movwf    ch_dot_point_L        ; replace with last valid ASC code
    
        bcf     STATUS,C        ; Clear Carry flag
        rlf    ch_dot_point_L,f    ; asc code * 2
        rlf    ch_dot_point_H,f    ;         

        bcf     STATUS,C        ; Clear Carry flag        
        rlf    ch_dot_point_L,w    ; 
        movwf    Scratch            ; Scratch = (asc code * 2) *2
        rlf    ch_dot_point_H,w    ;
        movwf    Scratch2        ; 
        
        movf    Scratch,w        ; ch_dot_point (16bit) = (asc code - 32) * 6
        addwf    ch_dot_point_L,f    ; 
        btfsc    STATUS,C        ; 
        incf    Scratch2,f        ;
        movf    Scratch2,w        ;
        addwf    ch_dot_point_H,f    ; ch_dot_point = ch_dot_point + 0x500 start of char gen table
        movlw    0x05            ; this is the entry in the char gen table for the
        addwf    ch_dot_point_H,f    ; first pixel data of the requested char
        
        movlw    .6
        movwf    ch_dot_index        ; indicate start of new char
        return

;--------        
LoadChrData    movf    ch_dot_point_H,w    ;
        movwf    PCLATH            ;
        movf    ch_dot_point_L,w    ;
        call    CharGen            ;
        incf    ch_dot_point_L,f    ; pointer++
        btfsc    STATUS,Z        ;
        incf    ch_dot_point_H,f    ;
        decf    ch_dot_index,f        ; dec dot-index
        return                            

;--------        
PrintDisp    call    ClearDisplay        ; clear display content
        bsf    STATUS, RP0        ; Bank1
        clrf    EEADR            ; start of EE-memory
        movlw    0xE4            ; Start for first char a 7 o'clock
        movwf    FSR            ;
        movlw    .14            ; 14 char to display
        movwf    Scratch3        ;
pdisp_1                
        bsf    EECON1, RD        ; read character from EEProm
        incf    EEADR,f            ; inc address for next read
        movf    EEDATA,w        ;

        bsf    STATUS,RP1        ; goto Bank2
        bcf    STATUS,RP0        ;

        call    CharOffset        ; call character data
pdisp_2        
        call    LoadChrData        ; load pixel data from CharGen
        movwf    INDF            ; store char pixel data in display memory
        incf    FSR,w        ; increment FSR
        call     CheckIncrement    ;
        movwf    FSR        ;                
        
        decfsz    ch_dot_index,f        ; 6 dot's in one character, all displayed ?
        goto    pdisp_2            ;

        bcf    STATUS,RP1        ; leave bank 2, back to bank1
        bsf    STATUS,RP0        ;
            
        decfsz    Scratch3,f        ;                         
        goto    pdisp_1                
        
        bcf    STATUS,RP0        ; go back to bank 0
        return    
        
;--------
ScrollText    bsf    STATUS,RP1        ; goto Bank2
        bcf    STATUS,RP0        ;
              
              movf    ch_dot_index,w        ;
        btfss    STATUS,Z        ; dot_index == 0 ?
        goto    Scroll_0 
        
        movf    ch_blanking,w        ;
        btfsc    STATUS,Z        ;
        goto    Scroll_read_ee        ;
        decfsz    ch_blanking,f        ;
        goto    Scroll_2        ; insert one more " "
        btfss    fDemo            ; in demo mode?
        goto    Scroll_read_ee        ; re-read char
        
        bcf    STATUS,RP1        ; to bank 0
        call    TextON_OFF        ; at end of line, turn text off!
        return                ; stop scrolling
        
        
Scroll_read_ee    bcf    STATUS,RP1        ; leave bank 2, to bank1
        bsf    STATUS,RP0        ;
        bsf    EECON1, RD        ; read character from EEProm
        incf    EEADR,f            ; inc address for next read
        bcf    EEADR,7            ; roll over after 0x80 => 0x00
        movf    EEDATA,w        ;

        btfsc    STATUS,Z        ; Chr$(0) indicates end of line
        clrf    EEADR            ; start of EE-memory
        bsf    STATUS,RP1        ; go back to Bank2
        bcf    STATUS,RP0        ;

        btfss    STATUS,Z        ; if Z was 1, it wil still be 1 here 
        goto    Scroll_1        ;
        movlw    0x0F            ; insert 15 " " at end of string to clear display
        movwf    ch_blanking        ;
Scroll_2
        movlw    " "            ; w = " "
Scroll_1

        call    CharOffset        ; call character data
Scroll_0
        call    LoadChrData        ; load pixel data from CharGen
        movwf    Scratch            ;        

#ifdef ReversTextScroll
        movlw    0xE4            ; Start at begin of 7 o'clock character
#else
        movlw    0xBF            ; Start at end of 5 o'clock character
#endif
        movwf    FSR            ;
ScrollLoop
        movf    INDF,w            ; load current data
        movwf    Scratch2        ; temp store
        movf    Scratch,w        ; 
        movwf    INDF            ; 
        movf    Scratch2,w        ; shift data
        movwf    Scratch            ;
        
#ifdef ReversTextScroll
        incf    FSR,w            ; 
        call    CheckIncrement
        movwf    FSR            ;                        
        movlw    .14            ; check end of 5 o'clock character
#else
        decf    FSR,w            ; 
        call    CheckDecrement
        movwf    FSR            ;                        
        movlw    0xE3            ; check begin of 7 o'clock character
#endif
        subwf    FSR,w            ;
        btfss     STATUS,Z        ; FSR = 0xE4 ? (or 0xC0)
        goto    ScrollLoop        ;

        bcf    STATUS,RP0        ; goto Bank0
        bcf    STATUS,RP1        ; 

        return                ;

;DemoMode    btfsc    fScrollOn        ; in scroll mode?
;        goto    Demo_0            ; yes, already in scroll mode
;        
;        movf    Second,w        ;
;        btfsc    STATUS,Z        ;
;        bsf    fSCrollOn        ;    
;        return
;        
;Demo_0        
;
;        return                ;

DemoMode    movf    Second2,w        ;
        btfsc    STATUS,Z        ;
        call    TextON_OFF
        return
        
                
;******************************************************************************
;    Some general functions
;******************************************************************************
                
;- check correct decrement of Display memory pointer
CheckDecrement
        xorlw    0x1F        ;
        btfsc    STATUS,Z    ;
        movlw    0xEF ^ 0x1F    ;
        xorlw    0x9F ^ 0x1F    ;
        btfsc    STATUS,Z    ;
        movlw    0x47 ^ 0x9F    ;
        xorlw    0x9F        ;
        return            ;

;- check correct increment of Display memory pointer
CheckIncrement
        xorlw    0x48        ;
        btfsc    STATUS,Z    ;
        movlw    0xA0 ^ 0x48    ;
        xorlw    0xF0 ^ 0x48    ;
        btfsc    STATUS,Z    ;
        movlw    0x20 ^ 0xF0    ;
        xorlw    0xF0        ;
        return            ;
        
                
    END    ; directive 'end of program'
Archivos Adjuntos
Tipo de Archivo: zip ASM.zip (13,4 KB (Kilobytes), 41 visitas)
25/09/2010 #5

Avatar de el-rey-julien

Respuesta: Ayuda con codigo ASM para PIC
amigo si vas a usar un control universal,para que querés cambiar el codigo?,yo lo dejaría tal cual esta y usaria el control remoto universal.saludos
25/09/2010 #6


Respuesta: Ayuda con codigo ASM para PIC
Hola...

Bueno, ahi está la cuestión... a ver si me pueden entender lo que les voy a plantear.

Partamos de la base que el autor uso el control remoto de un cañon/proyector marca "barco".
También partamos de la base que los controles remotos universales están preparados para manejar aparatos TV/DVD/VCR. En algunos casos solo admiten esta clase de equipos, en otros admiten otra clase como por ejemplo SAT/CAM. Pero no admiten equipos tales como los cañones/proyectores. Y ahí está mi mayor de las dudas. Que no tengo garantias de que un control remoto universal vaya a funcionar, puesto que si la programacion del reloj hace referencia a una dirección distinta a la de un control remoto de TV/DVD/VCR/SAT O CAM el control universal simplemente no podrá compatibilizar con el reloj. En que me baso para pensar todo esto?. En dos cosas, la primera, que el autor de este proyecto no publicó las direcciones RC5 que utiliza su control remoto de proyector (de ahí mi necesidad de entender en donde se hace refrencia en el codigo fuente a tal dirección y saber cual es). La segunda, es que el protocolo RC5 define muchas direcciones distintas para controles remotos y es dificil saber a ciencia cierta si un control remoto universal podría funcionar, la tabla con direcciones predefinidas por philips la adjunto debajo.

Espero hayan entendido lo que les planteo.

Gracias.

PD: La incertidumbre se me crea por no saber tambien en que categoria entrarian los proyectores en la tabla de direcciones predefinidas de philips.
Imágenes Adjuntas
Tipo de Archivo: gif direcciones.gif (10,8 KB (Kilobytes), 15 visitas)
25/09/2010 #7

Avatar de el-rey-julien

Respuesta: Ayuda con codigo ASM para PIC
el control remoto universal ,ponlo con algún código de tv marca philip,lo pruebas y si no funciona ,recién ay metamosle mano al codigo ,estoy seguro que funciona ,nomas probalo así como te explique .
en esa tabla solo dice el/los primeros bit definen el aparato a controlar ,no te desesperes que no es tan dificil,
acá mismo en el foro si buscas el tema de los remotos esta explicado,(o sera que lo vi en otro lado?)--(mira si esperas un poco yo en algún lado tengo toda esa info,nomas tene paciensa)
07-7 es el experimental ,muchos usan esos códigos,creo que entrarían en esa categoría de direcciones

pd:
aca esta mira en este archivo adjunto que subi que esta bien explicado el tema del control remoto ,en este caso tambien se usa un control remoto philip Sintonizador de TV pero lo importante son las explicaciones que el autor da por el tema rc5
25/09/2010 #8


Respuesta: Ayuda con codigo ASM para PIC
Bueno, gracias por la ayuda...

Haré una cosa, probaré así como está...Seguiré tus consejos, es mas, te digo que por ahora estás teniendo razón porque acabo de buscar info sobre los proyectores barco, y buscando di con el manual de uno de ellos y en una parte estaba la parte de control remoto y me encontré con la sorpresa de que los controles de esos proyectores son de dirección programables (usado cuando hay mas de un proyector en la misma sala), y en una parte estaba especificado que el protocolo que usaba era RC5 y que la dirección que empleaba por defecto estaba en el 001 (que según la tabla coincidiría con la dirección asignada para TV: 01-1 si hacemos una asociación por sentido común).

Gracias por el adjunto que me pasaste, ya lo descargué y en breve lo leeré.

Les agradezco a todos por la ayuda que me brindaron.

Hector.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.