Code: Select all
; 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 <ashabarshin@gmail.com>
;
; 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 <http://www.gnu.org/licenses/>.
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
после включения надо переключателями выставить текущее время и сдвинуть переключатель W/R вверх и сразу вниз - после этого часы будут показывать текущее время, убегая вперёд на 1 секунду каждые 31 минуту