title "3x5dcf_high_side.asm" ; I've never seen a clock with 3x5 displays. This should put that right. HH:MM:SS format only. This version drives the rows from GND via MOSFETs and the columns from high side using HEF4094 shift registers. ; ; 200725 v0.1 Copied from original low side shift register LED drive ; 200730 v0.2 Fixed missing pulses (DCFLOSS) from crap Elektor ESP01 code (March 2018) ; 200731 v0.3 Copy decoded time only when parcheck passed twice to avoid zeroes at DCFLOSS but immediately after successful decode at poweron ; 200731 v1.0 Release ; 200801 v1.1 Still issues with DCFOK after DCFLOSS event (skip 1 minute) ; ; GPL Copyleft 2019, 2020 pic@polonai.se LIST P=16F628A, F=INHX8M #include <p16f628a.inc> __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _LVP_OFF & _CP_OFF & _BODEN_OFF ; Equates RESET_V EQU 0x00 ; Address of RESET Vector OSC_FREQ EQU D'4000000' ; Oscillator Frequency is 4 MHz ; Registers TEMP EQU 0x20 ; TEMP register THOURS EQU 0x21 ; 10 Hours value HOURS EQU 0x22 ; Hours value TMINS EQU 0x23 ; 10 Minutes value MINS EQU 0x24 ; Minutes value TSECS EQU 0x25 ; 10 Seconds value HSECS EQU 0x26 ; Half Seconds value (because of TIMER1) DIGIT1 EQU 0x31 ; 10 hr digit DIGIT2 EQU 0x32 ; hour digit DIGIT3 EQU 0x33 ; 10 min digit DIGIT4 EQU 0x34 ; minute digit DIGIT5 EQU 0x35 ; 10 sec digit DIGIT6 EQU 0x36 ; seconds digit DCFHIGH EQU 0x37 ; Counter for the length of received DCF high pulses, used for decoding DCFLOW EQU 0x38 ; Counter for the length of received DCF space between pulses, used for decoding and syncing MINBUF EQU 0x39 ; Received DCF Data Minutes Buffer HRBUF EQU 0x3A ; Received DCF Data Hours Buffer DCFSEC EQU 0x3D ; Counter for DCF data FLAGS EQU 0x7F ; Various flags #define ROW0 PORTB,0 ; Row 0 (low side switching) #define ROW1 PORTB,1 ; Row 1 #define ROW2 PORTB,2 ; Row 2 #define ROW3 PORTB,3 ; Row 3 #define ROW4 PORTB,4 ; Row 4 #define DCFIN PORTA,4 ; Input DCF signal, positive (mark = HIGH) #define SDI PORTA,6 ; Serial Data line of HEF4094 #define CLK PORTA,7 ; Clock for HEF4094 (high pulse) #define STR PORTA,0 ; Strobe for HEF4094 (high pulse) #define OE PORTA,1 ; Output Enable for HEF4094 (active high) #define LED PORTA,2 ; Blue LED for DCF input activity #define TETS PORTA,3 ; Yellow LED for debugging #define FIRSTDEC FLAGS,1 ; First successful decode after poweron #define DCFOK FLAGS,2 ; when both hour and minute even parities are OK, needs good signal, colon solid otherwise flashing/alternating #define DCFBAD FLAGS,3 ; Clock free running after having had valid time (parity fail, loss of signal), colon alternating (prio over DCFOK) #define P1 FLAGS,4 ; Calculated parity over received minute #define P2 FLAGS,5 ; Calculated parity over received hour #define RXD FLAGS,6 ; Received DCF data bit org 0x00 GOTO START org 0x04 ; Interrupt handler ; NOTE: Everything of this program runs inside an interrupt handler so it's not necesssary ; to back up any critical registers (WREG, STATUS) when entering or exiting the handler. BTFSC INTCON,TMR0IF ; TMR0 interrupt GOTO DCFHandler BTFSC PIR1,TMR1IF ; Check to see if the interrupt was caused by a TIMER1 rollover Overflow) GOTO Timehandler ; half second timer BTFSC PIR1,TMR2IF ; Check to see if the interrupt was caused by a TIMER2 rollover (overflow) GOTO Multiplex ; 6 ms multiplex time for LED display RETFIE ; If none of the above is true, then just leave the interrupt handler DCFHandler BCF INTCON,TMR0IF ; Clear interrupt source MOVLW 0x44 ; Check DCFIN every 50 ms-ish (too many interrupts and too low internal clock of 4 MHz) MOVWF TMR0 BTFSC DCFIN ; Input high? GOTO DCF1 ; Yes BTFSC LED ; LED still on? GOTO FIRSTLOW ; Yes INCF DCFLOW,F MOVLW 0x2A ; Test for 42 pulses SUBWF DCFLOW,W ; if true, C=1, loss of signal BTFSC STATUS,C GOTO DCFLOSS RETFIE DCFLOSS MOVLW 0x29 MOVWF DCFLOW BTFSC FIRSTDEC ; Skip setting DCFBAD if firstdecode hasn't happened yet BSF DCFBAD BCF DCFOK RETFIE FIRSTLOW ; Test for one or zero DCF bit BCF LED ; Switch off LED BCF RXD CLRF DCFLOW ; Destroy value in counter MOVLW 0x00 ; Decode received bit SUBWF DCFHIGH,W BTFSC STATUS,Z ; One sample? GOTO SETZERO ; Yes MOVLW 0x01 SUBWF DCFHIGH,W BTFSC STATUS,Z ; Two samples? GOTO SETZERO ; Yes MOVLW 0x02 SUBWF DCFHIGH,W BTFSC STATUS,Z ; Three samples? GOTO SETZERO ; Yes MOVLW 0x03 SUBWF DCFHIGH,W BTFSC STATUS,Z ; Four samples? GOTO SETONE ; Yes MOVLW 0x04 SUBWF DCFHIGH,W BTFSC STATUS,Z ; FIVE samples? (just in case) GOTO SETONE ; Yes BCF DCFOK ; HIGH pulse too long RETFIE SETONE BSF RXD SETZERO ; Rather remain zero INCF DCFSEC,F MOVLW 0x16 SUBWF DCFSEC,W BTFSS STATUS,C ; At minutes yet? RETFIE ; No MOVLW 0x1E SUBWF DCFSEC,W BTFSC STATUS,C ; At hours yet? GOTO SHIFTHOUR ; Yes BCF STATUS,C BTFSC RXD BSF STATUS,C RRF MINBUF,F ; Move received bit into minutes buffer RETFIE SHIFTHOUR MOVLW 0x25 SUBWF DCFSEC,W BTFSC STATUS,C ; Done hours? RETFIE ; Yes BCF STATUS,C BTFSC RXD BSF STATUS,C RRF HRBUF,F ; Move received bit into hours buffer RETFIE DCF1 BTFSS LED ; LED on? GOTO FIRSTHIGH ; No INCF DCFHIGH,F RETFIE ; Not testing anything else, already done at FIRSTLOW FIRSTHIGH BSF LED CLRF DCFHIGH ; Clear HIGH pulse duration counter MOVLW 0x0D SUBWF DCFLOW,W ; Test for pulse > 0x0D*50 ms (valid LOW pulse) BTFSS STATUS,C ; Pause too short? RETFIE ; Yes MOVLW 0x21 SUBWF DCFLOW,W ; Test for pulse > 0x21*50 ms (59th second) BTFSS STATUS,C ; Pause too short for 59th second? RETFIE ; Yes MOVLW 0x28 SUBWF DCFLOW,W ; Test for pulse >= 0x28*50 ms (59th second) BTFSC STATUS,C ; Pause too long? RETFIE MOVLW 0x0B ; Preload TIMER1 (0.5 second)... MOVWF TMR1H MOVLW 0xD0 MOVWF TMR1L ; ...to start the second half second after half a second CLRF DCFSEC ; This is the zeroth second (M) CLRF TSECS CLRF HSECS MOVLW 0x7F ; Blank parity bit ANDWF MINBUF,W ; and store in W CALL PARCHECK ; Call parity routine btfsc TEMP,0 ; Test parity bit 0 goto MINODD ; if bit=1 odd # of bits set BTFSS MINBUF,7 ; Parity even? GOTO HRCHECK ; Yes, check hour parity GOTO DCFNOK ; No, no need to test hours MINODD BTFSC MINBUF,7 ; Parity odd? GOTO HRCHECK ; Yes, check hour parity GOTO DCFNOK ; No, no need to test hours HRCHECK ; Check parity of hour MOVLW 0x7E ; Blank parity bit (and bit 0) ANDWF HRBUF,W ; and store in W CALL PARCHECK ; Call parity routine btfsc TEMP,0 ; Test parity bit 0 goto HRODD ; if bit=1 odd # of bits set BTFSS HRBUF,7 ; Parity even? GOTO DCFWOK ; Yes, make DCF OK ("Wel OK") GOTO DCFNOK ; No ("Not OK") HRODD BTFSC HRBUF,7 ; Parity odd? GOTO DCFWOK ; Yes, make DCF OK GOTO DCFNOK ; No ; Parity Subroutine ; http://picprojects.org.uk/projects/pictips.htm#Parity PARCHECK movwf TEMP swapf TEMP,W xorwf TEMP,W movwf TEMP rrf TEMP,F rrf TEMP,F xorwf TEMP,W movwf TEMP rrf TEMP,F xorwf TEMP,F return DCFWOK BTFSC DCFBAD GOTO Skipdecode BSF FIRSTDEC ; Enable setting DCFBAD after loading time at powerup BCF MINS,0 ; Decode minutes from buffer BTFSC MINBUF,0 BSF MINS,0 BCF MINS,1 BTFSC MINBUF,1 BSF MINS,1 BCF MINS,2 BTFSC MINBUF,2 BSF MINS,2 BCF MINS,3 BTFSC MINBUF,3 BSF MINS,3 BCF TMINS,0 BTFSC MINBUF,4 BSF TMINS,0 BCF TMINS,1 BTFSC MINBUF,5 BSF TMINS,1 BCF TMINS,2 BTFSC MINBUF,6 BSF TMINS,2 BCF HOURS,0 ; Decode hours from buffer BTFSC HRBUF,1 ; Only seven "hour" bits so offset by one BSF HOURS,0 BCF HOURS,1 BTFSC HRBUF,2 BSF HOURS,1 BCF HOURS,2 BTFSC HRBUF,3 BSF HOURS,2 BCF HOURS,3 BTFSC HRBUF,4 BSF HOURS,3 BCF THOURS,0 BTFSC HRBUF,5 BSF THOURS,0 BCF THOURS,1 BTFSC HRBUF,6 BSF THOURS,1 Skipdecode BCF DCFBAD CLRF MINBUF CLRF HRBUF BSF DCFOK RETFIE DCFNOK BCF DCFOK BTFSC FIRSTDEC ; Skip setting DCFBAD if firstdecode hasn't happened yet BSF DCFBAD CLRF MINBUF CLRF HRBUF RETFIE Timehandler BCF PIR1,TMR1IF ; Clear Interrupt Source MOVLW 0x0E ; Preload TIMER1 (0.5 second-ish) MOVWF TMR1H CLRF TMR1L ; Increment halfseconds INCF HSECS,F MOVLW 0x14 ; Test for overflow SUBWF HSECS,W ; if true, C=1, increment 10 seconds BTFSS STATUS,C RETFIE CLRF HSECS ; Increment 10 seconds INCF TSECS,F MOVLW 0x06 ; Test for overflow SUBWF TSECS,W ; if true, C=1, increment minutes BTFSS STATUS,C RETFIE CLRF TSECS BTFSC DCFOK ; DCF OK? If so skip further time processing and get time from decoded DCF RETFIE ; Yes ; Increment minutes (only when free-running) INCF MINS,F MOVLW 0x0A ; Test for overflow SUBWF MINS,W ; if true, C=1, increment 10 minutes BTFSS STATUS,C RETFIE CLRF MINS ; Increment 10 minutes INCF TMINS,F MOVLW 0x06 ; Test for overflow SUBWF TMINS,W ; if true, C=1, increment hours BTFSS STATUS,C RETFIE CLRF TMINS ; Check for midnight MOVLW 0x02 SUBWF THOURS,0 ; if true, C=1, check for midnight BTFSC STATUS,C GOTO MIDNIGHT ; Increment hours INCF HOURS,F MOVLW 0x0A ; Test for overflow SUBWF HOURS,W ; if true, C=1, increment 10 hours BTFSS STATUS,C RETFIE CLRF HOURS ; Increment 10 hours INCF THOURS,F RETFIE MIDNIGHT INCF HOURS,F MOVLW 0x04 ; Test for midnight SUBWF HOURS,W ; if true, C=1, new day BTFSS STATUS,C RETFIE CLRF HOURS CLRF THOURS RETFIE Multiplex ; Get the pattern for the current time display per row BCF PIR1,TMR2IF ; Clear interrupt source (4.114ms) BCF OE ; Disable (Hi-Z) outputs HEF chip to prevent ghosting BTFSC ROW0 ; Top row active? GOTO ONROW1 ; Yes, go to next row BTFSC ROW1 ; (etcetera) GOTO ONROW2 BTFSC ROW2 GOTO ONROW3 BTFSC ROW3 GOTO ONROW4 BCF ROW4 ; Rows 0-3 were not active so switch off ROW4 MOVLW 0x02 MOVWF PCLATH ; Adjust for page boundary computed goto BCF STATUS,C ; Clear carry RRF HSECS,W ; Divide half seconds by two to get whole seconds and place in W reg CALL row0show ; Get pattern to shift into register MOVWF DIGIT6 MOVFW TSECS CALL row0show MOVWF DIGIT5 MOVFW MINS CALL row0show MOVWF DIGIT4 MOVFW TMINS CALL row0show MOVWF DIGIT3 MOVFW HOURS CALL row0show MOVWF DIGIT2 MOVFW THOURS CALL row0show MOVWF DIGIT1 CLRW SUBWF THOURS,0 ; Test for leading zero in tenhours BTFSC STATUS,Z CLRF DIGIT1 ; Blank first digit BSF ROW0 ; Switch on ROW0 GOTO Show ONROW1 BCF ROW0 ; Switch off ROW0 MOVLW 0x02 MOVWF PCLATH ; Adjust for page boundary computed goto BCF STATUS,C ; Clear carry to prevent spurious bit7 being set RRF HSECS,W ; Divide half seconds by two to get whole seconds and place in W reg for lookup table CALL row1show MOVWF DIGIT6 MOVFW TSECS CALL row1show MOVWF DIGIT5 MOVFW MINS CALL row1show MOVWF DIGIT4 MOVFW TMINS CALL row1show MOVWF DIGIT3 MOVFW HOURS CALL row1show MOVWF DIGIT2 MOVFW THOURS CALL row1show MOVWF DIGIT1 CLRW SUBWF THOURS,0 ; Test for leading zero in tenhours BTFSC STATUS,Z CLRF DIGIT1 ; Blank first digit BSF ROW1 GOTO Show ONROW2 BCF ROW1 MOVLW 0x02 MOVWF PCLATH ; Adjust for page boundary computed goto BCF STATUS,C ; Clear carry RRF HSECS,W ; Divide half seconds by two to get whole seconds and place in W reg CALL row2show MOVWF DIGIT6 MOVFW TSECS CALL row2show MOVWF DIGIT5 MOVFW MINS CALL row2show MOVWF DIGIT4 MOVFW TMINS CALL row2show MOVWF DIGIT3 MOVFW HOURS CALL row2show MOVWF DIGIT2 MOVFW THOURS CALL row2show MOVWF DIGIT1 CLRW SUBWF THOURS,0 ; Test for leading zero in tenhours BTFSC STATUS,Z CLRF DIGIT1 ; Blank first digit BSF ROW2 GOTO Show ONROW3 BCF ROW2 MOVLW 0x02 MOVWF PCLATH ; Adjust for page boundary computed goto BCF STATUS,C ; Clear carry RRF HSECS,W ; Divide half seconds by two to get whole seconds and place in W reg CALL row3show MOVWF DIGIT6 MOVFW TSECS CALL row3show MOVWF DIGIT5 MOVFW MINS CALL row3show MOVWF DIGIT4 MOVFW TMINS CALL row3show MOVWF DIGIT3 MOVFW HOURS CALL row3show MOVWF DIGIT2 MOVFW THOURS CALL row3show MOVWF DIGIT1 CLRW SUBWF THOURS,0 ; Test for leading zero in tenhours BTFSC STATUS,Z CLRF DIGIT1 ; Blank first digit BSF ROW3 GOTO Show ONROW4 BCF ROW3 MOVLW 0x02 MOVWF PCLATH ; Adjust for page boundary computed goto BCF STATUS,C ; Clear carry RRF HSECS,W ; Divide half seconds by two to get whole seconds and place in W reg CALL row4show MOVWF DIGIT6 MOVFW TSECS CALL row4show MOVWF DIGIT5 MOVFW MINS CALL row4show MOVWF DIGIT4 MOVFW TMINS CALL row4show MOVWF DIGIT3 MOVFW HOURS CALL row4show MOVWF DIGIT2 MOVFW THOURS CALL row4show MOVWF DIGIT1 CLRW SUBWF THOURS,0 ; Test for leading zero in tenhours BTFSC STATUS,Z CLRF DIGIT1 ; Blank first digit if zero BSF ROW4 Show ; Fill shift register BTFSC DIGIT6,5 ; Get Col27 (rightmost column, HEF3:QP4, display4:ROW2) BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT6,6 ; Get Col26 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT6,7 ; Get Col25 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT5,5 ; Get Col23 (skip Col24) BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT5,6 ; Get Col22 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT5,7 ; Get Col21 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 CALL Colon1 ; Get colon (flashing or not) BTFSC DIGIT4,5 ; Get Col17 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT4,6 ; Get Col16 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT4,7 ; Get Col15 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT3,5 ; Get Col13 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT3,6 ; Get Col12 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT3,7 ; Get Col11 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 CALL Colon2 BTFSC DIGIT2,5 ; Get Col7 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT2,6 ; Get Col6 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT2,7 ; Get Col5 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT1,5 ; Get Col3 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT1,6 ; Get Col2 BSF SDI BSF CLK BCF CLK ; Output bit BCF SDI ; Data -> 0 BTFSC DIGIT1,7 ; Get Col1 (HEF1:QP1, display1:ROW7) BSF SDI BSF CLK BCF CLK ; Output bit BSF STR BCF STR ; Drive latch BCF SDI ; Make sure data line is zero to prevent spurious display in Col27 BSF OE ; Done shift register, enable outputs RETFIE Colon1 BTFSC ROW0 GOTO Endcolon BTFSC ROW2 GOTO Endcolon BTFSC ROW4 GOTO Endcolon BTFSC DCFBAD GOTO Altcolon1 BTFSS DCFOK ; Solid colon when DCF OK BTFSC HSECS,1 ; Get colon pattern (0.5 Hz flash) if not OK BSF SDI GOTO Endcolon Altcolon1 BTFSC ROW1 GOTO Altcolon11 BTFSC HSECS,1 ; This is ROW3 BSF SDI GOTO Endcolon Altcolon11 BTFSS HSECS,1 ; This is ROW1 BSF SDI GOTO Endcolon Colon2 BTFSC ROW0 GOTO Endcolon BTFSC ROW2 GOTO Endcolon BTFSC ROW4 GOTO Endcolon BTFSC DCFBAD GOTO Altcolon2 BTFSS DCFOK ; Solid colon when DCF OK BTFSC HSECS,1 ; Get colon pattern (0.5 Hz flash) if not OK BSF SDI GOTO Endcolon Altcolon2 BTFSC ROW1 GOTO Altcolon21 BTFSS HSECS,1 ; This is ROW3 BSF SDI GOTO Endcolon Altcolon21 BTFSC HSECS,1 ; This is ROW1 BSF SDI Endcolon BSF CLK BCF CLK ; Output bit (colon1) BCF SDI RETURN ; END Interrupthandlers START ;Init stuff BCF STATUS,RP0 ; Go to bank 0 BCF STATUS,RP1 ; Go to bank 0 MOVLW 0x07 ; Turn comparators off MOVWF CMCON BSF STATUS,RP0 ; Go to bank 1 CLRF TRISA ; Set port A as all outputs BSF TRISA,4 ; except port A (DCFIN) CLRF TRISB ; Set port B as all outputs MOVLW B'00000111' MOVWF OPTION_REG ; Weak pullups, prescaler Timer0, 1:256 (0.26ms per count for Timer0) BCF STATUS,RP0 ; Go back to bank 0 BSF T1CON,T1CKPS1 ; These set the TIMER1 prescaler. Here are the possible values: BSF T1CON,T1CKPS0 ; 00=1:1 01=1:2 10=1:4 11=1:8. Now set to 1:4 BCF T1CON,T1OSCEN ; Turn off the TIMER1 oscillator to save power (we don't need it because we're using the internal oscillator) BCF T1CON,TMR1CS ; Select the internal oscillator for TIMER1 BSF T1CON,TMR1ON ; Enable TIMER1 BSF T2CON,T2CKPS1 ; Prescale 1:16 for TIMER2 BCF T2CON,T2CKPS0 ; BCF T2CON,TOUTPS3 ; Postscale 1:1 for TIMER2 BCF T2CON,TOUTPS2 ; BCF T2CON,TOUTPS1 ; BCF T2CON,TOUTPS0 ; BSF T2CON,TMR2ON ; Enable TIMER2 ; Enable interrupts BCF INTCON,INTF ; Clear INTF flag before enabling interrupts BCF INTCON,T0IF ; Clear T0IF (TIMER0 Interrupt Flag) before enabling interrupts BCF PIR1,TMR1IF ; Clear TMR1IF (TIMER1 Interrupt Flag) before enabling interrupts BCF PIR1,TMR2IF ; Clear TMR2IF (TIMER1 Interrupt Flag) before enabling interrupts BCF INTCON,INTE ; Disable interrupt on RB0/INT pin (an External interrupt) BSF INTCON,PEIE ; Enable PEIE (PEripheral Interrupt Enable - for TIMER1, the 16 bit timer) BSF STATUS,RP0 ; Go to bank 1 BSF PIE1,TMR1IE ; Enable interrupt on TIMER1 overflow (when the TMR1 register pair wraps around from 0xFFFF to 0x0000) BSF PIE1,TMR2IE ; Enable interrupt on TIMER2 overflow BCF PIE1,CMIE ; Disable interrupt on comparator output change BCF STATUS,RP0 ; Go to bank 0 BSF INTCON,GIE ; Enable global interrupts ; INIT Registers CLRF TMR1H CLRF TMR1L CLRF THOURS CLRF HOURS CLRF TMINS CLRF MINS CLRF TSECS CLRF HSECS CLRF FLAGS ; INIT Ports CLRF PORTB CLRF PORTA WaitForInterrupt GOTO WaitForInterrupt ; Do Nothing ; Lookup tables ORG 0x240 row0show ADDWF PCL,F ; Jump into the lookup table RETLW B'11100000' ; 0 RETLW B'11000000' ; 1 RETLW B'11100000' ; 2 RETLW B'11100000' ; 3 RETLW B'10000000' ; 4 RETLW B'11100000' ; 5 RETLW B'11000000' ; 6 with short top bar RETLW B'11100000' ; 7 RETLW B'11100000' ; 8 RETLW B'11100000' ; 9 row1show ADDWF PCL,F ; Jump into the lookup table RETLW B'10100000' ; 0 RETLW B'01000000' ; 1 RETLW B'00100000' ; 2 RETLW B'00100000' ; 3 RETLW B'10100000' ; 4 RETLW B'10000000' ; 5 RETLW B'10000000' ; 6 RETLW B'10100000' ; 7 with a hook RETLW B'10100000' ; 8 RETLW B'10100000' ; 9 row2show ADDWF PCL,F ; Jump into the lookup table RETLW B'10100000' ; 0 RETLW B'01000000' ; 1 RETLW B'11100000' ; 2 RETLW B'11100000' ; 3 RETLW B'11100000' ; 4 RETLW B'11100000' ; 5 RETLW B'11100000' ; 6 RETLW B'00100000' ; 7 RETLW B'11100000' ; 8 RETLW B'11100000' ; 9 row3show ADDWF PCL,F ; Jump into the lookup table RETLW B'10100000' ; 0 RETLW B'01000000' ; 1 RETLW B'10000000' ; 2 RETLW B'00100000' ; 3 RETLW B'00100000' ; 4 RETLW B'00100000' ; 5 RETLW B'10100000' ; 6 RETLW B'00100000' ; 7 RETLW B'10100000' ; 8 RETLW B'00100000' ; 9 row4show ADDWF PCL,F ; Jump into the lookup table RETLW B'11100000' ; 0 RETLW B'11100000' ; 1 RETLW B'11100000' ; 2 RETLW B'11100000' ; 3 RETLW B'00100000' ; 4 RETLW B'11100000' ; 5 RETLW B'11100000' ; 6 RETLW B'00100000' ; 7 RETLW B'11100000' ; 8 RETLW B'11100000' ; 9 with long tail NOP END