; t1_test2.asm - 2nd test for 3niti alpha simu1 (updated 27 Nov 2009) ; TERNARY CLOCK: HOURS - 4 TRITS, MINUTES - 4 TRITS, SECONDS - 4 TRITS ; ; Part of NedoPC SDK (software development kit for simple devices) ; ; Copyright (C) 2009, Alexander A. Shabarshin ; ; 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 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . processor pic16f870 radix dec include "p16f870.inc" __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC include "shaos-p16.inc" ; PORTA - outputs to choose column (A0...A4) and direct LED (A5) ; PORTB - inputs for rows of switches (B0...B5) and I2C (B6,B7) ; PORTC - outputs for rows of LEDs (C0...C5) and RS232 (C6,C7) BSIZE EQU 27 ; -13...+13 INTCNT EQU 3 ; Specific vars 0x20...0x6F (banks 0 and 2) c_base EQU 32 ; ternary code segment 0x20...0x3A d_base EQU 59 ; ternary data segment 0x3B...0x55 (may be used as 2nd code segment) e_base EQU 86 ; end of segments (0x56) c_addr EQU 0x57 d_addr EQU 0x58 CA_m EQU 0x59 ; current code segment address (middle and high parts) CA_h EQU 0x5A DA_m EQU 0x5B ; current data segment address (middle and high parts) DA_h EQU 0x5C PC_l EQU 0x5D ; PC PC_m EQU 0x5E PC_h EQU 0x5F DPn_l EQU 0x60 ; DPn DPn_m EQU 0x61 DPn_h EQU 0x62 DPo_l EQU 0x63 ; DPo DPo_m EQU 0x64 DPo_h EQU 0x65 DPp_l EQU 0x66 ; DPp DPp_m EQU 0x67 DPp_h EQU 0x68 F_reg EQU 0x69 ; Register F (RSF,DPF,BCF) A_reg EQU 0x6A ; Register A B_reg EQU 0x6B ; Register B C_reg EQU 0x6C ; ??? D_reg EQU 0x6D ; Data to display on LEDs 10,11,12 ; Specific vars 0xA0...0xBF (banks 1 and 3) ; Global vars 0x70...0x7F (all banks) swit0 EQU 0x70 ; copy of switch row 0 swit1 EQU 0x71 ; copy of switch row 1 swit2 EQU 0x72 ; copy of switch row 2 swit3 EQU 0x73 ; copy of switch row 3 swit4 EQU 0x74 ; copy of switch row 4 cnt1 EQU 0x75 cnt2 EQU 0x76 tmp0 EQU 0x77 tmp1 EQU 0x78 tmp2 EQU 0x79 tmp3 EQU 0x7A mask EQU 0x7B count EQU 0x7C savedT EQU 0x7D ; saved TMP savedW EQU 0x7E ; saved W savedS EQU 0x7F ; saved STATUS ; Reset vector ORG 00h goto Start ; Interrupt vector ORG 04h movwf savedW _movrr STATUS,savedS _bank0 btfss INTCON,T0IF goto intend ; _movrr tmp1,savedT decfsz tmp0,f goto intend1 _movlr INTCNT,tmp0 btfss C_reg,5 goto ii_1 bcf C_reg,5 bsf C_reg,4 goto ii_2 ii_1: btfss C_reg,4 bsf C_reg,5 bcf C_reg,4 goto intend1 ii_2: btfss C_reg,3 goto ii_3 bcf C_reg,3 bsf C_reg,2 goto ii_4 ii_3: btfss C_reg,2 bsf C_reg,3 bcf C_reg,2 goto intend1 ii_4: btfss C_reg,1 goto ii_5 bcf C_reg,1 bsf C_reg,0 goto ii_6 ii_5: btfss C_reg,0 bsf C_reg,1 bcf C_reg,0 goto intend1 ii_6: btfss D_reg,5 goto ii1 bcf D_reg,5 bsf D_reg,4 goto ii2 ii1: btfss D_reg,4 bsf D_reg,5 bcf D_reg,4 goto iiM ii2: btfss D_reg,3 goto ii3 bcf D_reg,3 bsf D_reg,2 goto ii4 ii3: btfss D_reg,2 bsf D_reg,3 bcf D_reg,2 goto iiM ii4: btfss D_reg,1 goto ii5 bcf D_reg,1 bsf D_reg,0 goto ii6 ii5: btfss D_reg,0 bsf D_reg,1 bcf D_reg,0 goto iiM ii6: btfss PC_l,5 goto ii7 bcf PC_l,5 bsf PC_l,4 goto iiM ii7: btfss PC_l,4 bsf PC_l,5 bcf PC_l,4 iiM: movf D_reg,w sublw b'00001000' btfss STATUS,Z goto intend1 btfsc PC_l,4 goto intend1 btfss PC_l,5 goto intend1 movlw b'00000100' movwf D_reg bsf PC_l,4 bcf PC_l,5 btfss PC_l,3 goto ii8 bcf PC_l,3 bsf PC_l,2 goto ii9 ii8: btfss PC_l,2 bsf PC_l,3 bcf PC_l,2 goto iiH ii9: btfss PC_l,1 goto ii10 bcf PC_l,1 bsf PC_l,0 goto ii11 ii10: btfss PC_l,0 bsf PC_l,1 bcf PC_l,0 goto iiH ii11: btfss PC_m,5 goto ii12 bcf PC_m,5 bsf PC_m,4 goto ii13 ii12: btfss PC_m,4 bsf PC_m,5 bcf PC_m,4 goto iiH ii13: btfss PC_m,3 goto ii14 bcf PC_m,3 bsf PC_m,2 goto iiH ii14: btfss PC_m,2 bsf PC_m,3 bcf PC_m,2 iiH: movf PC_l,w andlw b'00001111' sublw b'00000010' btfss STATUS,Z goto intend1 movf PC_m,w andlw b'00111100' sublw b'00001000' btfss STATUS,Z goto intend1 bsf PC_l,0 bcf PC_l,1 bsf PC_m,2 bcf PC_m,3 btfss PC_m,1 goto ii15 bcf PC_m,1 bsf PC_m,0 goto ii16 ii15: btfss PC_m,0 bsf PC_m,1 bcf PC_m,0 goto iiD ii16: btfss PC_h,5 goto ii17 bcf PC_h,5 bsf PC_h,4 goto ii18 ii17: btfss PC_h,4 bsf PC_h,5 bcf PC_h,4 goto iiD ii18: btfss PC_h,3 goto ii19 bcf PC_h,3 bsf PC_h,2 goto ii20 ii19: btfss PC_h,2 bsf PC_h,3 bcf PC_h,2 goto iiM ii20: btfss PC_h,1 goto ii21 bcf PC_h,1 bsf PC_h,0 goto iiD ii21: btfss PC_h,0 bsf PC_h,1 bcf PC_h,0 iiD: btfsc PC_m,0 goto intend1 btfsc PC_m,1 goto intend1 movf PC_h,w sublw b'00100010' btfss STATUS,Z goto intend1 clrf PC_h intend1: ; _movrr savedT,tmp1 _movlr 15,TMR0 bcf INTCON,T0IF intend: _movrr savedS,STATUS movf savedW,w retfie Start: ; Configure all I/O pins as digital _bank1 _movlr 0x06,ADCON1 ; Set direction of ports _bank1 _movlr b'00000000',TRISA _movlr b'00111111',TRISB _movlr b'00000000',TRISC ; Initialize output ports _bank0 _movlr b'11111111',PORTA _movlr b'11111111',PORTB _movlr b'11111111',PORTC ; Setup interrupts _bank1 clrf INTCON ; disable all interrupts and clear all flags bcf OPTION_REG,NOT_RBPU ; enable pull-ups bsf OPTION_REG,INTEDG ; interrupt on rising edge bcf OPTION_REG,T0CS ; enable Timer0 in timer mode bcf OPTION_REG,PSA ; assign prescaler to the Timer0 (1:256) bsf INTCON,T0IE ; enable Timer0 interrupt bcf INTCON,INTE ; disable RB0 port change interrupt bsf INTCON,GIE ; enable interrupts ; Clear watch dog _bank0 clrwdt goto Main ; Ternary inversion (negation) of W (used tmp1,tmp2) tri_neg: ; 14 cycles with call movwf tmp1 andlw b'01010101' movwf tmp2 movf tmp1,W andlw b'10101010' movwf tmp1 bcf STATUS,C rlf tmp2,F rrf tmp1,W iorwf tmp2,W return ; P.S. it also works with inverted binary representation ; Ternary increment of W (used tmp1), C if overflow tri_inc: bcf STATUS,C movwf tmp1 btfss tmp1,5 goto tri_i4 bcf tmp1,5 bsf tmp1,4 goto tri_i3 tri_i4: btfss tmp1,4 bsf tmp1,5 bcf tmp1,4 movf tmp1,w return tri_i3: btfss tmp1,3 goto tri_i2 bcf tmp1,3 bsf tmp1,2 goto tri_i1 tri_i2: btfss tmp1,2 bsf tmp1,3 bcf tmp1,2 movf tmp1,w return tri_i1: btfss tmp1,1 goto tri_i0 bcf tmp1,1 bsf tmp1,0 goto tri_ic tri_i0: btfss tmp1,0 bsf tmp1,1 bcf tmp1,0 movf tmp1,w return tri_ic: movf tmp1,w bsf STATUS,C return Main: ; Initialize registers movlw b'11111111' movwf swit0 movwf swit1 movwf swit2 movwf swit3 movwf swit4 clrf PC_h clrf PC_m clrf PC_l clrf A_reg clrf B_reg clrf C_reg clrf D_reg clrf F_reg _movlr INTCNT,tmp0 bsf PORTA,5 ; fire LED ; Test program loop: movlw b'11111110' movwf mask movlw 5 movwf count movlw swit0 movwf FSR loop0: movf mask,w movwf PORTA _delay1 10,cnt1 movf PORTB,w call tri_neg movwf INDF incf FSR,f btfsc mask,0 goto loop1 comf PC_h,w goto loop6 loop1: btfsc mask,1 goto loop2 comf PC_m,w goto loop6 loop2: btfsc mask,2 goto loop3 comf PC_l,w goto loop6 loop3: btfsc mask,3 goto loop4 comf D_reg,w goto loop6 loop4: comf C_reg,w loop6: movwf PORTC _delay1 0,cnt1 bsf STATUS,C rlf mask,f decfsz count,f goto loop0 movf mask,w movwf PORTA btfsc swit4,1 goto loop comf swit0,w movwf PC_h comf swit1,w movwf PC_m comf swit2,w movwf PC_l comf swit3,w movwf D_reg goto loop END