;4 chan DMX, PWM output
;On RB5, RB6, RB7, RA3
;Thijs Assies
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC & _LVP_OFF
list P=16F628A
#INCLUDE <P16F628a.INC>
#DEFINE OUT1 PORTB,5
#DEFINE OUT2 PORTB,6
#DEFINE OUT3 PORTB,7
#DEFINE OUT4 PORTA,3
#DEFINE RCLED PORTB,3 ;green led
#DEFINE RX PORTB,1
#DEFINE ERRLED PORTB,4 ;red led
#DEFINE BREAK DMX_reg,0
#DEFINE STARTCODE DMX_reg,1
#DEFINE MOVED DMX_reg,2
#DEFINE ADDR9 DMX_reg,3
#DEFINE RC9 DMX_reg,4
DMX_reg EQU 020h
Reg1 EQU 021h
Reg2 EQU 022h
Reg3 EQU 023h
Reg4 EQU 024h
W_SAVE EQU 026h
S_SAVE EQU 027h
P_SAVE EQU 028h
pwmcounter EQU 029h
flag EQU 02Ah
D_ADDR EQU 02Bh
temp EQU 02Ch
R_ADDR EQU 02Dh
Offset EQU 02Eh
temp2 EQU 02Fh
ORG 00h
GOTO INIT ;Initialize PIC
ORG 04h ;Interrupt vector
MOVWF W_SAVE ;save context,
MOVF STATUS,W ;save STATUS, PCLATH & W
MOVWF S_SAVE
MOVF PCLATH,W
MOVWF P_SAVE
GOTO INTHANDLER
INIT
MOVLW 0x07 ;turn analog comparators off
MOVWF CMCON
CLRF PORTA
CLRF PORTB
BSF STATUS,RP0 ;Select Bank1
CLRF TRISA ;porta output
CLRF TRISB ;portb output
BSF TRISB,1 ;B1 input (UART Recieve)
MOVLW 04h
MOVWF SPBRG ;Set baud rate
BSF TXSTA,BRGH ;high speed
BCF TXSTA,SYNC ;Async connection
CLRF PIE1 ;clear other interrupts
BSF PIE1,RCIE ;Set recieve interrupt
BCF STATUS,RP0 ;Return to bank0
BSF RCSTA,RX9 ;Enable 9bit data
MOVF RCREG,W ;clear RCREG FIFO
MOVF RCREG,W
MOVF RCREG,W
BSF RCSTA,CREN ;Enable recieve
BSF RCSTA,SPEN ;Enable UART
BSF INTCON,PEIE ;Enable interrupts
BSF INTCON,GIE
BCF RCLED ;because RA4 is open drain, set means NOT on
BCF ERRLED
CLRF Reg1
CLRF Reg2
CLRF Reg3
CLRF Reg4
CLRF D_ADDR ;set our dmx adress to 0
BCF ADDR9
GOTO MAIN ;Goto Main Program
MAIN
BCF RCLED
BCF ERRLED
MOVLW 0FFh
MOVWF pwmcounter
BCF OUT1
BCF OUT2
BCF OUT3
BCF OUT4
CALL PWM_CYCLE
GOTO MAIN
PWM_CYCLE
MOVF Reg1,W
XORWF pwmcounter,W
BTFSC STATUS,Z
BSF OUT1
MOVF Reg2,W
XORWF pwmcounter,W
BTFSC STATUS,Z
BSF OUT2
MOVF Reg3,W
XORWF pwmcounter,W
BTFSC STATUS,Z
BSF OUT3
MOVF Reg4,W
XORWF pwmcounter,W
BTFSC STATUS,Z
BSF OUT4
DECFSZ pwmcounter
GOTO PWM_CYCLE
RETURN
INTRETURN
MOVF P_SAVE,W ;restore context
MOVWF PCLATH
MOVF S_SAVE,W
MOVWF STATUS
SWAPF W_SAVE,F
SWAPF W_SAVE,W
RETFIE
INTHANDLER
BTFSS PIR1,RCIF
GOTO INTRETURN
BTFSC NO_DMX
MOVF RCREG,W
BTFSC NO_DMX
GOTO INTRETURN
GOTO DMX
DMX
BSF ERRLED
BTFSC RCSTA,OERR
GOTO OVERRUN
BTFSC RCSTA,FERR ;Check for framing error
GOTO FRAME
BTFSS BREAK ;check if break has passed
GOTO RET
BTFSS STARTCODE ;has a startcode passed ?
GOTO SC ;yes: go check for valid startcode
BTFSC STARTCODE
GOTO CHANNEL
RET
MOVF RCREG,W
GOTO INTRETURN
OVERRUN
BCF RCSTA,SPEN
BSF RCSTA,SPEN
MOVF RCREG,W
BSF ERRLED
GOTO LAST
FRAME
BCF BREAK
BCF STARTCODE
BCF RC9
CLRF R_ADDR
CLRF Offset
BTFSS RCSTA,RX9D
BSF BREAK
MOVF RCREG,W
GOTO INTRETURN
SC
MOVF RCREG,W
XORLW 00h
BTFSC STATUS,Z
BSF STARTCODE
GOTO INTRETURN
INCREASE
INCF R_ADDR
BTFSC STATUS,Z
BSF RC9
RETURN
CHANNEL
MOVF Offset,W
XORLW 00h ;check if offset != 0
BTFSS STATUS,Z
GOTO CHAN
MOVF R_ADDR,W ;else: check if chans match
XORWF D_ADDR,W
BTFSC STATUS,Z
GOTO NINTH ;if so: check for 9th bit
CALL INCREASE
GOTO RET ;if not: just return from interrupt
NINTH
BTFSC ADDR9
GOTO TRUE
MOVF RCREG,W
GOTO FALSE
TRUE ;our 9th bit is set
BTFSC RC9
GOTO CHAN
CALL INCREASE
GOTO RET
FALSE
BTFSS RC9
GOTO CHAN
CALL INCREASE
GOTO RET
CHAN
; BCF RCLED
INCF Offset
MOVF Offset,W
XORLW 01h ;check if count = 0
BTFSC STATUS,Z
GOTO CHAN1
MOVF Offset,W
XORLW 02h
BTFSC STATUS,Z
GOTO CHAN2
MOVF Offset,W
XORLW 03h
BTFSC STATUS,Z
GOTO CHAN3
MOVF Offset,W
XORLW 04h
BTFSC STATUS,Z
GOTO CHAN4
MOVF Offset,W
XORLW 05h
BTFSC STATUS,Z
GOTO LAST
CHAN1
MOVF RCREG,W
MOVWF Reg1
CALL INCREASE
GOTO INTRETURN
CHAN2
MOVF RCREG,W
MOVWF Reg2
CALL INCREASE
GOTO INTRETURN
CHAN3
MOVF RCREG,W
MOVWF Reg3
CALL INCREASE
GOTO INTRETURN
CHAN4
MOVF RCREG,W
MOVWF Reg4
CALL INCREASE
GOTO INTRETURN
LAST
BCF BREAK
BCF STARTCODE
CLRF Offset
GOTO INTRETURN
END