; Frequencies needed for a PM5507 clone based on SAA1043

; Outputs CLK0 for SAA and CLK1&2 for subcarrier +/- f(h)

; The PM5507 generates a PAL rainbow test pattern for aligning color TVs.


; v0.0 230728 Start project, copy-paste from cmcd_pll_tx.asm

; v0.1 240211 Fix phase relation HSYNC and color subcarrier not defined

; v0.2 240211 Move to PIC12F675 because phase detector is not fast enough. Need external HEF4046

; v0.3 240212 Implement clock skip circuit to enable proper phase detection with 74HC4046

; v0.4 240213 Read voltage of phase detector

; v1.0 240214 Release


LIST P=12F675, F=INHX8M

#include <P12F675.INC>


__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_OFF

ERRORLEVEL -302 ; remove message about using proper bank

; Equates

RESET_V EQU 0x00 ; Address of RESET Vector


; Registers

FLAGS EQU 0x20 ; Various flags

I2CBUF EQU 0x21 ; Used for I2C data

I2CCNT EQU 0x22 ; Used for I2C bitbanger

CTR1 EQU 0x24 ; Counter for delay (inner)

CTR2 EQU 0x25 ; Second Counter (outer)

CTRP EQU 0x26 ; Number of nudges


; Defines

#define SDA GPIO,0 ; I2C Data

#define SCL GPIO,1 ; I2C Clock

#define LED GPIO,4 ; LOW: Red, HIGH: Green to show successful phase chase

#define SKIP GPIO,5 ; Drive to transistor to short SAA1043 clock input to GND in order to nudge phase

#define NAK FLAGS,1 ; Not Acknowledge after I2C byte

#define SYSINIT FLAGS,2 ; Clear when system init of Si5351A has completed

; GPIO,2 is defined as analog input (AN2)


ORG 0

GOTO START

ORG 4


; There are no interrupts

RETFIE

; End interrupts


START

; Init stuff

CLRF STATUS ; Do initialization, select Bank 0

CLRF INTCON ; Clear int-flags, disable interrupts

CLRF PCLATH ; Keep in lower 2KByte

BSF STATUS,RP0 ; Select Bank 1

MOVLW B'00000111' ; TMR0 Prescaler 1:256, enable weak pullups

MOVWF OPTION_REG

MOVLW B'00000100'

MOVWF TRISIO ; GPIO,0,1,5 outputs, GPIO,2 input

MOVLW B'01010100'

MOVWF ANSEL ; GPIO,2 is analog input

BCF STATUS,RP0 ; Select Bank 0

MOVLW B'00001001'

MOVWF ADCON0 ; A/D config

CLRF T1CON

MOVLW B'00000111' ; Comparators off

MOVWF CMCON

CLRF INTCON

CLRF GPIO

CLRF FLAGS

BSF SCL

BSF SDA


; Initialize Si5351A

INITOSC

CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

CLRW ; Prepare register 0 for reading

CALL I2CBYTE

CALL I2CSTOP


Readsysinit ; Check if Si5153A is ready (SYS_INIT)

CALL I2CSTART

MOVLW 0xC1 ; Read address

CALL I2CBYTE

CLRF I2CCNT ; Used for ACK timeout

BSF STATUS,RP0 ; Select Bank 1

BSF TRISIO,0 ; Set SDA as input to float SDA line

BCF STATUS,RP0 ; Select Bank 0

CALL I2CDELAY

BSF SCL ; Read SYS_INIT bit

CALL I2CDELAY

BTFSS SDA

BCF SYSINIT

BCF SCL

MOVLW 0x07

MOVWF I2CCNT


DUMMYREAD

CALL I2CDELAY

BSF SCL

CALL I2CDELAY

BCF SCL

DECFSZ I2CCNT,F

GOTO DUMMYREAD

BSF STATUS,RP0 ; Select Bank 1

BCF TRISIO,0 ; Set SDA as output to assert SDA line

BCF STATUS,RP0 ; Select Bank 0

BCF SDA ; Present NAK

CALL I2CDELAY

BSF SCL

CALL I2CDELAY

BCF SCL

CALL I2CSTOP

BTFSC SYSINIT ; System init done?

GOTO Readsysinit ; No


; Start configure

CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x03 ; Register 3

CALL I2CBYTE

MOVLW 0xFF ; Register 3 data (Output Enable Control)

CALL I2CBYTE

CALL I2CSTOP



CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x09 ; Register 9

CALL I2CBYTE

MOVLW 0xFF ; Register 9 data (OEB Pin Enable Control Mask)

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x10 ; Register 16

CALL I2CBYTE

MOVLW 0x4F ; Register 16 data

CALL I2CBYTE

MOVLW 0x6F ; Register 17 data

CALL I2CBYTE

MOVLW 0x2F ; Register 18 data

CALL I2CBYTE

MOVLW 0x80 ; Register 19 data

CALL I2CBYTE

MOVLW 0x80 ; Register 20 data

CALL I2CBYTE

MOVLW 0x80 ; Register 21 data

CALL I2CBYTE

MOVLW 0x80 ; Register 22 data

CALL I2CBYTE

MOVLW 0x80 ; Register 23 data

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0xB7 ; Register 183

CALL I2CBYTE

MOVLW 0xD2 ; Register 183 data: XTAL load capacitance and mandatory bit pattern

CALL I2CBYTE

CALL I2CSTOP




CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x1B ; Register 27

CALL I2CBYTE

MOVLW 0x03 ; Register 27 data

CALL I2CBYTE

CLRW ; Register 28 data is zero

CALL I2CBYTE

MOVLW 0x0E ; Register 29 data

CALL I2CBYTE

MOVLW 0xAA ; Register 30 data

CALL I2CBYTE

CLRW ; Register 31 data is zero

CALL I2CBYTE

CLRW ; Register 32 data is zero

CALL I2CBYTE

MOVLW 0x02 ; Register 33 data

CALL I2CBYTE

MOVLW 0x0D ; Register 34 data

CALL I2CBYTE

MOVLW 0x40 ; Register 35 data

CALL I2CBYTE

CLRW ; Register 36 data (zero)

CALL I2CBYTE

MOVLW 0x0D ; Register 37 data

CALL I2CBYTE

MOVLW 0xE7 ; Register 38 data

CALL I2CBYTE

MOVLW 0x31 ; Register 39 data

CALL I2CBYTE

MOVLW 0xE6 ; Register 40 data

CALL I2CBYTE

MOVLW 0xC0 ; Register 41 data

CALL I2CBYTE

CLRW ; Register 42 data (zero)

CALL I2CBYTE

MOVLW 0x03 ; Register 43 data

CALL I2CBYTE

CLRW ; Register 44 data (zero)

CALL I2CBYTE

MOVLW 0x51 ; Register 45 data

CALL I2CBYTE

MOVLW 0x55 ; Register 46 data

CALL I2CBYTE

CLRW ; Register 47 data (zero)

CALL I2CBYTE

CLRW ; Register 48 data (zero)

CALL I2CBYTE

MOVLW 0x01 ; Register 49 data

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x33 ; Register 51

CALL I2CBYTE

MOVLW 0x01 ; Register 51 data

CALL I2CBYTE

CLRW ; Register 52 data (zero)

CALL I2CBYTE

MOVLW 0x58 ; Register 53 data

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x3A ; Register 58

CALL I2CBYTE

MOVLW 0x9E ; Register 58 data

CALL I2CBYTE

MOVLW 0xED ; Register 59 data

CALL I2CBYTE

CLRW ; Register 60 data (zero)

CALL I2CBYTE

MOVLW 0x57 ; Register 61 data

CALL I2CBYTE

MOVLW 0x5E ; Register 62 data

CALL I2CBYTE

MOVLW 0x30 ; Register 63 data

CALL I2CBYTE

MOVLW 0xA1 ; Register 64 data

CALL I2CBYTE

MOVLW 0xFA ; Register 65 data

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0xB1 ; Register 177

CALL I2CBYTE

MOVLW 0xA0 ; Register 177 data (Reset PLLA&B)

CALL I2CBYTE

CALL I2CSTOP


CALL I2CSTART

MOVLW 0xC0 ; Address

CALL I2CBYTE

MOVLW 0x03 ; Register 3

CALL I2CBYTE

MOVLW 0xF8 ; Register 3 data: enable CLK0, CLK1 and CLK2

CALL I2CBYTE

CALL I2CSTOP

; Done setup Si5351A


MOVLW 0x14 ; 20 nudges to ensure PC2 is positive

MOVWF CTRP

BSF SKIP ; Skip phase (~10 clock pulses SAA1043)

BCF SKIP

CALL DELAY

DECFSZ CTRP

GOTO $-4


NUDGE1

BSF SKIP ; Skip phase (~10 clock pulses SAA1043)

BCF SKIP

CALL DELAY

BSF ADCON0,GO

BTFSC ADCON0,GO

GOTO $-1

MOVLW 0x80

SUBWF ADRESH,W

BTFSC STATUS,C ; Carry set (ADRESH>=0x80)?

GOTO NUDGE1 ; Yes


NUDGE2

BSF SKIP ; Skip phase (~10 clock pulses SAA1043)

BCF SKIP

CALL DELAY

BSF ADCON0,GO

BTFSC ADCON0,GO

GOTO $-1

MOVLW 0xD4

SUBWF ADRESH,W

BTFSS STATUS,C ; Carry set (ADRESH>=0xD4)?

GOTO NUDGE2 ; No

BSF LED

GOTO $ ; Loop forever



; Subroutines

I2CSTART

BCF SDA

CALL I2CDELAY

BCF SCL

CALL I2CDELAY

RETURN


I2CBYTE ; Sends byte in W

MOVWF I2CBUF

MOVLW 0x08

MOVWF I2CCNT


NEXTBIT

BCF STATUS,C ; Clear carry

RLF I2CBUF,F ; Rotate MSB into carry

BTFSC STATUS,C ; Carry clear?

BSF SDA ; No, set SDA

BTFSS STATUS,C ; Carry set?

BCF SDA ; No, clear SDA

CALL I2CDELAY

BSF SCL ; Send clock

CALL I2CDELAY

BCF SCL ; Done clock

DECFSZ I2CCNT,F

GOTO NEXTBIT

; ACK handler

BSF STATUS,RP0 ; Select Bank 1

BSF TRISIO,0 ; Set SDA as input to float SDA line

BCF STATUS,RP0 ; Select Bank 0

BSF NAK

CALL I2CDELAY

BSF SCL ; Solicit ACK

CLRF I2CCNT


TESTACK

BTFSC SDA ; SDA pulled low?

GOTO CONTACK ; No, continue testing for ACK until timeout (~20 ms)

BCF NAK ; Clear NAK

GOTO EXITACK ; Exit loop


CONTACK

DECFSZ I2CCNT,F

GOTO TESTACK


EXITACK

BSF STATUS,RP0 ; Select Bank 1

BCF TRISIO,0 ; Set SDA as output

BCF STATUS,RP0 ; Select Bank 0

BTFSC NAK ; NAK handler

GOTO START ; Timeout, no ACK, force reset

BSF SDA ; Just in case

CALL I2CDELAY

BCF SCL

CALL I2CDELAY

RETURN


I2CSTOP

BCF SDA

CALL I2CDELAY

BSF SCL

CALL I2CDELAY

BSF SDA

RETURN

I2CDELAY

NOP ; 8 us delay

NOP

NOP

NOP

RETURN


DELAY

DECFSZ CTR1,F ; Set up 178 ms delay

GOTO DELAY

DECFSZ CTR2,F

GOTO DELAY

RETURN


END