; ****************** 16F18446 Bus Monitor Display version 01 ****************** ; This is a firmware written in assembly for https://github.com/Johnlon/SevenSegmentModule ; Important note: Don't forget to add "-PRES_VECT=0000" and "-PINT_VECT=0004h" to custom linker options! ; Navigate to: Project Properties => Conf => pic-as Global Options => pic-as Linker ; Then edit "Custom linker options". ; ********************************* CHANGELOG ********************************* ; ********** Version 01 ********** ; - Initial version ; Processor selection ;PROCESSOR 16F18446 ; Configuration for PIC16(L)F18446 ; Config bits for register: CONFIG1 @ 0x8007 ; FEXTOSC: External Oscillator mode Selection bits ;CONFIG FEXTOSC = ECH ; EC above 8MHz; PFM set to high power ;CONFIG FEXTOSC = ECM ; EC for 500kHz to 8MHz; PFM set to medium power ;CONFIG FEXTOSC = ECL ; EC below 500kHz; PFM set to low power ;CONFIG FEXTOSC = HS ; HS (crystal oscillator) above 4MHz; PFM set to high power ;CONFIG FEXTOSC = XT ; XT (crystal oscillator) above 500kHz, below 4MHz; PFM set to medium power ;CONFIG FEXTOSC = LP ; LP (crystal oscillator) optimized for 32.768kHz; PFM set to low power CONFIG FEXTOSC = OFF ; External oscillator not enabled ; RSTOSC: Power-up default value for COSC bits ;CONFIG RSTOSC = EXT1X ; EXTOSC operating per FEXTOSC bits CONFIG RSTOSC = HFINT1 ; HFINTOSC (1MHz) ;CONFIG RSTOSC = LFINT ; LFINTOSC (31kHz) ;CONFIG RSTOSC = SOSC ; SOSC (31kHz) ;CONFIG RSTOSC = EXT4X ; EXTOSC with 4x PLL, with EXTOSC operating per FEXTOSC bits ;CONFIG RSTOSC = HFINTPLL ; HFINTOSC with 2x PLL, with OSCFRQ = 16 MHz and CDIV = 1:1 (FOSC = 32 MHz) ;CONFIG RSTOSC = HFINT32 ; HFINTOSC with OSCFRQ = 32 MHz and CDIV = 1:1 ; CLKOUTEN: Clock Out Enable bit CONFIG CLKOUTEN = OFF ; CLKOUT function is disabled; I/O or oscillator function on OSC2 ;CONFIG CLKOUTEN = ON ; CLKOUT function is enabled; FOSC/4 clock appears at OSC2 ; CSWEN: Clock Switch Enable bit CONFIG CSWEN = ON ; Writing to NOSC and NDIV is allowed ;CONFIG CSWEN = OFF ; The NOSC and NDIV bits cannot be changed by user software ; FCMEN: Fail-Safe Clock Monitor Enable bit CONFIG FCMEN = ON ; Fail-Safe Clock Monitor is enabled ;CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor is disabled ; Config bits for register: CONFIG2 @ 0x8008 ; MCLRE: Master Clear Enable bit ;CONFIG MCLRE = ON ; MCLR/VPP pin function is MCLR; Weak pull-up enabled CONFIG MCLRE = OFF ; MCLR/VPP pin function is digital input; MCLR internally disabled; Weak pull-up under control of port pin's WPU control bit. ; PWRTS: Power-up Timer Selection bits CONFIG PWRTS = OFF ; PWRT disabled ;CONFIG PWRTS = PWRT_64 ; PWRT set at 64 ms ;CONFIG PWRTS = PWRT_16 ; PWRT set at 16 ms ;CONFIG PWRTS = PWRT_1 ; PWRT set at 1 ms ; LPBOREN: Low-power BOR enable bit CONFIG LPBOREN = OFF ; ULPBOR disabled ;CONFIG LPBOREN = ON ; ULPBOR enabled ; BOREN: Brown-out Reset Enable bits CONFIG BOREN = ON ; Brown-out Reset enabled, SBOREN bit ignored ;CONFIG BOREN = SLEEP ; Brown-out Reset enabled while running, disabled in Sleep; SBOREN is ignored ;CONFIG BOREN = SBOREN ; Brown-out Reset enabled according to SBOREN ;CONFIG BOREN = OFF ; Brown-out Reset disabled ; BORV: Brown-out Reset Voltage selection bit CONFIG BORV = LO ; Brown-out voltage (Vbor) set to 1.9V for PIC16LF18446 or 2.45V for PIC16F18446 ;CONFIG BORV = HI ; Brown-out voltage (Vbor) set to 2.7V ; ZCD: Zero-cross detect circuit POR mode selection bit CONFIG ZCD = OFF ; Zero-cross detect circuit is disabled at POR ;CONFIG ZCD = ON ; Zero-cross detect circuit is always enabled ; PPS1WAY: PPSLOCK bit One-Way Set Enable bit CONFIG PPS1WAY = ON ; The PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle ;CONFIG PPS1WAY = OFF ; The PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence) ; STVREN: Stack Overflow/Underflow Reset Enable bit CONFIG STVREN = ON ; Stack Overflow or Underflow will cause a Reset ;CONFIG STVREN = OFF ; Stack Overflow or Underflow will not cause a Reset ; Config bits for register: CONFIG3 @ 0x8009 ; WDTCPS: WDT Period Select bits CONFIG WDTCPS = WDTCPS_0 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_1 ; Divider ratio 1:64 ;CONFIG WDTCPS = WDTCPS_2 ; Divider ratio 1:128 ;CONFIG WDTCPS = WDTCPS_3 ; Divider ratio 1:256 ;CONFIG WDTCPS = WDTCPS_4 ; Divider ratio 1:512 ;CONFIG WDTCPS = WDTCPS_5 ; Divider ratio 1:1024 ;CONFIG WDTCPS = WDTCPS_6 ; Divider ratio 1:2048 ;CONFIG WDTCPS = WDTCPS_7 ; Divider ratio 1:4096 ;CONFIG WDTCPS = WDTCPS_8 ; Divider ratio 1:8192 ;CONFIG WDTCPS = WDTCPS_9 ; Divider ratio 1:16384 ;CONFIG WDTCPS = WDTCPS_10 ; Divider ratio 1:32768 ;CONFIG WDTCPS = WDTCPS_11 ; Divider ratio 1:65536 ;CONFIG WDTCPS = WDTCPS_12 ; Divider ratio 1:131072 ;CONFIG WDTCPS = WDTCPS_13 ; Divider ratio 1:262144 ;CONFIG WDTCPS = WDTCPS_14 ; Divider ratio 1:524299 ;CONFIG WDTCPS = WDTCPS_15 ; Divider ratio 1:1048576 ;CONFIG WDTCPS = WDTCPS_16 ; Divider ratio 1:2097152 ;CONFIG WDTCPS = WDTCPS_17 ; Divider ratio 1:4194304 ;CONFIG WDTCPS = WDTCPS_18 ; Divider ratio 1:8388608 ;CONFIG WDTCPS = WDTCPS_19 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_20 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_21 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_22 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_23 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_24 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_25 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_26 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_27 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_28 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_29 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_30 ; Divider ratio 1:32 ;CONFIG WDTCPS = WDTCPS_31 ; Divider ratio 1:65536; software control of WDTPS ; WDTE: WDT operating mode CONFIG WDTE = OFF ; WDT Disabled, SWDTEN is ignored ;CONFIG WDTE = SWDTEN ; WDT enabled/disabled by SWDTEN bit in WDTCON0 ;CONFIG WDTE = NSLEEP ; WDT enabled while sleep=0, suspended when sleep=1; SWDTEN ignored ;CONFIG WDTE = ON ; WDT enabled regardless of sleep; SWDTEN ignored ; WDTCWS: WDT Window Select bits ;CONFIG WDTCWS = WDTCWS_0 ; window delay = 87.5 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_1 ; window delay = 75 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_2 ; window delay = 62.5 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_3 ; window delay = 50 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_4 ; window delay = 37.5 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_5 ; window delay = 25 percent of time; no software control; keyed access required ;CONFIG WDTCWS = WDTCWS_6 ; window always open (100%); no software control; keyed access required CONFIG WDTCWS = WDTCWS_7 ; window always open (100%); software control; keyed access not required ; WDTCCS: WDT input clock selector ;CONFIG WDTCCS = LFINTOSC ; WDT reference clock is the 31.0kHz LFINTOSC output ;CONFIG WDTCCS = HFINTOSC ; WDT reference clock is the 31.25 kHz HFINTOSC ;CONFIG WDTCCS = SOSC ; WDT reference clock is the 32kHz secondary oscillator CONFIG WDTCCS = SC ; WDT reference clock is controlled by software ; Config bits for register: CONFIG4 @ 0x800A ; BBSIZE: Boot Block Size Selection bits CONFIG BBSIZE = BB512 ; 512 words boot block size ;CONFIG BBSIZE = BB1K ; 1024 words boot block size ;CONFIG BBSIZE = BB2K ; 2048 words boot block size ;CONFIG BBSIZE = BB4K ; 4096 words boot block size ;CONFIG BBSIZE = BB8K ; 8192 words boot block size ;CONFIG BBSIZE = BB16K ; * half of user program memory ;CONFIG BBSIZE = BB32K ; * half of user program memory ;CONFIG BBSIZE = BB64K ; * half of user program memory ; BBEN: Boot Block Enable bit CONFIG BBEN = OFF ; Boot Block disabled ;CONFIG BBEN = ON ; Boot Block enabled ; SAFEN: SAF Enable bit CONFIG SAFEN = OFF ; SAF disabled ;CONFIG SAFEN = ON ; SAF enabled ; WRTAPP: Application Block Write Protection bit ;CONFIG WRTAPP = OFF ; Application Block not write protected CONFIG WRTAPP = ON ; Application Block write protected ; WRTB: Boot Block Write Protection bit ;CONFIG WRTB = OFF ; Boot Block not write protected CONFIG WRTB = ON ; Boot Block write protected ; WRTC: Configuration Register Write Protection bit ;CONFIG WRTC = OFF ; Configuration Register not write protected CONFIG WRTC = ON ; Configuration Register write protected ; WRTD: Data EEPROM write protection bit ;CONFIG WRTD = OFF ; Data EEPROM NOT write protected CONFIG WRTD = ON ; Data EEPROM write protected ; WRTSAF: Storage Area Flash Write Protection bit ;CONFIG WRTSAF = OFF ; SAF not write protected CONFIG WRTSAF = ON ; SAF write protected ; LVP: Low Voltage Programming Enable bit ;CONFIG LVP = ON ; Low Voltage programming enabled. MCLR/Vpp pin function is MCLR. CONFIG LVP = OFF ; High Voltage on MCLR/Vpp must be used for programming ; Config bits for register: CONFIG5 @ 0x800B ; CP: UserNVM Program memory code protection bit ;CONFIG CP = OFF ; UserNVM code protection disabled CONFIG CP = ON ; UserNVM code protection enabled ; Register: IDLOC0 @ 0x8000 ;CONFIG IDLOC0 = 0x55 ; Register: IDLOC1 @ 0x8001 ;CONFIG IDLOC1 = 0xAA ; Register: IDLOC2 @ 0x8002 ;CONFIG IDLOC2 = 0x55 ; Register: IDLOC3 @ 0x8003 ;CONFIG IDLOC3 = 0xAA ; Place includes after device configuration to avoid label clashes. ; An example of such is "SWDTEN", which is both a configuration option and ; the name of a device register. #include ; ********** Common RAM working registers ********** PSECT udata_shr ; Main AREG: DS 1 BREG: DS 1 CREG: DS 1 DREG: DS 1 LREG: DS 1 HREG: DS 1 TEMP0: DS 1 TEMP1: DS 1 ; ISR ISR_AREG: DS 1 ISR_BREG: DS 1 ISR_CREG: DS 1 ISR_DREG: DS 1 ISR_LREG: DS 1 ISR_HREG: DS 1 ISR_TEMP0: DS 1 ISR_TEMP1: DS 1 ; ********** General purpose RAM ********** ; Bank 0 (0x0020 to 0x006F) ;PSECT udata_bank0 ;MY_REGISTER: DS 1 ;MY_BLOCK: DS 8 ; Bank 1 (0x00A0 to 0x00EF) ;PSECT udata_bank1 ; Bank 2 (0x0120 to 0x016F) ;PSECT udata_bank2 ; Bank 3 (0x01A0 to 0x01EF) ; ... ; Bank 25 (0x0CA0 to 0x0CBF) ; ********** Labels / Constants ********** ; ********** Reset vector ********** PSECT RES_VECT, class = CODE, delta = 2 ; Don't forget to add "-PRES_VECT=0000" to custom linker options PROG_START: LJMP INIT ; ********** Interrupt vector ********** PSECT INT_VECT, class = CODE, delta = 2 ; Don't forget to add "-PINT_VECT=0004h" to custom linker options ; Select interrupt flag bank ISR_START: BANKSEL PIR0 ; Timer0 interrupt BTFSC TMR0IF BRA ISR_TMR0 ; Oops! Unhandled interrupt. RESET ; Clear interrupt flag ISR_TMR0: BCF TMR0IF ; Display multiplexer BANKSEL LATB BTFSC LATB7 BRA ISR_DISP_H ; Balance instruction cycles ISR_DISP_L: NOP ; Select input port bank BANKSEL PORTA ; Read bus low nibble into WREG CLRW BTFSC RB5 BSF WREG, 0 BTFSC RB4 BSF WREG, 1 BTFSC RC2 BSF WREG, 2 BTFSC RC1 BSF WREG, 3 ; Store bus value MOVWF ISR_TEMP0 ; Look up and store LATA IOR mask CALL ISR_IORMASKA MOVWF ISR_AREG ; Load bus value MOVF ISR_TEMP0, W ; Look up and store LATC IOR mask CALL ISR_IORMASKC MOVWF ISR_CREG ; Select output latch bank BANKSEL LATA ; High digit off BSF LATB7 ; AND mask segments off MOVLW 11001111B ANDWF LATA, F MOVLW 00000111B ANDWF LATC, F ; IOR mask segments on MOVF ISR_AREG, W IORWF LATA, F MOVF ISR_CREG, W IORWF LATC, F ; Low digit on BCF LATB6 ; Return from interrupt RETFIE ; Select input port bank ISR_DISP_H: BANKSEL PORTA ; Read bus high nibble into WREG CLRW BTFSC RC0 BSF WREG, 0 BTFSC RA2 BSF WREG, 1 BTFSC RA1 BSF WREG, 2 BTFSC RA0 BSF WREG, 3 ; Store bus value MOVWF ISR_TEMP0 ; Look up and store LATA IOR mask CALL ISR_IORMASKA MOVWF ISR_AREG ; Load bus value MOVF ISR_TEMP0, W ; Look up and store LATC IOR mask CALL ISR_IORMASKC MOVWF ISR_CREG ; Select output latch bank BANKSEL LATA ; Low digit off BSF LATB6 ; AND mask segments off MOVLW 11001111B ANDWF LATA, F MOVLW 00000111B ANDWF LATC, F ; IOR mask segments on MOVF ISR_AREG, W IORWF LATA, F MOVF ISR_CREG, W IORWF LATC, F ; High digit on BCF LATB7 ; Return from interrupt RETFIE ; Given a value in WREG low nibble, ; return the LATA IOR mask. ISR_IORMASKA: ANDLW 00001111B ; Mask out high nibble BRW RETLW 00110000B ; 0 RETLW 00010000B ; 1 RETLW 00110000B ; 2 RETLW 00110000B ; 3 RETLW 00010000B ; 4 RETLW 00100000B ; 5 RETLW 00100000B ; 6 RETLW 00110000B ; 7 RETLW 00110000B ; 8 RETLW 00110000B ; 9 RETLW 00110000B ; A RETLW 00000000B ; b RETLW 00000000B ; c RETLW 00010000B ; d RETLW 00100000B ; E RETLW 00100000B ; F ; Given a value in WREG low nibble, ; return the LATC IOR mask. ISR_IORMASKC: ANDLW 00001111B ; Mask out high nibble BRW RETLW 01111000B ; 0 RETLW 00100000B ; 1 RETLW 10011000B ; 2 RETLW 10110000B ; 3 RETLW 11100000B ; 4 RETLW 11110000B ; 5 RETLW 11111000B ; 6 RETLW 00100000B ; 7 RETLW 11111000B ; 8 RETLW 11100000B ; 9 RETLW 11101000B ; A RETLW 11111000B ; b RETLW 10011000B ; c RETLW 10111000B ; d RETLW 11011000B ; E RETLW 11001000B ; F ; ********** Main program ********** PSECT MAIN_PROG, class = CODE, delta = 2, reloc = 1 ; ***** Oscillator and clock config ***** INIT: BANKSEL OSCCON1 ; Explicitly enable HFINTOSC BSF HFOEN ; Set HFINTOSC frequency to 8MHz MOVLW 00000011B MOVWF OSCFRQ ; Wait until HFINTOSC is ready WAIT_HFOR: BTFSS HFOR BRA WAIT_HFOR ; Set clock source to HFINTOSC with divider: 1 MOVLW 01100000B MOVWF OSCCON1 ; Wait until OSCCON2 = OSCCON1 WAIT_ORDY: BTFSS ORDY BRA WAIT_ORDY ; ***** Disable unused peripherals ***** BANKSEL PMD0 BSF SYSCMD ; Disable Peripheral System Clock Network (Fosc) BSF FVRMD ; Disable Fixed Voltage Reference BSF NVMMD ; Disable Nonvolatile Memory Control BSF CLKRMD ; Disable Reference Clock Output BSF IOCMD ; Disable Interrupt-On-Change BSF TMR6MD ; Disable Timer6 BSF TMR5MD ; Disable Timer5 BSF TMR4MD ; Disable Timer4 BSF TMR3MD ; Disable Timer3 BSF TMR2MD ; Disable Timer2 BSF TMR1MD ; Disable Timer1 ;BSF TMR0MD ; Disable Timer0 BSF NCO1MD ; Disable Numerically Controlled Oscillator BSF DAC1MD ; Disable Digital-to-Analog Converter BSF ADCMD ; Disable Analog-to-Digital Converter BSF CMP2MD ; Disable Comparator 2 BSF CMP1MD ; Disable Comparator 1 BSF ZCDMD ; Disable Zero-Cross Detection BSF PWM7MD ; Disable Pulse Width Modulation 7 BSF PWM6MD ; Disable Pulse Width Modulation 6 BSF CCP4MD ; Disable Capture/Compare/PWM 4 BSF CCP3MD ; Disable Capture/Compare/PWM 3 BSF CCP2MD ; Disable Capture/Compare/PWM 2 BSF CCP1MD ; Disable Capture/Compare/PWM 1 BSF CWG2MD ; Disable Complementary Waveform Generator 2 BSF CWG1MD ; Disable Complementary Waveform Generator 1 BSF U1MD ; Disable EUSART 1 BSF MSSP2MD ; Disable Master Synchronous Serial Port 2 BSF MSSP1MD ; Disable Master Synchronous Serial Port 1 BSF SMT1MD ; Disable Signal Measurement Timer BSF CLC4MD ; Disable Configurable Logic Cell 4 BSF CLC3MD ; Disable Configurable Logic Cell 3 BSF CLC2MD ; Disable Configurable Logic Cell 2 BSF CLC1MD ; Disable Configurable Logic Cell 1 BSF DSM1MD ; Disable Data Signal Modulator 1 ; ***** Port config ***** ; Disable all analog inputs BANKSEL ANSELA CLRF ANSELA CLRF ANSELB CLRF ANSELC ; Enable weak pull-ups for bus and RA3 BANKSEL WPUA BSF WPUA3 ; MCLR/VPP/RA3 BSF WPUA0 ; Bus bit 0 BSF WPUA1 ; Bus bit 1 BSF WPUA2 ; Bus bit 2 BSF WPUC0 ; Bus bit 3 BSF WPUC1 ; Bus bit 4 BSF WPUC2 ; Bus bit 5 BSF WPUB4 ; Bus bit 6 BSF WPUB5 ; Bus bit 7 ; Drive all output latches low, except LATB6 and LATB7 BANKSEL LATA CLRF LATA MOVLW 11000000B MOVWF LATB CLRF LATC ; Enable outputs for segments and cathodes BANKSEL TRISA BCF TRISA5 ; Segment A BCF TRISA4 ; Segment B BCF TRISC5 ; Segment C BCF TRISC4 ; Segment D BCF TRISC3 ; Segment E BCF TRISC6 ; Segment F BCF TRISC7 ; Segment G BCF TRISB7 ; High digit cathode BCF TRISB6 ; Low digit cathode ; ***** Timer0 config ***** BANKSEL T0CON0 ; Clock source, sync/async and prescaler ; Async required for operation during sleep MOVLW 01110110B ; HFINTOSC, async, 1:64 prescaler (125KHz with 8MHz HFINTOSC) ;MOVLW 01110101B ; HFINTOSC, async, 1:32 prescaler (250KHz with 8MHz HFINTOSC) ;MOVLW 01110100B ; HFINTOSC, async, 1:16 prescaler (500KHz with 8MHz HFINTOSC) ;MOVLW 01110011B ; HFINTOSC, async, 1:8 prescaler (1000KHz with 8MHz HFINTOSC) ;MOVLW 01110010B ; HFINTOSC, async, 1:4 prescaler (2000KHz with 8MHz HFINTOSC) MOVWF T0CON1 ; Period counter MOVLW 124 ; 1KHz @ 125KHz, 2KHz @ 250KHz, 4KHz @ 500KHz ;MOVLW 249 ; 0.5KHz @ 125KHz, 1KHz @ 250KHz, 2KHz @ 500KHz MOVWF TMR0H ; Enable, mode and postscaler MOVLW 10000000B ; Enable TMR0, no output, 8 bit mode, no postscaler MOVWF T0CON0 ; ***** Interrupts ***** BANKSEL PIE0 BSF TMR0IE ; Enable Timer0 interrupts BSF PEIE ; Enable peripheral interrupts BSF GIE ; Enable global interrupts ; ***** Initialise registers ***** ;BANKSEL 0 ; ***** Main loop ***** MAIN_LOOP: BANKSEL 0 ; Sleep SLEEP ; Loop forever BRA MAIN_LOOP END PROG_START