; Copyright (C) 2018 H.Poetzl ; ; This program is free software: you can redistribute it and/or ; modify it under the terms of the GNU General Public License ; as published by the Free Software Foundation, either version ; 2 of the License, or (at your option) any later version. ; PROCESSOR 16F1718 RADIX dec INCLUDE "p16f1718.inc" __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_ON & _BOREN_ON & _FCMEN_OFF __config _CONFIG2, _PLLEN_OFF & _ZCDDIS_OFF & _PPS1WAY_OFF ; 0x2000 Bank 0 PORT, PIR, TMR 0/1/2 ; 0x2050 Bank 1 TRIS, PIE, OSC ; 0x20A0 Bank 2 LAT, CM 1/2, DAC 1/2 ; 0x20F0 Bank 3 ANSEL, UART 1 ; 0x2140 Bank 4 WPU, SSP 1 ; 0x2190 Bank 5 ODCON, CCP 1/2 ; 0x21E0 Bank 6 SRLCON ; 0x2230 Bank 7 INLVL, IOC ; 0x2280 Bank 8 TMR 4/6 ; 0x22D0 Bank 9 NCO 1 ; 0x2320 Bank 10 OPA 1/2 ; 0x2370 Bank 11 ; 0x23C0 Bank 12 PWM 3/4 ; 0x2410 Bank 13 COG 1 ; 0x2460 Bank 14 ; 0x24B0 Bank 15 ; 0x2500 Bank 16 ; 0x2550 Bank 17 ; 0x25A0 Bank 18 ; 0x25F0 Bank 19 ; 0x2640 Bank 20 ; 0x2690 Bank 21 ; 0x26E0 Bank 22 ; 0x2730 Bank 23 ; 0x2780 Bank 24 ; 0x27D0 Bank 25 ; FSR0H 0x25 Bank 16-19 ; 0x2500 Port A change flags ; 0x2501 Port B change flags ; 0x2502 Port C change flags ; 0x2504 Port A status ; 0x2505 Port B status ; 0x2506 Port C status ; 0x2510 Quadrature encoder 1 ; 0x2511 Quadrature encoder 2 ; 0x2520 PWM Red / Pattern ; 0x2521 PWM Green / Pattern ; 0x2522 PWM Blue / Pattern ; 0x2523 PWM Load ; 0x2530 Pattern Red 7:0 ; 0x2531 Pattern Reg 15:8 ; 0x2532 Pattern Green 7:0 ; 0x2533 Pattern Green 15:8 ; 0x2534 Pattern Blue 7:0 ; 0x2535 Pattern Blue 15:8 ; 0x2536 Pattern Load ; FSR1H 0x26 Bank 19-22 C1 EQU 0x70 C2 EQU 0x71 C3 EQU 0x72 C4 EQU 0x73 I0 EQU 0x78 ; interrupt temp _cyrl EQU 0x020 ; 0x2000 Cycle Red (low) _cyrh EQU 0x021 ; 0x2001 Cycle Red (high) _cygl EQU 0x022 ; 0x2002 Cycle Green (low) _cygh EQU 0x023 ; 0x2003 Cycle Green (high) _cybl EQU 0x024 ; 0x2004 Cycle Blue (low) _cybh EQU 0x025 ; 0x2005 Cycle Blue (high) _adr EQU 0x220 ; 0x2140 I2C addr _idx EQU 0x221 ; 0x2141 I2C index _cnt EQU 0x222 ; 0x2142 I2C byte QE1CNT EQU 0x830 ; 0x2510 quadrature encoder 1 QE2CNT EQU 0x831 ; 0x2511 quadrature encoder 2 PWM_R EQU 0x840 ; 0x2520 red pwm PWM_G EQU 0x841 ; 0x2521 green pwm PWM_B EQU 0x842 ; 0x2522 blue pwm PWM_L EQU 0x843 ; 0x2523 load pwm PAT_RL EQU 0x850 ; 0x2530 red pattern 7:0 PAT_RH EQU 0x851 ; 0x2531 red pattern 15:8 PAT_GL EQU 0x852 ; 0x2532 green pattern 7:0 PAT_GH EQU 0x853 ; 0x2533 green pattern 15:8 PAT_BL EQU 0x854 ; 0x2534 blue pattern 7:0 PAT_BH EQU 0x855 ; 0x2535 blue pattern 15:8 PAT_L EQU 0x856 ; 0x2536 pattern load ; reset vector ORG __VECTOR_RESET PAGESEL init GOTO init ; interrupt vector ORG __VECTOR_INT BANKSEL PIR1 BTFSS PIR1,SSP1IF BRA _ssp1x BCF PIR1,SSP1IF ; clear interrupt BANKSEL SSP1STAT BTFSS SSP1STAT,BF ; data in buffer? BRA _read BTFSC SSP1STAT,D_NOT_A ; data or addr? BRA _data MOVFW SSP1BUF ; get address MOVWF _adr ; save address MOVLW 0xFF MOVWF _cnt ; set cnt to -1 BTFSS SSP1STAT,R_NOT_W GOTO _ssp1x _read: BTFSC SSP1CON1,CKP ; clock active?? GOTO _ssp1x MOVFW _idx ; current index MOVWF FSR0L MOVFW INDF0 ; get buf data MOVWF SSP1BUF ; transmission BSF SSP1CON1,CKP ; release SCL MOVLW 0x4 SUBWF _idx,W ; idx < 4 ? SKPC CLRF INDF0 ; zero register INCF _idx,F ; increment idx GOTO _ssp1x _data: INCFSZ _cnt,F ; index write? BRA _write MOVFW SSP1BUF ; get i2c index MOVWF _idx ; update index GOTO _ssp1x _write: MOVFW _idx ; current index MOVWF FSR0L MOVFW SSP1BUF ; get i2c data MOVWF INDF0 ; store to buffer INCF _idx,F ; increment idx _ssp1x: BANKSEL INTCON BTFSS INTCON,IOCIF BRA _iocx BANKSEL IOCAF CLRF FSR0L MOVFW IOCAF BZ _iocax IORWF INDF0,F ; add change mask MOVWF I0 ; safe ioc flags XORLW 0xFF ANDWF IOCAF,F ; clear flag BANKSEL PORTA MOVFW PORTA MOVWI 4[FSR0] ; update port reg BTFSS I0,7 ; change on E1_A? GOTO _qe1x MOVWF I0 LSLF I0,W XORWF I0,W ; E1_A xor E1_B BANKSEL QE1CNT BTFSC WREG,7 ; decrement? INCF QE1CNT,F BTFSS WREG,7 ; increment? DECF QE1CNT,F _qe1x: BANKSEL IOCBF _iocax: INCF FSR0L,F MOVFW IOCBF BZ _iocbx IORWF INDF0,F ; add change mask XORLW 0xFF ANDWF IOCBF,F ; clear flag BANKSEL PORTB MOVFW PORTB MOVWI 4[FSR0] ; update port reg BANKSEL IOCCF _iocbx: INCF FSR0L,F MOVFW IOCCF BZ _iocx IORWF INDF0,F ; add change mask MOVWF I0 ; safe ioc flags XORLW 0xFF ANDWF IOCCF,F ; clear flag BANKSEL PORTC MOVFW PORTC MOVWI 4[FSR0] ; update port reg BTFSS I0,5 ; change on E2_A? GOTO _qe2x MOVWF I0 LSRF I0,W XORWF I0,W ; E2_A xor E2_B BANKSEL QE2CNT BTFSC WREG,5 ; decrement? INCF QE2CNT,F BTFSS WREG,5 ; increment? DECF QE2CNT,F _qe2x: _iocx: BANKSEL PIR1 BTFSS PIR1,TMR1IF BRA _tmr1x BCF PIR1,TMR1IF ; clear interrupt BANKSEL _cybl RLF _cybh,W RLF _cybl,F RLF _cybh,F BANKSEL CLC1CON SKPNC BSF CLC1CON,7 SKPC BCF CLC1CON,7 BANKSEL _cygl RLF _cygh,W RLF _cygl,F RLF _cygh,F BANKSEL CLC3CON SKPNC BSF CLC3CON,7 SKPC BCF CLC3CON,7 BANKSEL CM1CON0 SKPNC BSF CM1CON0,7 SKPC BCF CM1CON0,7 BANKSEL _cyrl RLF _cyrh,W RLF _cyrl,F RLF _cyrh,F BANKSEL CLC2CON SKPNC BSF CLC2CON,7 SKPC BCF CLC2CON,7 _tmr1x: RETFIE init: BANKSEL LATA MOVLW 00000111b MOVWF LATA MOVLW 00000010b MOVWF LATB CLRF LATC BANKSEL TRISA MOVLW 11111000b ; RA0-RA2 out MOVWF TRISA MOVLW 11111101b ; RB1 out [COMP] MOVWF TRISB MOVLW 01111110b ; RC0,RC7 out MOVWF TRISC ; setup Pin Properties BANKSEL ANSELA CLRF ANSELA CLRF ANSELB CLRF ANSELC BANKSEL ODCONA MOVLW 00000111b ; RA0-RA2 od MOVWF ODCONA CLRF ODCONB CLRF ODCONC BANKSEL WPUA MOVLW 11111000b ; RA3-RA7 up MOVWF WPUA MOVLW 11111101b ; all but RB1 MOVWF WPUB MOVLW 01111110b ; RC1-RC6 up MOVWF WPUC BANKSEL INLVLA MOVLW 11111111b ; all ST MOVWF INLVLA MOVWF INLVLB MOVWF INLVLC BANKSEL OPTION_REG BCF OPTION_REG,NOT_WPUEN ; setup PPS BANKSEL PPSLOCK BCF PPSLOCK, PPSLOCKED MOVLW 01111b ; RB7 MOVWF SSPDATPPS MOVLW 01110b ; RB6 MOVWF SSPCLKPPS BANKSEL RB7PPS MOVLW 10001b ; SDA MOVWF RB7PPS MOVLW 10000b ; SCL MOVWF RB6PPS BANKSEL CLCIN2PPS MOVLW 01101b ; RB5 [P13] MOVWF CLCIN2PPS BANKSEL RA0PPS MOVLW 00100b ; CLC1OUT MOVWF RA0PPS BANKSEL RA1PPS MOVLW 10110b ; C1OUT MOVWF RA1PPS BANKSEL RA2PPS MOVLW 00101b ; CLC2OUT MOVWF RA2PPS BANKSEL RB1PPS MOVLW 00110b ; CLC3OUT MOVWF RB1PPS ; setup indirect memory MOVLW 0x25 ; 0x25xx MOVWF FSR0H MOVLW 0x26 ; 0x26xx MOVWF FSR1H ; setup oscillator BANKSEL OSCCON MOVLW 01111000b MOVWF OSCCON ; initialize ram BANKSEL _adr CLRF _adr CLRF _cnt CLRF _idx BANKSEL _cyrl MOVLW 0xFF MOVWF _cyrl MOVWF _cyrh MOVWF _cygl MOVWF _cygh MOVWF _cybl MOVWF _cybh BANKSEL QE1CNT CLRF QE1CNT CLRF QE2CNT BANKSEL PWM_R CLRF PWM_R CLRF PWM_G CLRF PWM_B ; setup SSP1 BANKSEL SSP1STAT CLRF SSP1STAT BSF SSP1STAT,SMP MOVLW 0110b ; 7bit slave mode MOVWF SSP1CON1 BSF SSP1CON1,SSPEN ; enable I2C BSF SSP1CON1,CKP ; enable I2C clock CLRF SSP1CON2 BCF SSP1CON2,SEN ; clock stretching disabled BSF SSP1CON2,GCEN ; general call enabled CLRF SSP1CON3 BSF SSP1CON3,BOEN ; buffer override enabled BSF SSP1CON3,SCIE ; start condition irq BCF SSP1CON3,PCIE ; stop condition irq MOVLW 00100000b ; address 0x10 MOVWF SSP1ADD MOVLW 11111110b ; address mask MOVWF SSP1MSK ; setup IOC BANKSEL IOCAP MOVLW 10111000b ; RA3-RA7, not RA6 MOVWF IOCAP MOVWF IOCAN MOVLW 00101100b ; RB2,RB3 and RB5 MOVWF IOCBP MOVWF IOCBN MOVLW 00111100b ; RC2-RC5 MOVWF IOCCP MOVWF IOCCN ; setup CLC BANKSEL CLC1CON ; MOVLW 00010b ; CLCIN2 [P13] MOVLW 01100b ; CCP1 MOVWF CLC1SEL0 MOVWF CLC1SEL1 MOVWF CLC1SEL2 MOVWF CLC1SEL3 MOVLW 01010101b ; AND MOVWF CLC1GLS0 MOVWF CLC1GLS1 MOVWF CLC1GLS2 MOVWF CLC1GLS3 MOVLW 10001111b ; NAND MOVWF CLC1POL MOVLW 10000010b ; 4-in-AND MOVWF CLC1CON BANKSEL CLC2CON ; MOVLW 00010b ; CLCIN2 [P13] MOVLW 01101b ; CCP2 MOVWF CLC2SEL0 MOVWF CLC2SEL1 MOVWF CLC2SEL2 MOVWF CLC2SEL3 MOVLW 01010101b ; AND MOVWF CLC2GLS0 MOVWF CLC2GLS1 MOVWF CLC2GLS2 MOVWF CLC2GLS3 MOVLW 10001111b ; NAND MOVWF CLC2POL MOVLW 10000010b ; 4-in-AND MOVWF CLC2CON BANKSEL CLC3CON MOVLW 01110b ; PWM3 MOVWF CLC3SEL0 MOVWF CLC3SEL1 MOVWF CLC3SEL2 MOVWF CLC3SEL3 MOVLW 01010101b ; AND MOVWF CLC3GLS0 MOVWF CLC3GLS1 MOVWF CLC3GLS2 MOVWF CLC3GLS3 ; MOVLW 10001111b ; NAND MOVLW 00001111b ; AND MOVWF CLC3POL MOVLW 10000010b ; 4-in-AND MOVWF CLC3CON ; setup FVR BANKSEL FVRCON MOVLW 10001000b ; 2xFVR for CM MOVWF FVRCON ; setup Comparator 1 BANKSEL CM1CON0 MOVLW 00110011b ; +FVR, C1IN3- [RB1] MOVWF CM1CON1 ; MOVLW 10001100b ; async, speed MOVLW 10011100b ; async, speed, inv MOVWF CM1CON0 ; setup TMR1 BANKSEL T1CON CLRF T1GCON CLRF TMR1L CLRF TMR1H MOVLW 00110001b ; 1:8, on MOVWF T1CON ; setup TMR2 BANKSEL T2CON MOVLW 0x00 ; offset 0/3 MOVWF TMR2 MOVLW 0xFF MOVWF PR2 MOVLW 00000001b ; 1:4, 1:1, off MOVWF T2CON ; setup TMR4 BANKSEL T4CON MOVLW 0x55 ; offset 1/3 MOVWF TMR4 MOVLW 0xFF MOVWF PR4 MOVLW 00000001b ; 1:4, 1:1, off MOVWF T4CON ; setup TMR6 BANKSEL T6CON MOVLW 0xAA ; offset 2/3 MOVWF TMR6 MOVLW 0xFF MOVWF PR6 MOVLW 00000001b ; 1:4, 1:1, off MOVWF T6CON ; start TMR2/4/6 BANKSEL T2CON BSF T2CON,TMR2ON BANKSEL T4CON BSF T4CON,TMR4ON BANKSEL T6CON BSF T6CON,TMR6ON ; setup PWM BANKSEL CCPTMRS MOVLW 00100100b ; TMR2/4/6 MOVWF CCPTMRS BANKSEL CCP1CON MOVLW 00001100b ; PWM mode MOVWF CCP1CON CLRF CCPR1L BANKSEL CCP2CON MOVLW 00001100b ; PWM mode MOVWF CCP2CON CLRF CCPR2L BANKSEL PWM3CON MOVLW 10010000b ; active low, on MOVWF PWM3CON CLRF PWM3DCH CLRF PWM3DCL ; enable IRQ BANKSEL PIR1 BCF PIR1,SSP1IF ; clear I2C IRQ BANKSEL PIE1 BSF PIE1,SSP1IE ; enable I2C IRQ BSF PIE1,TMR1IE ; enable TMR1 IRQ BANKSEL INTCON BSF INTCON,IOCIE ; enable IOC IRQ BSF INTCON,PEIE ; enable peripheral IRQ BSF INTCON,GIE ; enable global IRQ goto main delay: MOVLW 0x10 MOVWF C3 dloop: DECFSZ C1,F GOTO dloop DECFSZ C2,F GOTO dloop DECFSZ C3,F GOTO dloop RETURN cpwm1v macro val errorlevel -1302 MOVLW (val >> 2) MOVWF CCPR1L MOVLW ((val & 3) << 4) | 1100b MOVWF CCP1CON RETURN errorlevel +1302 endm cpwm1: ANDLW 0xF BANKSEL CCP1CON BRW GOTO _pwm10 GOTO _pwm11 GOTO _pwm12 GOTO _pwm13 GOTO _pwm14 GOTO _pwm15 GOTO _pwm16 GOTO _pwm17 GOTO _pwm18 GOTO _pwm19 GOTO _pwm1A GOTO _pwm1B GOTO _pwm1C GOTO _pwm1D GOTO _pwm1E GOTO _pwm1F _pwm10: cpwm1v 0 _pwm11: cpwm1v 1 _pwm12: cpwm1v 2 _pwm13: cpwm1v 4 _pwm14: cpwm1v 6 _pwm15: cpwm1v 10 _pwm16: cpwm1v 16 _pwm17: cpwm1v 25 _pwm18: cpwm1v 40 _pwm19: cpwm1v 64 _pwm1A: cpwm1v 101 _pwm1B: cpwm1v 161 _pwm1C: cpwm1v 256 _pwm1D: cpwm1v 406 _pwm1E: cpwm1v 644 _pwm1F: cpwm1v 1023 cpwm2v macro val errorlevel -1302 MOVLW (val >> 2) MOVWF CCPR2L MOVLW ((val & 3) << 4) | 1100b MOVWF CCP2CON RETURN errorlevel +1302 endm cpwm2: ANDLW 0xF BANKSEL CCP2CON BRW GOTO _pwm20 GOTO _pwm21 GOTO _pwm22 GOTO _pwm23 GOTO _pwm24 GOTO _pwm25 GOTO _pwm26 GOTO _pwm27 GOTO _pwm28 GOTO _pwm29 GOTO _pwm2A GOTO _pwm2B GOTO _pwm2C GOTO _pwm2D GOTO _pwm2E GOTO _pwm2F _pwm20: cpwm2v 0 _pwm21: cpwm2v 1 _pwm22: cpwm2v 2 _pwm23: cpwm2v 4 _pwm24: cpwm2v 6 _pwm25: cpwm2v 10 _pwm26: cpwm2v 16 _pwm27: cpwm2v 25 _pwm28: cpwm2v 40 _pwm29: cpwm2v 64 _pwm2A: cpwm2v 101 _pwm2B: cpwm2v 161 _pwm2C: cpwm2v 256 _pwm2D: cpwm2v 406 _pwm2E: cpwm2v 644 _pwm2F: cpwm2v 1023 cpwm3v macro val errorlevel -1302 MOVLW (val >> 2) MOVWF PWM3DCH MOVLW ((val & 3) << 6) MOVWF PWM3DCL RETURN errorlevel +1302 endm cpwm3: ANDLW 0xF BANKSEL PWM3DCH BRW GOTO _pwm30 GOTO _pwm31 GOTO _pwm32 GOTO _pwm33 GOTO _pwm34 GOTO _pwm35 GOTO _pwm36 GOTO _pwm37 GOTO _pwm38 GOTO _pwm39 GOTO _pwm3A GOTO _pwm3B GOTO _pwm3C GOTO _pwm3D GOTO _pwm3E GOTO _pwm3F _pwm30: cpwm3v 0 _pwm31: cpwm3v 1 _pwm32: cpwm3v 2 _pwm33: cpwm3v 4 _pwm34: cpwm3v 6 _pwm35: cpwm3v 10 _pwm36: cpwm3v 16 _pwm37: cpwm3v 25 _pwm38: cpwm3v 40 _pwm39: cpwm3v 64 _pwm3A: cpwm3v 101 _pwm3B: cpwm3v 161 _pwm3C: cpwm3v 256 _pwm3D: cpwm3v 406 _pwm3E: cpwm3v 644 _pwm3F: cpwm3v 1023 patl: ANDLW 0xF BRW RETLW 0xFF ; 0 - all on RETLW 0xFF ; 1 - slowest RETLW 0x0F ; 2 - slow RETLW 0x33 ; 3 - fast RETLW 0x55 ; 4 - fastest RETLW 0x0F ; 5 - flash 25.0 RETLW 0x03 ; 6 - flash 12.5 RETLW 0x01 ; 7 - flash 6.25 RETLW 0x00 ; 8 - inv 0 RETLW 0x00 ; 9 - inv 1 RETLW 0xF0 ; A - inv 2 RETLW 0xCC ; B - inv 3 RETLW 0xAA ; C - inv 4 RETLW 0xF0 ; D - inv 5 RETLW 0xFC ; E - inv 6 RETLW 0xFE ; F - inv 7 path: ANDLW 0xF BRW RETLW 0xFF ; 0 - all on RETLW 0x00 ; 1 - slowest RETLW 0x0F ; 2 - slow RETLW 0x33 ; 3 - fast RETLW 0x55 ; 4 - fastest RETLW 0x00 ; 5 - flash 25.0 RETLW 0x00 ; 6 - flash 12.5 RETLW 0x00 ; 7 - flash 6.25 RETLW 0x00 ; 8 - inv 0 RETLW 0xFF ; 9 - inv 1 RETLW 0xF0 ; A - inv 2 RETLW 0xCC ; B - inv 3 RETLW 0xAA ; C - inv 4 RETLW 0xFF ; D - inv 5 RETLW 0xFF ; E - inv 6 RETLW 0xFF ; F - inv 7 main: BANKSEL PWM_L TSTF PWM_L BZ _pwmx CLRF PWM_L MOVFW PWM_R CALL cpwm2 BANKSEL PWM_R SWAPF PWM_R,W CALL patl MOVWF PAT_RL SWAPF PWM_R,W CALL path MOVWF PAT_RH MOVFW PWM_G CALL cpwm3 BANKSEL PWM_G SWAPF PWM_G,W CALL patl MOVWF PAT_GL SWAPF PWM_G,W CALL path MOVWF PAT_GH MOVFW PWM_B CALL cpwm1 BANKSEL PWM_B SWAPF PWM_B,W CALL patl MOVWF PAT_BL SWAPF PWM_B,W CALL path MOVWF PAT_BH BSF PAT_L,7 _pwmx: BANKSEL PAT_L TSTF PAT_L BZ _patx MOVLW 0x30 MOVWF FSR0L BANKSEL INTCON BCF INTCON,GIE ; disable global IRQ BANKSEL _cyrl ; load patterns MOVIW 0[FSR0] MOVWF _cyrl MOVIW 1[FSR0] MOVWF _cyrh MOVIW 2[FSR0] MOVWF _cygl MOVIW 3[FSR0] MOVWF _cygh MOVIW 4[FSR0] MOVWF _cybl MOVIW 5[FSR0] MOVWF _cybh BANKSEL INTCON BSF INTCON,GIE ; enable global IRQ BANKSEL PAT_L CLRF PAT_L _patx: GOTO main end