/**********************************************************
New Seismometer Nov.24,2019
(c)2019 Akira Tominaga, All rights reserved.
**********************************************************/
#include "Wire.h"
#include "SPI.h"
// SPI MOSI:11 MISO:12 SCK:13
int cS; // chip-select pin (variable)
#define cS0 10 // chip-select 0 for SRAM0
#define cS1 9 // chip-select 1 for SRAM1
#define cS2 8 // chip-select 2 for SRAM2
#define cSmin 8 // for chip-select shifting
#define cSmax 10 // for chip-select shifting
int LED; // LED to show currently used SRAM
#define LED0 7 // SRAM0 used now - Red
#define LED1 6 // SRAM1 used now - Green
#define LED2 5 // SRAM2 used now - Blue
#define LEDmin 5 // for LED shifting
#define LEDmax 7 // for LED shifting
#define Sw 3 // Tact switch at D3
// (to be replaced by PIC signal(L) generated by IR sig)
#define Timing 16 // Timing signal(L) at A2=D16
#define testPin 2 // Test signal pin D2
// Accelerometer LSM6DS3
#define Accel 0x6B // Accelorometer addr 0x6B (PIC=D6)
int16_t Galx10[3] = {0, 0, 0}; // measured Gal x 10
int32_t usualGalx10[3]; // usual Galx10 for calculation
byte Qflags = B00000000; // status to record to SRAM
#define nowQ B10000000 // currently quaking
#define wasQ B01000000 // there was a quake
float qVal = 0; // quake value
int32_t magQ = 0; // total/avg Q to check quake
#define magQth 20 // quake threshold (10 in real env ?)
int16_t magQctr = 0; // counter to get average magQ
#define magQcmax 50 // magQ counter max value (1 sec)
int16_t qEctr = 0; // Q end counter to judge end of Q
#define qEcmax 250 // no quake for continuous 5 secs
#define serSpeed 9600
#define srCM 0x01 // Mode command of SRAM
#define srCMseq 0x40 // Mode=sequential
#define srCW 0x02 // Write command of SRAM
#define srCR 0x03 // Read command of SRAM
uint32_t srAdr = 0; // address in SRAM
#define srAdrMax 131071
/* One rec consists of 4x16bit-int [fileID+Qflags,X,Y,Z]
[rec at Time of quakeEnd to be replaced with the Time
of which format is ["FFFF",YY*12+MM,DD*24+hh,mm*60+ss]
*/
int16_t Rec[4]; // integer array for recording
int16_t fileID = 0; // file ID(repeat 0-250, 16384 recs/file)
#define fileIDmax 250 // repeat from 0 to 250
// for RTC (real time clock)
byte vR[8]; // values in RTC registers
int vI[8] = { 0, 0, 0, 0, 0, 0, 0, 0}; // integers for RTC data
#define RTC_addr 0x68 // I2C address
#define mds 1 // ss
#define mdm 2 // mm
#define mdh 3 // hh
#define mdW 4 // WW=Day of Week
#define mdD 5 // DD
#define mdM 6 // MM
#define mdY 7 // YY
;U1910-Xtal-Timer-12F1822-V00-01.asm As of Oct. 30, 2019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Xtal Timer with PIC12F1822 Version 00-01 ;
; All rights reserved. 2018(C) Akira Tominaga ;
; Function ;
; ;
; Input/Output for 16F1823 ;
; RA0 LEDr output (on =H) ;
; RA1 NC ;
; RA2 Timing Signal output Tmg(on =L) ;
; RA4 Osc2 for Xtal HS 16MHz ;
; RA5 Osc1 for Xtal HS 16MHz ;
; Remarks ;
; 1. Clock = HF Xtal ( 16.000MHz) ;
; Hence 1 step = 0.25 micro seconds ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
page
list p=12F1822 ; list directive to define processor
#include ;P12F1822 processor specific variable definitions
__CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macro definitions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Device dependent Macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DEVset macro
BANKSEL OSCCON ; Bank=1
movlw B'00000000' ; HS Xtal oscillator
movwf OSCCON
;
; BANKSEL INTCON ; Interrupt Con (in all banks hence comment)
clrf INTCON ; Disable all interrupts
;
; PORTA initialization
BANKSEL PORTA ; Bank=0
clrf PORTA
BANKSEL LATA ; Bank=2
clrf LATA
BANKSEL ANSELA ; Bank=3
movlw B'00000000' ; No use of Analog input
movwf ANSELA
BANKSEL TRISA ; Bank=1
movlw B'11111010' ; RA0 and 2 are output
movwf TRISA
;
BANKSEL ADCON0 ; Bank=1
clrf ADCON0 ; No use of ADC
;
BANKSEL OPTION_REG ; Bank=1
bcf OPTION_REG,7 ; Enable weak pull-up
BANKSEL WPUA ; Bank=4
movlw B'00001000' ; Weak Pull-up for RA3
movwf WPUA ;
;
clrf BSR ; Bank=0
endm
;
OUTini macro ; L for LEDs, and H for Signal
nop ; Timing for PORTA
movlw B'11001100' ; Set space (H) to RA2
movwf PORTA
goto $+1 ; Timing for PORTA
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I/O macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For general purpose ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDon macro
goto $+1
bsf PORTA,LED
goto $+1
endm
;
LEDoff macro
goto $+1
bcf PORTA,LED
goto $+1
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Constant time consuming ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic macro ;Consume 1 μS only
goto $+1
goto $+1
endm
;
Mic2 macro mic2p ;Consume 2 μS x n
movlw mic2p
call Mic2r
endm
;
Mic2p5 macro mic25p ; Consume 2.5μS x n
movlw mic25p
call Mic25r
endm
;
Mic5 macro mic5p ; Consume 5μS x n
movlw mic5p
call Mic25r
movlw mic5p
call Mic25r
endm
;
Mic50 macro mic50p ; Consume 50μS x n
movlw mic50p
call Mic50r
endm
;
Milli macro millip ; Consume mS x n
movlw millip
call Millir
endm
;
Mil100 macro mil100p ; Consume 100 mS x n
movlw mil100p
call Mil100r
endm
;
Secs macro secsp ; Consume Second x n
movlw secsp
call Secsr
endm
;
Mins macro minsp ; Consume Minute x n
movlw minsp
call Minsr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Debug and Abend macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Udebug macro Addr
movf Addr,W
call Udbgr
endm
;
Ustop macro ; Stop until Sw2 on (=L)
call Udstopr ;
endm
;
Trigger macro ; DSO external trigger
goto $+1
bsf PORTtrg,Trig
Mic2
bcf PORTtrg,Trig
goto $+1
endm
;
Uabend macro abn ; User Abnormal-end number
movlw abn
goto Uabendr
endm
;
Ublink macro bno ; Blink LED for specified times
movlw bno
call Ublinkr
endm
;
Ucp macro CPNo ; Check point literal chr to display to LCD
movlw CPNo
movwf Ucpc
Udebug Ucpc
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files and Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cblock H'20' ; available from H'20' to H'6F' (80 bytes)
;
; For application support
Flags ; Flag byte
;
; Areas for time consuming subroutines
; Do not change the sequences from Mic5c to Minsc
; as these areas are co-used with calculation parameters
Mic25c
Mic50c
Millic
Mil100c
Secsc
Minsc
;
; Areas for debugging routine
DmpA ; Display byte area
Dmp8C ; Bit counter for loop (Initial Dmp8V =8)
BlinkC ; Counter for blinking (set for Debugb or Abendb)
Abendn ; Abend number
Ucpc ; User Check point chr to trace
;
endc
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For PORTA ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LED equ 0 ; LED
Tmg equ 2 ; Timing signal(L)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Values ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Flags Byte ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDsv equ 0 ; LED save bit for debug
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For Debug ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dmp8V equ D'8' ; Debug display bit counter initial value
Debugb equ D'8' ; number of blinkings to show Debugging
Abendb equ D'30' ; number of blinkings to notify Abend
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Initializing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0
goto Startp ; Go to start entry
org 4 ; This is Interrupt entry
retfie ;
;
Startp DEVset ; Define ports
OUTini ; L for LED(0), and H for Clk and Dio
clrf Flags ; Clear Flags byte
;
LEDon ; Indicate I am awake
Mil100 1 ; ***
LEDoff
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Main program loop = precise 20mS/loop required ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mainp bcf PORTA,Tmg ; Tmg on (L)
Mic5 D'10' ; On for 50 micro seconds
bsf PORTA,Tmg ; Yes, clear Tmg signal
;
goto $+1 ; +0.5microS = 51microS up to here
;
; Requires 20mS-0.052mS = 19.948mS here
Milli D'19' ; / 19.0mS
Mic50 D'18' ; / 19.9mS
Mic5 D'9' ; / 19.945mS
Mic2 1 ; / 19.947mS
Mic ; / 19.948mS Total 19.999 mS
;
; Last segment consumes 0.001mS ;
goto $+1 ; consume 1microS hereafter
goto Mainp ; and loop
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Timing subrooutines for general purposes;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.0 micro S x n (Mic2) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic2r movwf Mic25c ; + Wset + call = 1 micro sec
;
Mic2l decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic2li ; else go out (2nd time 1.75 mic sec)
return
;
Mic2li goto $+1 ; (2nd time 2.25 mic sec)
nop ; (2nd time 2.5 mic sec)
goto Mic2l ; go back (2nd time 3 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.5 micro S x n (Mic2p5) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic25r movwf Mic25c ; + Wset + call = 1 micro sec
nop ; 1.25 micro sec
;
Mic25l nop ; 1.5 micro sec (2nd time 4 mic sec)
decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic25li ; else go out (2nd time 2.25 mic sec)
return
;
Mic25li Mic ; (2nd time 3.25 mic sec)
goto Mic25l ; go back (2nd time 3.75 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 50 Microseconds x n Mic50 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Mic50r movwf Mic50c ; set how many 50 microsec (1 micro sec to here)
nop ; 1.25 micro sec up to here
;
Mic50l Mic2p5 D'19' ; + 47.5 = 48.75 mic sec (2nd time 98.75 mic sec)
nop ; + 0.25 = 49 micro sec (2nd time 99 mic sec)
;
decfsz Mic50c,F ; If exhausted then 1 mic S hereafter
goto Mic50li ; else go out (2nd time 49.75 mic sec)
return
;
;
Mic50li Mic ; (2nd time 50.75 mic sec)
goto Mic50l ; go back (2nd time 51.25 mic sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Milliseconds x n (Milli) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Millir movwf Millic ; set how many 1 mil sec (1 mic S up to here)
nop ; 1.25 micro sec
;
Millil Mic50 D'19' ; + 50 mic x 19 = 951.25 mic S (2nd, 1951.25)
Mic2p5 D'19' ; + 47.5 mic = 998.75 micro S (2nd, 1998.75)
nop ; +0.25 mic = 999 micro sec (2nd, 1999)
;
decfsz Millic,F ; If exhausted then 1 micro sec hereafter
goto Millili ; else go out (2nd, 999.75 mic S)
return
;
Millili Mic ; (2nd time 1000.75 mic S)
goto Millil ; go back (2nd time 1001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 100 Milliseconds x n (Mil100);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mil100r movwf Mil100c ;set how many 100 ms(1 micr sec up to here)
nop ; 1.25 micro sec
;
Milhl Milli D'99' ;+1ms x 99 = 99001.25 micS (2nd,199001.25mic)
Mic50 D'19' ; + 950 mic = 99951.25 micS(2nd.199951.25mic)
Mic2p5 D'19' ; + 47.5 mic = 99998.75micS(2nd,199998.75mic)
nop ; + 0.25 mic = 99999 mic S (2nd,199999 micS)
;
decfsz Mil100c,F ; If exhausted then 1 micro sec hereafter
goto Milhli ; else go out (2nd time, 99999.75 mic S)
return
;
Milhli Mic ; (2nd time, 100000.75 mic S)
goto Milhl ; (2nd time, 100001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Seconds x n (Secs) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Secsr movwf Secsc ; set how many sec ( 1 mic sec up to here)
nop ; 1.25 micro sec
;
Secsl Mil100 D'9' ;
Milli D'99' ; + 999 milli sec = 999001.25 micro sec
;
Mic50 D'19' ; + 950 mic = 999951.25 micro sec
Mic2p5 D'19' ; + 47.5 mic = 999998.75 micro sec
nop ; + 0.25 mic = 999999 micro sec
;
decfsz Secsc,F ; If exhausted then 1 micro sec hereafter
goto Secsli ; else, go out
return
;
Secsli Mic
goto Secsl ; (Second time, Sec + 1.25 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Minutes x n (Mins) ;
; Overhead ignored, that is only ;
; 751.25 Mic S even when 100 Min ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Minsr movwf Minsc ;set how many minutes from parameter
;
Minsl Secs D'60' ; 1 Seconds x 60
decfsz Minsc,F
goto Minsl
return
;
space
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User debug subroutine ;
; Show bit 7 to 0 ;
; of specified area ;
; by Udebug macro ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Udbgr clrf BSR ; Set Bank=0
movwf DmpA ; move data to Dmpa
;
btfss PORTA,LED ; Check if LED=on (on=High)
goto UdbLoff ; if LED=off(Low), skip saving process
bsf Flags,LEDsv ; Save LEDon status
LEDoff ; and off LED
Mil100 D'5' ; wait for 0.5 sec5 in case LED has been on
;
UdbLoff movlw Dmp8V ; set counter 8
movwf Dmp8C ; to Dmp8C
;
Udblp Ublink Debugb ; Blink for Debugging = 8 times
btfsc DmpA,7 ; check top bit 7
goto UdbOn ; if on then to UdbOn
goto UdbOff ; if off then to UdbOff
;
UdbOn LEDon
Mil100 D'5' ;
goto Udbeck
;
UdbOff LEDoff
Mil100 D'5' ;
; goto Udbeck
;
Udbeck decfsz Dmp8C,F
goto Udbnext
goto Udbend
;
Udbnext rlf DmpA,F
goto Udblp
;
Udbend Ublink Debugb ; end blinking and
Mil100 D'30' ; blank for 3 seconds to write down
;
btfss Flags,LEDsv ; Check if LED was on
goto Udbret ; no, goto return
LEDon ; if it was on, then on again
bcf Flags,LEDsv ; Clear LED save flag
;
Udbret return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Blinking to show debug or abend ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ublinkr movwf BlinkC
Ublinkl LEDon ; LED on
Milli D'10' ; for 10ms
LEDoff ; LED off
Milli D'50' ; for 50ms
;
decfsz BlinkC,F
goto Ublinkl
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Abend routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Uabendr clrf BSR
movwf Abendn ; Set Uabend number
;
Ublink Abendb ; Blinking 30 times
Udebug Abendn ; Show Abend number
goto $
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#define Timing 16 // Timing signal(L) at A2=D16
#define testSig B00000100 // test signal at D2 pin
// Wait for 20mS time-trigger (LOW for 50 microseconds) PORTD = PORTD ^ testSig; // Reverse test signal
while (digitalRead(Timing) == HIGH) {}
PORTD = PORTD ^ testSig; // Reverse test signal
// time to wait for trigger measured at D2 Test pin
さらに短い単位で測定をすることも十分可能ですが、そうするとSRAM1つの記録時間が減ります。地震は最長せいぜい4分のようですが、このしかけですとSRAM1つに5分20秒以上記録できます。とはいえ地震計の記録としては50Hzのサンプリングで大丈夫なので、Simple is the best、これで進めることにします。地震のこない時は1つのSRAMにラップラウンドで書き続け、地震があればその記録と時刻表記は1つのSRAM内に収まり、次のSRAMに書き始めるようにします。
;U191006-RTC-TM1637-V00.asm As of Oct. 06, 2019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; 8pin PIC RTC Reader/Writer with TM1637 display V00 ;
; (C)2015-2019 Akira Tominaga, All rights reserved. ;
; Major revisions ;
; V00 Original version Oct. 6, 2019 ;
; ;
; Function ;
; 1.Show time, on TM1637 4 digit display ;
; 2.Re-write RTC contents using three switches ;
; Set-switch: enter into update-mode ;
; Mode-switch: change calendar/time unit ;
; Time-switch: change value of the unit within its range ;
; Set-switch: reflect update and restart RTC ;
; Long push of Mode-sw: exit update-mode without updating RTC ;
; ;
; Input/output ;
; RA0 Mode-switch (swMode) input pulled-up ;
; RA1 Time-switch (swTime) input pulled-up ;
; Used as LED or DSO trigger when debugging ;
; RA2 DIO for TM1637 outuput usually and input occasionally ;
; RA3 Set-switch (swSet) input pulled-up ;
; RA4 SDA for I2C-RTC output usually and input occasionally ;
; RA5 SCL for I2C-RTC output and CLK for TM1637 output ;
; ;
; Remarks ;
; 1. Clock = HFINTOSC ( 16MHz) ;
; Hence 1 step = 0.25 micro seconds ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
list p=12F1822 ; list directive to define processor
#include ; <p12F1822.inc> specific variables
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
; page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macro definitions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Device dependent Macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DEVset macro
BANKSEL OSCCON ; Bank=1
movlw B'01111010' ; 16MHz and internal oscillator
movwf OSCCON
;
; BANKSEL INTCON ; Interrupt Con (in all banks hence comment)
clrf INTCON ; Disable all interrupts
;
; PORTA initialization
BANKSEL PORTA ; Bank=0
clrf PORTA
; BANKSEL LATA ; Bank=2
; clrf LATA
BANKSEL ANSELA ; Bank=3
clrf ANSELA ; No use of ADC
BANKSEL ADCON0 ; Bank=1
clrf ADCON0 ; No use of ADC
;
BANKSEL TRISA ; Bank=1
movlw B'11001011' ; RA2,4 and 5 are output
movwf TRISA
;
BANKSEL OPTION_REG ; Bank=1
bcf OPTION_REG,7 ; Enable weak pull-up
BANKSEL WPUA ; Bank=4
movlw B'00001011' ; Weak Pull-up for RA 0,1,and 3
movwf WPUA ;
;
clrf BSR ; Bank=0
InitP ; Initialize ports
endm
;
InitP macro ; Initialize ports
movlw B'11111111' ; All inputs pulled-up and outputs H
movwf PORTA
endm
;
; for I2C-Master protocol
; Sending data to I2C slave
I2Csnd macro slave,dataa,datalen
movlw slave
movwf I2Cadr
movlw dataa
movwf FSR0L
movlw datalen
movwf DataLen
call I2Csndr
endm
;
; Receiving data from I2C slave
I2Crcv macro slave,dataa,datalen
movlw slave
movwf I2Cadr
movlw dataa
movwf FSR0L
movlw datalen
movwf DataLen
call I2Crcvr
endm
;
; I2C start signal
I2Cstat macro
call I2Cstar
endm
;
; I2C stop signal
I2Cstop macro
call I2Cstpr
endm
;
; For TM16xx-Master protocol
; Sending Literal to TM16xx
TMsendL macro tslit ; Send a literal to TM1637
movlw tslit
call TMsndLr
endm
;
; Sending a Byte to TM16xx
TMsendB macro tsbyte ; Send a Byte specified, to TM1637
movf tsbyte,W
movwf Sbyte
call TMsndBr
endm
;
; TM16xx start signal
TMstart macro ; Start TM16xx lines
call TMstrtr
endm
;
; TM16xx stop signal
TMstop macro ; Stop TM16xx lines
call TMstopr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; API and I/O macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;for TM1637 application interfaces
;display 4 literal characters directly to TM1637
dsp4chr macro d1000,d100,d10,d1
movlw d1000
movwf Dig1000
movlw d100
movwf Dig100
movlw d10
movwf Dig10
movlw d1
movwf Dig1
call TMdspr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Time cosuming macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic macro ;Consume 1 μS only
goto $+1
goto $+1
endm
;
Mic2 macro mic2p ;Consume 2 μS x n
movlw mic2p
call Mic2r
endm
;
Mic2p5 macro mic25p ; Consume 2.5μS x n
movlw mic25p
call Mic25r
endm
;
Mic5 macro mic5p ; Consume 5μS x n
movlw mic5p
call Mic25r
movlw mic5p
call Mic25r
endm
;
Mic50 macro mic50p ; Consume 50μS x n
movlw mic50p
call Mic50r
endm
;
Milli macro millip ; Consume mS x n
movlw millip
call Millir
endm
;
Mil100 macro mil100p ; Consume 100 mS x n
movlw mil100p
call Mil100r
endm
;
Secs macro secsp ; Consume Second x n
movlw secsp
call Secsr
endm
;
Mins macro minsp ; Consume Minute x n
movlw minsp
call Minsr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Debug and Abend macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDon macro ; LED on macro for debugging
bcf Flags,LEDpH ; Clear LEDpin flags beforehand,
bcf Flags,LEDpIn ; as timing before PORT accessed
btfsc PORTdbg,LED ; Has LED been H before debug?
bsf Flags,LEDpH ; Yes, set LEDpH flag
BANKSEL TRISdbg ; Select TRIS bank
btfss TRISdbg,LED ; Has LED pin been input?
goto $+4 ; No, skip the next 3 steps
clrf BSR ; Point Bank0
bsf Flags,LEDpIn ; Show LED pin was input
BANKSEL TRISdbg ; Select Tris bank again
;
bcf TRISdbg,LED ; Set LED output mode, in any case
clrf BSR ; Point Bank 0
bsf PORTdbg,LED ; LED on
goto $+1 ; Timing after PORTdbg changed
endm
;
LEDoff macro ; LED off macro for debugging
goto $+1 ; Avoid PORT-update timing problem
bcf PORTdbg,LED ; LED off
btfss Flags,LEDpIn ; Was LEDpin input before debug?
goto $+7 ; No, skip the following 6 steps
;
BANKSEL TRISdbg ; Select TRISdbg bank
bsf TRISdbg,LED ; Set LED pin input again
BANKSEL WPUdbg ; Select WPUdbg, assuming Pulled-up
bsf WPUdbg,LED ; Weak Pull-up for input pin
clrf BSR ; Point Bank 0
goto $+3 ; skip the next 2 steps
;
btfsc Flags,LEDpH ; Was LEDpin High
bsf PORTdbg,LED ; Yes, set LED pin High
bcf Flags,LEDpH ; Clear LED flags,
bcf Flags,LEDpIn ; as timing after PORTdbg changed
endm
;
Trigger macro ; Trigger for DSO
bcf Flags,TrigpH ; ClearTrigger flags beforehand
bcf Flags,TrigpIn ; for timing before PORT changed
btfsc PORTdbg,Trig ; Has Trig pin been H before debug?
bsf Flags,TrigpH ; Yes, set TigpH flag
BANKSEL TRISdbg ; Select TRIS bank
btfss TRISdbg,Trig ; Has Trig pin been input?
goto $+4 ; No, skip the following 3 steps
clrf BSR ; Yes, point Bank 0,
bsf Flags,TrigpIn ; and show Trig pin was input,
BANKSEL TRISdbg ; select TRISdbg bank again
;
bcf TRISdbg,Trig ; Set Trig pin output, in any case
clrf BSR ; Point Bank 0
btfss Flags,TrigpH ; Was Trigger pin H?
goto $+3 ; No, goto slope-rising trigger
bcf PORTdbg,Trig ; Yes, set slope-falling trigger
goto $+2 ; and skip next line
bsf PORTdbg,Trig ; Slope-rising trigger
;
Mic2 2 ; Trigger for 4 micro seconds
movlw TrigpV ; Set trigger pin value to W
xorwf PORTdbg,F ; Stop trigger (H/L to L/H)
;
btfss Flags,TrigpIn ; Was Trig pin input before debug?
goto $+10 ; No, skip the following 9 steps
;
BANKSEL TRISdbg ; Select TRISdbg bank
bsf TRISdbg,Trig ; Set Trig-pin input
clrf BSR ; Select Bank 0
btfsc Flags,TrigpH ; Was Trigger pin L?
goto $+4 ; Yes, skip the followings
BANKSEL WPUdbg ; No,Bank select for WPUdbg
bsf WPUdbg,Trig ; Weak Pull-up for input pin
clrf BSR ; Re-select Bank 0
goto $+7 ; skip next 6 steps for output
;
btfss Flags,TrigpH ; Was Trigger pin H?
goto $+3 ; No, skip next 2 steps
bsf PORTdbg,Trig ; Yes, Set trig pin H
goto $+2 ; and skip next line
bcf PORTdbg,Trig ; Set trig pin L
;
bcf Flags,TrigpH ; Clear flags for trigger
bcf Flags,TrigpIn ; as timing after PORTdbg changed
endm
;
Udebug macro Addr
movf Addr,W
call Udbgr
endm
;
Uabend macro abn ; User Abnormal-end number
movlw abn
goto Uabendr
endm
;
Ublink macro bno ; Blink LED for specified times
movlw bno
call Ublinkr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Logic macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Comparison macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare A w/ B and branch to Smaller, Equal, or Larger(next statm't line)
CabSEL macro Aadr,Badr,Smladr,Eqladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ B and branch to Smaller or Others (Equal or Larger)
CabSO macro Aadr,Badr,Smladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ B and branch to Equal, or Other(next statm't line)
CabEO macro Aadr,Badr,Eqladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfsc STATUS,Z ; A=B?
goto Eqladr ; If A=B goto Eqljmp
; ; else next (here)
endm
;
; Compare A w/ literal and branch to Smaller, Equal, or Larger(next statm't)
CalSEL macro Aadr,Blit,Smladr,Eqladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ literal and branch to Smaller, or Others (Equal or Larger)
CalSO macro Aadr,Blit,Smladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ literal and branch to Equal, or Others
CalEO macro Aadr,Blit,Eqladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; else next (here)
endm
;
; Compare A w/ literal and branch to Large, or Others
CalLO macro Aadr,Blit,Ladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto $+3 ; If A<B goto Others
btfss STATUS,Z ; A=B? Yes skip next
goto Ladr ; If A>B goto Laddr
; ; If A≦B then next (here)
endm
;
; Compare A with Literal and branch to Un-equal, or Others
CalUO macro Aadr,Blit,Uneqladr
movlw Blit ; W=B literal
subwf Aadr,W ; W=A-B
btfss STATUS,Z ; A=B?
goto Uneqladr ; No, goto unequal
; ; If yes then next
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files and Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cblock H'20'
;
; For Application support
ModeN ; Mode to point BCD mem addr of RTC
T7Chr ; 7 segment character to show ModeN
RvMax ; Max number of RTC data in ModeN
RvMin ; Minimum num of RTC data in ModeN
Byteh ; Work area as high byte of a word
Bytel ; Work area as low byte of a word
Sbyte ; Byte to be sent/received by devices
Bytectr ; Byte counter for device processes
Bitctr ; Bit counter for device processes
;
; For RTC
RTCmem ; RTC memory address
BCDsec ; RTC memory 0 = Second BCD 00-59
BCDmin ; RTC memory 1 = Min BCD 00-59
BCDhr ; RTC memory 2 = Hour BCD 00-23
BCDdow ; RTC memory 3 = Day of Week 01-07
BCDday ; RTC memory 4 = Day BCD 01-31
BCDmon ; RTC memory 5 = Month BCD 01-12
BCDyr ; RTC memory 6 = Year yy BCD 00-99
;
; For I2C protocols
I2Cadr ; Destinated slave I2C address
DataLen ; Number of bytes to be sent/received
;
; For TM1637 4 digit display
; Sbyte ; Byte to send, shared with I2C
Dig1000 ; Digit 1000
Dig100 ; Digit 100
Dig10 ; Digit 10
Dig1 ; Digit 1
;
; Areas for time consuming subroutines
Mic25c
Mic50c
Millic
Mil100c
Secsc
Minsc
;
; Areas for debugging routines
DmpA ; Display byte area
Dmp8C ; Bit counter for loop (Initial Dmp8V =8)
BlinkC ; Counter for blinking (set for Debugb or Abendb)
Abendn ; Abend number
Ucpc ; User Check point chr to trace
Flags ; Flags mainly for debug
;
endc
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For PORTA ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;swMode equ 0 ; PORTsw Mode Switch
;swTime equ 1 ; PORTsw Time switch
;LED equ 1 ; PORTdbg LED for debugging
;Trig equ 1 ; PORTdbg Trig for debugging
;Dio equ 2 ; PORTtm TM16xx DIO
;swSet equ 3 ; PORTsw Set switch
;Dl equ 4 ; PORTI2C SDA
;Cl equ 5 ; PORTI2C SCL
;Clk equ 5 ; PORTtm TM16xx CLK
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTI2C ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTI2C equ PORTA ;
Dl equ 4 ; I2C Data line = SDA
Cl equ 5 ; I2C Clock line = SCL
LATI2C equ LATA ; LATch for I2C port
TRISI2C equ TRISA ; TRIS reg for I2C
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTtm ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTtm equ PORTA ;
Dio equ 2 ; TM16xx Data line = DIO
Clk equ 5 ; TM16xx Clock line = CLK
LATtm equ LATA ; Latch for tm port
TRIStm equ TRISA ; TRIS for tm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTsw ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTsw equ PORTA
swMode equ 0 ; Mode switch input ulled-up
swTime equ 1 ; Time switch input pulled-up
swSet equ 3 ; Set switch input pulled-up
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTdbg ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA
TRISdbg equ TRISA
WPUdbg equ WPUA
LED equ 1 ; LED when debugging
Trig equ 1 ; Trigger for DSO when debugging
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Values & Characters ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations for RTC DS3231
Clkt equ 1 ; Clock-time/4 multiplier of 2.5μS
Clkq equ 1 ; Quick time within clock 2μS
DS3231 equ H'D0' ; RTC DS3231 address (to write)
RTCdata equ BCDsec ; RTC memory data top
ModeMax equ 6 ; RTC data pointer ModeN max
ModeMin equ 0 ; RTC data pointer ModeN minimum
;
secMax equ H'59'
secMin equ 0
;
minMax equ H'59'
minMin equ 0
;
hrMax equ H'23'
hrMin equ 0
;
dowMax equ H'07'
dowMin equ H'01'
;
dayMax equ H'31'
dayMin equ H'01'
;
monMax equ H'12'
monMin equ H'01'
;
Modeyr equ 6
yrMax equ H'99'
yrMin equ 0
;
; 7 segment LED characters for TM1637
Ch7Y equ H'6E'
Ch7Eq equ H'48'
Ch7M equ H'37'
Ch7d equ H'5E'
Ch7w equ H'1C'
Ch7h equ H'74'
Ch7m equ H'54'
Ch7S equ H'6D'
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For Debug ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA ;
Trig equ 1 ; DSO trigger pulse port for test use
TrigpV equ B'00000010' ; = 2^Trig
;
Dmp8V equ D'8' ; Debug display bit counter initial value
Debugb equ D'8' ; number of blinkings to show Debugging
Abendb equ D'25' ; number of blinkings to notify Abend
; Flags byte
LEDpH equ 0 ; LED pin was High before debug use
LEDpIn equ 1 ; LED pin was input before debug use
TrigpIn equ 2 ; Trigger pin was input before debug use
TrigpH equ 3 ; Trigger pin was High before debug use
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Initializing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0
goto Startp ; Go to start entry
org 4 ; This is Interrupt entry
retfie ;
;
Startp DEVset ; Define ports
clrf FSR0H ; Clear FSR0H forever
clrf FSR1H ; Clear FSR1H forever
clrf Flags ; Clear all bits of Flags
;
Milli D'50' ; Wait devices stabilized
call IniTMr ; Set-up TM1638 display
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Main program loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mainp call RTCrdr ; Read clock
call Dsptime ; Display time
Secs 1 ; for 1 second
;
btfss PORTsw,swSet ; Set switch ?
call RTCupdr ; Yes, call RTC updating routine
;
goto Mainp ; Contilue infinite loop
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC updating routine ;
; Display value for current ModeN ;
; If swMode pushed, display next unit to update ;
; If swTime pushed, increase value and display it ;
; If swSet pushed, update RTC (RTCwtr) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCupdr btfss PORTsw,swSet ; swSet still on?
goto $-1 ; then wait for off
movlw Modeyr ; set initial mode year
movwf ModeN
;
RTCudm movf ModeN,W ; Large loop on ModeN
brw
goto Mdsecr ; case ModeN=0
goto Mdminr ; case ModeN=1
goto Mdhrr ; case ModeN=2
goto Mddowr ; case ModeN=3
goto Mddayr ; case ModeN=4
goto Mdmonr ; case ModeN=5
goto Mdyrr ; case ModeN=6
;
; Macro used within this section
Mdsetup macro T7c,Rmax,Rmin
movlw T7c
movwf T7Chr
movlw Rmax
movwf RvMax
movlw Rmin
movwf RvMin
goto Mdnext
endm
;
; set up environment for update and display
Mdsecr Mdsetup Ch7S,secMax,secMin
Mdminr Mdsetup Ch7m,minMax,minMin
Mdhrr Mdsetup Ch7h,hrMax,hrMin
Mddowr Mdsetup Ch7w,dowMax,dowMin
Mddayr Mdsetup Ch7d,dayMax,dayMin
Mdmonr Mdsetup Ch7M,monMax,monMin
Mdyrr Mdsetup Ch7Y,yrMax,yrMin
;
Mdnext call Rdspr ; Display mode"X=nn"
btfss PORTsw,swTime ; Is Time pushed ?
goto Rinc ; Yes, goto Rinc
btfss PORTsw,swMode ; Is Mode pushed ?
goto Rnxtm ; Yes, goto Rnxtm
btfss PORTsw,swSet ; Is Set pushed ?
goto Rwrite ; Yes, goto Rwrite
goto Mdnext ; If no button, small loop for button
;
; Time pushed here
Rinc call Rincr ; Increase value in that mode
Mil100 2 ; 0.2 sec for increasing value
goto Mdnext ; return to loop for button
;
; Mode pushed here
Rnxtm btfss PORTsw,swMode ; Mode button still pushed
goto Rmdck ; Yes, goto mode switch cheking
; short push of Mode sw released here
Rmdsht CalEO ModeN,0,Msmax ; If current ModeN=0 goto Msmax
decf ModeN,F ; set next mode
Rnxtme goto RTCudm ; and return to large loop for mode
;
Rmdck Mil100 3 ; wait for 300milli sec
btfsc PORTsw,swMode ; Mode button still pushed ?
goto Rmdsht ; No, goto short push process
;
Mil100 6 ; wait for additional 600 milli sec
btfsc PORTsw,swMode ; Mode button still pushed ?
goto Rmdsht ; No, goto short push process
;
; Mode switch pushed long, hence exit
btfss PORTsw,swMode ; wait for Mode sw released
goto $-1
goto Rexit ; and goto exit of RTC update routine
;
Msmax movlw Modeyr ; get maximum mode
movwf ModeN ; and set it
goto RTCudm ; and return to large loop for mode
;
Rwrite btfss PORTsw,swSet ; Set button still on?
goto $-1 ; then wait for release
call RTCwtr ; and write to RTC
;
Rexit return ; exit from RTC updating routine
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Display value pointed by ModeN ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Rdspr movf T7Chr,W
movwf Dig1000
movlw Ch7Eq
movwf Dig100
;
movlw BCDsec ; Point BCD area top
movwf FSR1L ; set it to FSR1L
movf ModeN,W ; Get Mode number
addwf FSR1L,F ; Point current BCD area
swapf INDF1,W ; get high nibble to low in W
call TMser ; clear high nibble & edit
movwf Dig10 ; set it to Dig10
movf INDF1,W ; get low nibble to low
call TMser ; clear high nibble to low
movwf Dig1 ; set it to Dig1
;
call TMdspr
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Increase value pointed by ModeN ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Rincr movlw BCDsec ; Point BCD area top
movwf FSR1L ; set it to pointer
movf ModeN,W ; get ModeN to add
addwf FSR1L,F ; Point current BCD area
;
CabSO INDF1,RvMax,Rigo ;If smaller than max, goto Rigo
movf RvMin,W ; Else, get minimum value
movwf INDF1 ; and set it to INDF1 (BCD area)
return
;
Rigo movf INDF1,W ; Get BCD value
andlw H'0F' ; clear left nibble
movwf Bytel ; and set to Bytel
swapf INDF1,W ; Get BCD nibbles swapped
andlw H'0F' ; clear left nibble
movwf Byteh ; and set to Byteh
;
incf Bytel,F ; Bytel+1
CalSO Bytel,D'10',Rie ; If Bytel≦9,goto Rie
movlw D'16' ; Else increase digit 10
addwf INDF1,F ;
movlw H'F0' ; and clear digit 1
andwf INDF1,F
return
Rie incf INDF1,F ; Increase BCD value
return ; and return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Displaying Time routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dsptime movf BCDmin,W ; get minute dig 1
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig1 ; set it to Digit 1
;
swapf BCDmin,W ; get minutes dig 10
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig10 ; set it to Digit 10
;
movf BCDhr,W ; get hour dig 1
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig100 ; set it to Digit 100
bsf Dig100,7 ; set colon after Digit 100
;
swapf BCDhr,W ; get hour dig 10
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig1000 ; set it to Digit 1000
;
call TMdspr ; show them to TM1637
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC reading routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCrdr clrf RTCmem ; set RTC memory addr 0
I2Csnd DS3231,RTCmem,1 ; send it to DS3231
Milli 1 ; wait for readiness (unnecessary?)
I2Crcv DS3231,RTCdata,7 ; receive 7 byte data from DS3231
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC writing routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCwtr clrf RTCmem ; Set memory address zero
I2Csnd DS3231,RTCmem,8 ; Send data, with memory addr on top
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Send byte-string ;
; when called, ;
; I2C device adr in I2Cadr byte ;
; Data length in DataLen ;
; Data Addr in FSR0L (INDF0) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Csndr movf I2Cadr,W
movwf Sbyte
; rlf Sbyte,F ; shift leftt (if adr for Arduino)
bcf Sbyte,0 ; indicate write
;
I2Cstat ; Start I2C
call Sendr
Sdata movf INDF0,W ; Get a sending character
movwf Sbyte ; Set it to Sbyte
call Sendr ; Send it to the device
;
incf FSR0L,F ; point next char
decfsz DataLen,F ; Have all chars sent ?
goto Sdata ; No, loop
;
; Stop signal and return
I2Cstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Receive byte-string ;
; when called, ;
; I2C device adr in I2Cadr byte ;
; Data length in DataLen ;
; Data Addr in FSR0L (INDF0) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Crcvr equ $
I2Cstat ; Start I2C
movf I2Cadr,W ; Get I2C dev addr
movwf Sbyte ; Set it into Sbyte
; rlf Sbyte,F ; Shift left (if adr for Arduino)
bsf Sbyte,0 ; indicate read
call Sendr ; Send slave addr to read
;
I2Crbyt equ $
BANKSEL TRISI2C ;
bsf TRISI2C,Dl ; Set Dline input mode
clrf BSR ; Point Bank 0
;
movlw 8 ; Bits in a reciving byte
movwf Bitctr ; into loop counter
I2Crblp Mic2p5 2*Clkt ; Timing before raising clock
bsf PORTI2C,Cl ; Set clock high
Mic2p5 Clkt ; Timing after raising clock
;
btfsc PORTI2C,Dl
goto Rbith
; goto Rbitl
;
Rbitl bcf Sbyte,0 ; Clear bit 0
goto Rbitnxt ; and goto next
;
Rbith bsf Sbyte,0 ; Set bit 0
Rbitnxt Mic2 Clkq ; Timing after checking
bcf PORTI2C,Cl ; Set clock low
; Mic2p5 Clkt ; Timing after clock falling
decfsz Bitctr,F ; Still bits?
goto Rbcont ; Yes, continue
goto Rbend ; No, end of one byte
;
Rbcont rlf Sbyte,F ; Shit left
goto I2Crblp ; and goto loop
;
Rbend movf Sbyte,W ; Get received byte
movwf INDF0 ; Set it to INDF0
incf FSR0L,F ; increase index
decfsz DataLen,F ; DataLen-1
goto Sackr ; Send Ack and continue
goto Snackr ; Send Nack and stop
;
;Set Dl output mode and send Ack to conitinue
Sackr equ $
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
;
bcf PORTI2C,Dl ; Send Ack
Mic2 Clkq ; Timing after clock falling
bsf PORTI2C,Cl ; Show Ack
Mic2p5 2*Clkt
bcf PORTI2C,Cl ; Set clock low
Mic2 Clkq
bsf PORTI2C,Dl ; Return Dline to high
goto I2Crbyt ; Next byte process
;
;Set Dl output mode and send Nack
Snackr equ $
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
;
bsf PORTI2C,Dl ; Send Nack
Mic2 Clkq ; Timing after clock falling
bsf PORTI2C,Cl ; Show Nack
Mic2p5 2*Clkt
bcf PORTI2C,Cl ; Set clock low
Mic2p5 Clkt
I2Cstop ; and stop I2C once
Mic5 D'6' ; for 30 micro sec
;
I2Cstat ; then start I2C again
movf I2Cadr,W ; Get I2C dev addr
movwf Sbyte ; Set it into Sbyte
; rlf Sbyte,F ; Shift left (if adr for Arduino)
bcf Sbyte,0 ; indicate write
call Sendr ; Send it
;
I2Cstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Start signal routine ;
; when dataline mode is output ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Cstar bcf PORTI2C,Dl ; set SDA low
Mic2 Clkq
bcf PORTI2C,Cl ; set SCL low
Mic2p5 2*Clkt
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Stop signal routine ;
; when dataline mode is output ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Cstpr bcf PORTI2C,Cl ; set SCL low
Mic2 Clkq
bcf PORTI2C,Dl ; set SDA low
Mic2p5 2*Clkt
bsf PORTI2C,Cl ; Clock line rasing
Mic2p5 Clkt
bsf PORTI2C,Dl ; Data line rasing
Mic2 Clkq
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C One-byte sending routine ;
; with data in Sbyte ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Sendr movlw 8 ; Set bit count in a byte
movwf Bitctr ; into loop counter
;
Sloop btfsc Sbyte,7 ; Check top bit of Sbyte
goto Slpdh ;
bcf PORTI2C,Dl ; If bit low then Data L
goto Slpnxt
Slpdh bsf PORTI2C,Dl ; If bit high then Data H
;
Slpnxt Mic2 Clkq
bsf PORTI2C,Cl ; Show bit
Mic2p5 2*Clkt
bcf PORTI2C,Cl ;
Mic2 Clkq
;
rlf Sbyte,F ; Shift left
decfsz Bitctr,F ; All bits done?
goto Sloop ; No, loop within a byte
;
;Receive Ack
; set data line input mode
BANKSEL TRISI2C ;
bsf TRISI2C,Dl ; Set Dline input mode
clrf BSR ; Point Bank 0
;
Mic2 Clkq ; wait for Ack timing
bsf PORTI2C,Cl ; Clock H for Acq confirmation
Mic2p5 2*Clkt ;
bcf PORTI2C,Cl ; Cl L for Dl release by slave
Mic2p5 2*Clkt
;
; Set Data line output
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 support routines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 display brightness setting ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IniTMr equ $
; TM brightness initial setting ;
; H'88'+ duty ratio:
; H'00'=1/16, H'01'=2/16, H'02'=4/16, H'03'=10/16
; H'04'=11/16, H'05'=12/16, H'06'=13/16, H'07'=14/16
movlw H'88'+H'02' ; Initial brightness value
movwf Sbyte ; Set to Sbyte
TMstart
TMsendB Sbyte
TMstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM 1637 Char to 7 segment editing routine ;
; replaceubg Char in W with 7 seg in W ;
; 7 seg format is B'xgfe-dcba' ;
; if colon required,IOR H'80' to Dig100 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMser andlw H'0F' ; Prevent wild branch
brw
Case0 retlw H'3F'
Case1 retlw H'06'
Case2 retlw H'5B'
Case3 retlw H'4F'
Case4 retlw H'66'
Case5 retlw H'6D'
Case6 retlw H'7D'
Case7 retlw H'07'
Case8 retlw H'7F'
Case9 retlw H'6F'
CaseA retlw H'77' ; A
CaseB retlw H'7C' ; b
CaseC retlw H'39' ; C
CaseD retlw H'5E' ; d
CaseE retlw H'79' ; E
CaseF retlw H'71' ; F
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 4digits displaying routine ;
; using Dig1000 to Dig1 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMdspr movlw Dig1000 ; Point Byte0 address
movwf FSR0L ; set it to use INDF0
movlw 4 ; Set four digits
movwf Bytectr ; to Byte counter
;
TMstart
TMsendL H'40' ;
TMstop ;
;
TMstart
TMsendL H'C0' ; Set addr zero of TM
;
TMdspl movf INDF0,W ; Get byte contents
movwf Sbyte ; Set them to Sbyte
TMsendB Sbyte ;
incf FSR0L,F ; point next byte
decfsz Bytectr,F ; Check if all done
goto TMdspl ; No. loop
;
TMstop ; When all sent, Stop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Start sending routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMstrtr nop
BANKSEL TRIStm
bsf LATtm,Dio ; Dio high beforhand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; return to Bank0
;
bsf PORTtm,Dio ; Dio high
Mic2 Clkq
bsf PORTtm,Clk ; Clk high
Mic2 Clkq
bcf PORTtm,Dio ; Dio low
Mic2 Clkq
bcf PORTtm,Clk ; Clk low
Mic2 Clkq
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Stop sending routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMstopr nop
BANKSEL TRIStm
bcf LATtm,Dio ; Dio low beforehand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; Return to Bank0
;
Mic2 Clkq
bsf PORTtm,Clk ; Clk high
Mic2 Clkq
bsf PORTtm,Dio ; Data high
Mic2p5 D'10'
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Byte sending routine ;
; called by TMsendB with Sbyte or ;
; TMsendL with value in W reg ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMsndLr movwf Sbyte ; Set sending byte
;
TMsndBr movlw 8 ; Set bit count
movwf Bitctr ; into loop counter
;
Tloop btfsc Sbyte,0 ; Check LSb for little-endian-
goto Tlpdh ;
bcf PORTtm,Dio ; If bit low then Data L
goto Tlpnxt
;
Tlpdh bsf PORTtm,Dio ; If bit high then Data H
Tlpnxt Mic2 Clkq;
bsf PORTtm,Clk ; Clock high
Mic2p5 2*Clkt ; (5 micro sec if standard)
bcf PORTtm,Clk ; Clock low
Mic2 Clkq
rrf Sbyte,F ; Shift right for little-endian
decfsz Bitctr,F
goto Tloop
;
; Receiving Ack ;
BANKSEL TRIStm
bsf TRIStm,Dio ; Set Dio input mode
clrf BSR ; return to Bank0
Mic2p5 Clkt ; Wait for Ack=low
bsf PORTtm,Clk ; Clk high for Ack confirmation
Mic2p5 2*Clkt ; (5 micro sec if standard)
bcf PORTtm,Clk ; Clk L for Data release to H by Slave
Mic2p5 Clkt ; Wait for Dio set H
;
BANKSEL TRIStm
bsf LATtm,Dio ; Dio high beforhand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; return to Bank0
Mic2p5 5 ; Enough time for TM1637 after Ack
return ;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Timing subrooutines for general purposes ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.0 micro S x n (Mic2) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic2r movwf Mic25c ; + Wset + call = 1 micro sec
;
Mic2l decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic2li ; else go out (2nd time 1.75 mic sec)
return
;
Mic2li goto $+1 ; (2nd time 2.25 mic sec)
nop ; (2nd time 2.5 mic sec)
goto Mic2l ; go back (2nd time 3 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.5 micro S x n (Mic2p5) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic25r movwf Mic25c ; + Wset + call = 1 micro sec
nop ; 1.25 micro sec
;
Mic25l nop ; 1.5 micro sec (2nd time 4 mic sec)
decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic25li ; else go out (2nd time 2.25 mic sec)
return
;
Mic25li Mic ; (2nd time 3.25 mic sec)
goto Mic25l ; go back (2nd time 3.75 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 50 Microseconds x n Mic50 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Mic50r movwf Mic50c ; set how many 50 microsec (1 micro sec to here)
nop ; 1.25 micro sec up to here
;
Mic50l Mic2p5 D'19' ; + 47.5 = 48.75 mic sec (2nd time 98.75 mic sec)
nop ; + 0.25 = 49 micro sec (2nd time 99 mic sec)
;
decfsz Mic50c,F ; If exhausted then 1 mic S hereafter
goto Mic50li ; else go out (2nd time 49.75 mic sec)
return
;
;
Mic50li Mic ; (2nd time 50.75 mic sec)
goto Mic50l ; go back (2nd time 51.25 mic sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Milliseconds x n (Milli) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Millir movwf Millic ; set how many 1 mil sec (1 mic S up to here)
nop ; 1.25 micro sec
;
Millil Mic50 D'19' ; + 50 mic x 19 = 951.25 mic S (2nd, 1951.25)
Mic2p5 D'19' ; + 47.5 mic = 998.75 micro S (2nd, 1998.75)
nop ; +0.25 mic = 999 micro sec (2nd, 1999)
;
decfsz Millic,F ; If exhausted then 1 micro sec hereafter
goto Millili ; else go out (2nd, 999.75 mic S)
return
;
Millili Mic ; (2nd time 1000.75 mic S)
goto Millil ; go back (2nd time 1001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 100 Milliseconds x n (Mil100);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mil100r movwf Mil100c ;set how many 100 ms(1 micr sec up to here)
nop ; 1.25 micro sec
;
Milhl Milli D'99' ;+1ms x 99 = 99001.25 micS (2nd,199001.25mic)
Mic50 D'19' ; + 950 mic = 99951.25 micS(2nd.199951.25mic)
Mic2p5 D'19' ; + 47.5 mic = 99998.75micS(2nd,199998.75mic)
nop ; + 0.25 mic = 99999 mic S (2nd,199999 micS)
;
decfsz Mil100c,F ; If exhausted then 1 micro sec hereafter
goto Milhli ; else go out (2nd time, 99999.75 mic S)
return
;
Milhli Mic ; (2nd time, 100000.75 mic S)
goto Milhl ; (2nd time, 100001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Seconds x n (Secs) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Secsr movwf Secsc ; set how many sec ( 1 mic sec up to here)
nop ; 1.25 micro sec
;
Secsl Mil100 D'9' ;
Milli D'99' ; + 999 milli sec = 999001.25 micro sec
;
Mic50 D'19' ; + 950 mic = 999951.25 micro sec
Mic2p5 D'19' ; + 47.5 mic = 999998.75 micro sec
nop ; + 0.25 mic = 999999 micro sec
;
decfsz Secsc,F ; If exhausted then 1 micro sec hereafter
goto Secsli ; else, go out
return
;
Secsli Mic
goto Secsl ; (Second time, Sec + 1.25 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Minutes x n (Mins) ;
; Overhead ignored, that is only ;
; 751.25 Mic S even when 100 Min ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Minsr movwf Minsc ;set how many minutes from parameter
;
Minsl Secs D'60' ; 1 Seconds x 60
decfsz Minsc,F
goto Minsl
return
;
space
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User debug subroutine ;
; Show bit 7 to 0 ;
; of specified byte ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Udbgr clrf BSR ; Set Bank=0
movwf DmpA ; move data to Dmpa
;
btfss PORTdbg,LED ; Check if LED=on (on=High)
goto UdbLoff ; if LED=off(Low), skip saving process
bsf Flags,LEDpH ; Save LEDon status
LEDoff ; and off LED
Mil100 D'10' ; wait for a second in case LED has been on
;
UdbLoff movlw Dmp8V ; set counter 8
movwf Dmp8C ; to Dmp8C
;
Udblp Ublink Debugb ; Blink for Debug = 8 times
btfsc DmpA,7 ; check top bit 7
goto UdbOn ; if on then to UdbOn
goto UdbOff ; if off then to UdbOff
;
UdbOn LEDon
Mil100 D'30' ;
goto Udbeck
;
UdbOff LEDoff
Mil100 D'30' ;
; goto Udbeck
;
Udbeck decfsz Dmp8C,F
goto Udbnext
goto Udbend
;
Udbnext rlf DmpA,F
goto Udblp
;
Udbend Ublink Debugb ; end blinking and
Mil100 D'100' ; blank for 10 seconds to write down
;
btfss Flags,LEDpH ; Check if LED was on
goto Udbret ; no, goto return
LEDon ; if it was on, then on again
bcf Flags,LEDpH ; Clear LED save flag
;
Udbret return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Blinking to show debug or abend ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ublinkr movwf BlinkC
Ublinkl LEDon ; LED on
Milli D'30' ; for 30ms
LEDoff ; LED off
Milli D'200' ; for 200ms
;
decfsz BlinkC,F
goto Ublinkl
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Abend routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Uabendr clrf BSR
movwf Abendn ; Set Uabend number
;
Ublink Abendb ; Blink 25 times
Udebug Abendn ; Show Abend number
goto $
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end
PgmName="190923-JpgToPolarCoordinatesTxt-V00"
CopyRight="(c)2019 Akira Tominaga, All rights reserved"
' Function
' Get brightness data from jpg and make txt file for plotter
' Major revisions
' V00 Sept. 23, 2019
TextWindow.Title=PgmName +" "+CopyRight
TextWindow.BackgroundColor="Black"
' Set data path ***** PgmName must be correct to get data path *****
myPath=File.GetSettingsFilePath() 'set current path name all
Tlen1=Text.GetLength(mypath) ' get current path name length
Tlen2=Text.GetLength(PgmName+".Settings") ' get unneeded length
myPath=Text.GetSubText(myPath,1,Tlen1-Tlen2) 'set folder name only
myPath=myPath+"Dat5\" ' and add the name of data folder
' Load picture PICnnn.jpg specified by keyed-in nnn
TextWindow.WriteLine("") ' skip one line For ease of key-in
KeyIn:
TextWindow.Write(" Please type-in PIC#. -> ")
keyinN=TextWindow.Read()
myPict=myPath+"PIC"+keyinN+".jpg"
PsizeX=ImageList.GetWidthOfImage(myPict)
If PsizeX>18 Then ' exists with enough size to plot ?
Goto ImageOK
Else
TextWindow.WriteLine("*** No such PCL#.jpg ***")
Goto Keyin
EndIf
ImageOK:
PsizeY=ImageList.GetHeightOfImage(myPict)
'Graphics window
GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.Width=PsizeX*2
GraphicsWindow.Height=PsizeY
GraphicsWindow.Title=PgmName
inPic=ImageList.LoadImage(myPict)
GraphicsWindow.DrawImage(inPic,0,0)
'Setup Polar Coordinates values for tested rotator
thetaPi=1211 ' device specific number to rotate pi (half circle)
rMax=Math.SquareRoot(PsizeX*PsizeX/4+PsizeY*PsizeY)+1
'Setup work file name and create header record
wkFile=myPath+"Work"+KeyinN+".txt"
lnum=1 'PsizeX,PsizeY characters with left zero
szX=PsizeX+1000 ' to secure 4 digits, add 1000
szY=PsizeY+1000 ' to secure 4 digits, add 1000
rMax4=Text.GetSubText(rMax+1000,1,4) 'delete value under 1
thetaPi4=thetaPi+1000 ' to secure 4 digits, add 1000
header=szX+","+szY+","+rMax4+","+thetaPi4
File.WriteLine(wkFile,lnum,header)
'Get RGB data and convert them to Brightness data
Density=2.0 ' Set data density *********** Specify density*********
For Ptheta=0 To thetaPi step Density
For Pr=0 To rMax Step Density
'Convert polar-coordinates to XY
CalcXY()
xX=XX+1000 'force 4digits
YY=YY+1000 'force 4digits
X=Text.GetSubText(XX,1,4)-1000
Y=Text.GetSubText(YY,1,4)-1000
If X<=0 or X>=PsizeX or Y<=0 or Y>=PsizeY then
Goto Ignore
EndIF
'Get color and convert it to brightness
color=GraphicsWindow.GetPixel(X,Y)
getkido() ' convert RGB to Brightness
gcolor="#000000"
txdata=""
'If dark then make SD record and plot picture
If kido<128 Then
gcolor="#FFFFFF"
'Set text data
X4=X+1000
Y4=Y+1000
rp4=Pr+1000
thetap4=ptheta+1000
txdata=X4+","+Y4+","+rp4+","+thetap4
lnum=lnum+1
File.WriteLine(wkFile,lnum,txdata)
EndIf
GraphicsWindow.SetPixel(X+PsizeX,Y,gcolor)
Ignore:
EndFor
EndFor
' When all data done, write EOF
lnum=lnum+1
eof=9999
File.WriteLine(wkFile,lnum,eof)
TextWindow.Write("Work")
TextWindow.Write(KeyinN)
TextWindow.WriteLine(".txt has been created as a work file")
TextWindow.Write(" with ")
TextWindow.Write(lnum-2)
TextWindow.WriteLine(" points to plot")
' Optimization for quick plotting
'Prepare output file
OutFile=myPath+"PICT"+KeyinN+".txt"
' Transfer header (Xsize,Ysize,rMax,thetaPi)
InLnum=1
InText=File.ReadLine(wkFile,InLnum)
OutLnum=1
OutText=InText
File.WriteLine(OutFile,OutLnum,OutText)
' Convert wkFile to OutFile
OutReverse=0
InLnum=InLnum+1
InText=File.ReadLine(wkFile,InLnum)
OutText=InText
OutRec=1
Tsave=Text.GetSubText(InText,16,4)
OutLoop:
InLnum=InLnum+1
InText=File.ReadLine(wkFile,InLnum)
XX=Text.GetSubText(InText,1,4)
If XX=9999 Then
OutLnum=OutLnum+1
File.WriteLine(OutFile,OutLnum,OutText)
OutText=InText
OutLnum=OutLnum+1
File.WriteLine(OutFile,OutLnum,OutText)
Goto Eof
EndIf
' Change color of process point to yellow
X=XX-1000
YY=Text.GetSubText(InText,6,4)
Y=YY-1000
gcolor="#FFFF00"
GraphicsWindow.SetPixel(X+PsizeX,Y,gcolor)
' Go on to check next input
Tchk=Text.GetSubText(InText,16,4)
If Tchk=Tsave Then ' if same theta then
Goto accumText ' accumulate data without output
Else ' else output accumulated data
Tsave=Tchk
Goto accumOut
EndIf
' Accumulate data records with opposite sequences alternatively
accumText:
If OutReverse=0 Then
OutText=Text.GetSubText(OutText,1,22*OutRec-2)+"##"+InText
Else
OutText=Text.GetSubText(InText,1,20)+"##"+OutText
EndIf
OutRec=OutRec+1
Tsave=Tchk
Goto OutLoop
accumOut:
OutLnum=OutLnum+1
File.WriteLine(OutFile,OutLnum,OutText)
OutText=InText
If OutReverse=0 Then
OutReverse=1
Else
OutReverse=0
EndIf
Goto OutLoop
' End of file process
Eof:
TextWindow.Write("Edited ")
TextWindow.Write(InLnum-2)
TextWindow.Write(" input to ")
TextWindow.Write(OutLnum)
TextWindow.WriteLine(" output text-lines")
Sound.PlayBellRing()
Sub getkido ' from color code #rrggbb to brightness
HexV=0
Hexc=Text.GetSubText(color,2,1)
Hex2V()
R10=HexV
Hexc=Text.GetSubText(color,2,1)
Hex2V()
R01=HexV
Rv=R10*16+R01
Hexv=Text.GetSubText(color,3,1)
Hex2V()
G10=HexV
Hexc=Text.GetSubText(color,4,1)
Hex2V()
G01=HexV
Gv=G10*16+G01
Hexc=Text.GetSubText(color,5,1)
Hex2V()
B10=HexV
Hexc=Text.GetSubText(color,6,1)
Hex2V()
B01=HexV
Bv=B10*16+B01
Kido=0.299*Rv+0.587*Gv+0.114*Bv
EndSub
Sub Hex2V ' from hexa-decimal one digit to value
If Hexc < "9" Then
Hexv=Hexc
EndIf
If Hexc="A" Then
HexV=10
EndIf
If Hexc="B" Then
HexV=11
EndIf
If Hexc="C" Then
HexV=12
EndIf
If Hexc="D" Then
HexV=13
EndIf
If Hexc="E" Then
HexV=14
EndIf
If Hexc="F" Then
HexV=15
EndIf
EndSub
Sub CalcXY ' Calculate XX and YY from Pr and Ptheta
xx=Pr*Math.Cos(Math.Pi*Ptheta/thetaPi)
XX=xx+PsizeX/2
yy=Pr*Math.Sin(Math.Pi*Ptheta/thetaPi)
YY=PsizeY-yy
EndSub
Windowsの場合に、すぐ使うプログラムを作るのに一番単純で手っ取り早いのはマイクロソフトがフリーで提供している Small Basicかと思います。これですと作成時間が僅かで済むし、Windows自体との相性もいい(それはあたりまえか)。さらに、完成したプログラムをVisual Basicへ自動変換する機能も備えています。
;U190915-RTC-DHT11-TM16-V01s.asm As of Sept. 15, 2019
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; RTC Reader/Writer, DHT11 reader & TM1637 display with PIC12F1822 V01 ;
; (C)2015-2019 Akira Tominaga, All rights reserved. ;
; Major revisions ;
; V00 Original version Sept.8, 2019 ;
; V01 Raise 2-wire speed (both I2C and TM16xx) to 100kHz ;
; ;
; Function ;
; 1.Show time, temperature, & humidity on TM1637 4 digit display ;
; 2.Update DS3231 calendar and time when Set switch pushed ;
; Mode switch to change calendar/time unit ;
; Time switch to change value of the unit within its range ;
; ;
; Input/output ;
; RA0 Set switch (swSet) input pulled-up ;
; RA1 Time switch (swTime) input pulled-up ;
; Used as LED or DSO trigger when debugging ;
; RA2 DIO for TM1637 outuput usually and input occasionally ;
; RA3 Mode switch (swMode) input pulled-up ;
; RA4 SDA for I2C-RTC output usually and input occasionally ;
; RA5 SCL for I2C-RTC output, CLK for TM1637 output, and ;
; DHT11 1-wire output/input with Low-pass filter 200ohm+0.01μF;
; ;
; Remarks ;
; 1. Clock = HFINTOSC ( 16MHz) ;
; Hence 1 step = 0.25 micro seconds ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
list p=12F1822 ; list directive to define processor
#include ; <p12F1822.inc> specific variables
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
; page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Macro definitions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Device dependent Macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DEVset macro
BANKSEL OSCCON ; Bank=1
movlw B'01111010' ; 16MHz and internal oscillator
movwf OSCCON
;
; BANKSEL INTCON ; Interrupt Con (in all banks hence comment)
clrf INTCON ; Disable all interrupts
;
; PORTA initialization
BANKSEL PORTA ; Bank=0
clrf PORTA
; BANKSEL LATA ; Bank=2
; clrf LATA
BANKSEL ANSELA ; Bank=3
clrf ANSELA ; No use of ADC
BANKSEL ADCON0 ; Bank=1
clrf ADCON0 ; No use of ADC
;
BANKSEL TRISA ; Bank=1
movlw B'11001011' ; RA2,4 and 5 are output
movwf TRISA
;
BANKSEL OPTION_REG ; Bank=1
bcf OPTION_REG,7 ; Enable weak pull-up
BANKSEL WPUA ; Bank=4
movlw B'00001011' ; Weak Pull-up for RA 0,1,and 3
movwf WPUA ;
;
clrf BSR ; Bank=0
InitP ; Initialize ports
endm
;
InitP macro ; Initialize ports
movlw B'11111111' ; All inputs pulled-up and outputs H
movwf PORTA
endm
;
; for I2C-Master protocol
; Sending data to I2C slave
I2Csnd macro slave,dataa,datalen
movlw slave
movwf I2Cadr
movlw dataa
movwf FSR0L
movlw datalen
movwf DataLen
call I2Csndr
endm
;
; Receiving data from I2C slave
I2Crcv macro slave,dataa,datalen
movlw slave
movwf I2Cadr
movlw dataa
movwf FSR0L
movlw datalen
movwf DataLen
call I2Crcvr
endm
;
; I2C start signal
I2Cstat macro
call I2Cstar
endm
;
; I2C stop signal
I2Cstop macro
call I2Cstpr
endm
;
; For TM16xx-Master protocol
; Sending Literal to TM16xx
TMsendL macro tslit ; Send a literal to TM1637
movlw tslit
call TMsndLr
endm
;
; Sending a Byte to TM16xx
TMsendB macro tsbyte ; Send a Byte specified, to TM1637
movf tsbyte,W
movwf Sbyte
call TMsndBr
endm
;
; TM16xx start signal
TMstart macro ; Start TM16xx lines
call TMstrtr
endm
;
; TM16xx stop signal
TMstop macro ; Stop TM16xx lines
call TMstopr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; API and I/O macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;for TM1637 application interfaces
;display 4 literal characters directly to TM1637
dsp4chr macro d1000,d100,d10,d1
movlw d1000
movwf Dig1000
movlw d100
movwf Dig100
movlw d10
movwf Dig10
movlw d1
movwf Dig1
call TMdspr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Time cosuming macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic macro ;Consume 1 μS only
goto $+1
goto $+1
endm
;
Mic2 macro mic2p ;Consume 2 μS x n
movlw mic2p
call Mic2r
endm
;
Mic2p5 macro mic25p ; Consume 2.5μS x n
movlw mic25p
call Mic25r
endm
;
Mic5 macro mic5p ; Consume 5μS x n
movlw mic5p
call Mic25r
movlw mic5p
call Mic25r
endm
;
Mic50 macro mic50p ; Consume 50μS x n
movlw mic50p
call Mic50r
endm
;
Milli macro millip ; Consume mS x n
movlw millip
call Millir
endm
;
Mil100 macro mil100p ; Consume 100 mS x n
movlw mil100p
call Mil100r
endm
;
Secs macro secsp ; Consume Second x n
movlw secsp
call Secsr
endm
;
Mins macro minsp ; Consume Minute x n
movlw minsp
call Minsr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Debug and Abend macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LEDon macro ; LED on macro for debugging
bcf Flags,LEDpH ; Clear LEDpin flags beforehand,
bcf Flags,LEDpIn ; as timing before PORT accessed
btfsc PORTdbg,LED ; Has LED been H before debug?
bsf Flags,LEDpH ; Yes, set LEDpH flag
BANKSEL TRISdbg ; Select TRIS bank
btfss TRISdbg,LED ; Has LED pin been input?
goto $+4 ; No, skip the next 3 steps
clrf BSR ; Point Bank0
bsf Flags,LEDpIn ; Show LED pin was input
BANKSEL TRISdbg ; Select Tris bank again
;
bcf TRISdbg,LED ; Set LED output mode, in any case
clrf BSR ; Point Bank 0
bsf PORTdbg,LED ; LED on
goto $+1 ; Timing after PORTdbg changed
endm
;
LEDoff macro ; LED off macro for debugging
goto $+1 ; Avoid PORT-update timing problem
bcf PORTdbg,LED ; LED off
btfss Flags,LEDpIn ; Was LEDpin input before debug?
goto $+7 ; No, skip the following 6 steps
;
BANKSEL TRISdbg ; Select TRISdbg bank
bsf TRISdbg,LED ; Set LED pin input again
BANKSEL WPUdbg ; Select WPUdbg, assuming Pulled-up
bsf WPUdbg,LED ; Weak Pull-up for input pin
clrf BSR ; Point Bank 0
goto $+3 ; skip the next 2 steps
;
btfsc Flags,LEDpH ; Was LEDpin High
bsf PORTdbg,LED ; Yes, set LED pin High
bcf Flags,LEDpH ; Clear LED flags,
bcf Flags,LEDpIn ; as timing after PORTdbg changed
endm
;
Trigger macro ; Trigger for DSO
bcf Flags,TrigpH ; ClearTrigger flags beforehand
bcf Flags,TrigpIn ; for timing before PORT changed
btfsc PORTdbg,Trig ; Has Trig pin been H before debug?
bsf Flags,TrigpH ; Yes, set TigpH flag
BANKSEL TRISdbg ; Select TRIS bank
btfss TRISdbg,Trig ; Has Trig pin been input?
goto $+4 ; No, skip the following 3 steps
clrf BSR ; Yes, point Bank 0,
bsf Flags,TrigpIn ; and show Trig pin was input,
BANKSEL TRISdbg ; select TRISdbg bank again
;
bcf TRISdbg,Trig ; Set Trig pin output, in any case
clrf BSR ; Point Bank 0
btfss Flags,TrigpH ; Was Trigger pin H?
goto $+3 ; No, goto slope-rising trigger
bcf PORTdbg,Trig ; Yes, set slope-falling trigger
goto $+2 ; and skip next line
bsf PORTdbg,Trig ; Slope-rising trigger
;
Mic2 2 ; Trigger for 4 micro seconds
movlw TrigpV ; Set trigger pin value to W
xorwf PORTdbg,F ; Stop trigger (H/L to L/H)
;
btfss Flags,TrigpIn ; Was Trig pin input before debug?
goto $+10 ; No, skip the following 9 steps
;
BANKSEL TRISdbg ; Select TRISdbg bank
bsf TRISdbg,Trig ; Set Trig-pin input
clrf BSR ; Select Bank 0
btfsc Flags,TrigpH ; Was Trigger pin L?
goto $+4 ; Yes, skip the followings
BANKSEL WPUdbg ; No,Bank select for WPUdbg
bsf WPUdbg,Trig ; Weak Pull-up for input pin
clrf BSR ; Re-select Bank 0
goto $+7 ; skip next 6 steps for output
;
btfss Flags,TrigpH ; Was Trigger pin H?
goto $+3 ; No, skip next 2 steps
bsf PORTdbg,Trig ; Yes, Set trig pin H
goto $+2 ; and skip next line
bcf PORTdbg,Trig ; Set trig pin L
;
bcf Flags,TrigpH ; Clear flags for trigger
bcf Flags,TrigpIn ; as timing after PORTdbg changed
endm
;
Udebug macro Addr
movf Addr,W
call Udbgr
endm
;
Uabend macro abn ; User Abnormal-end number
movlw abn
goto Uabendr
endm
;
Ublink macro bno ; Blink LED for specified times
movlw bno
call Ublinkr
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Logic macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Comparison macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare A w/ B and branch to Smaller, Equal, or Larger(next statm't line)
CabSEL macro Aadr,Badr,Smladr,Eqladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ B and branch to Smaller or Others (Equal or Larger)
CabSO macro Aadr,Badr,Smladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ B and branch to Equal, or Other(next statm't line)
CabEO macro Aadr,Badr,Eqladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfsc STATUS,Z ; A=B?
goto Eqladr ; If A=B goto Eqljmp
; ; else next (here)
endm
;
; Compare A w/ literal and branch to Smaller, Equal, or Larger(next statm't)
CalSEL macro Aadr,Blit,Smladr,Eqladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ literal and branch to Smaller, or Others (Equal or Larger)
CalSO macro Aadr,Blit,Smladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ literal and branch to Equal, or Others
CalEO macro Aadr,Blit,Eqladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; else next (here)
endm
;
; Compare A w/ literal and branch to Large, or Others
CalLO macro Aadr,Blit,Ladr
movlw Blit ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto $+3 ; If A<B goto Others
btfss STATUS,Z ; A=B? Yes skip next
goto Ladr ; If A>B goto Laddr
; ; If A≦B then next (here)
endm
;
; Compare A with Literal and branch to Un-equal, or Others
CalUO macro Aadr,Blit,Uneqladr
movlw Blit ; W=B literal
subwf Aadr,W ; W=A-B
btfss STATUS,Z ; A=B?
goto Uneqladr ; No, goto unequal
; ; If yes then next
endm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files and Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Files ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cblock H'20'
;
; For Application support
ModeN ; Mode to point BCD mem addr of RTC
T7Chr ; 7 segment character to show ModeN
RvMax ; Max number of RTC data in ModeN
RvMin ; Minimum num of RTC data in ModeN
Byteh ; Work area as high byte of a word
Bytel ; Work area as low byte of a word
Sbyte ; Byte to be sent/received by devices
Bytectr ; Byte counter for device processes
Bitctr ; Bit counter for device processes
;
; For RTC
RTCmem ; RTC memory address
BCDsec ; RTC memory 0 = Second BCD 00-59
BCDmin ; RTC memory 1 = Min BCD 00-59
BCDhr ; RTC memory 2 = Hour BCD 00-23
BCDdow ; RTC memory 3 = Day of Week 01-07
BCDday ; RTC memory 4 = Day BCD 01-31
BCDmon ; RTC memory 5 = Month BCD 01-12
BCDyr ; RTC memory 6 = Year yy BCD 00-99
;
; For I2C protocols
I2Cadr ; Destinated slave I2C address
DataLen ; Number of bytes to be sent/received
;
; For TM1637 4 digit display
; Sbyte ; Byte to send, shared with I2C
Dig1000 ; Digit 1000
Dig100 ; Digit 100
Dig10 ; Digit 10
Dig1 ; Digit 1
;
; For DHT11 input data area
DHTrh ; Relative humidity integer
DHTrhd ; Relative humidity digit under 1
DHTt ; Temperature integer
DHTtd ; Temperature digit under 1
DHTcks ; Checksum
;
; Areas for time consuming subroutines
Mic25c
Mic50c
Millic
Mil100c
Secsc
Minsc
;
; Areas for debugging routines
DmpA ; Display byte area
Dmp8C ; Bit counter for loop (Initial Dmp8V =8)
BlinkC ; Counter for blinking (set for Debugb or Abendb)
Abendn ; Abend number
Ucpc ; User Check point chr to trace
Flags ; Flags mainly for debug
;
endc
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For PORTA ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;swSet equ 0 ; PORTsw Set switch
;swTime equ 1 ; PORTsw Time switch
;LED equ 1 ; PORTdbg LED for debugging
;Trig equ 1 ; PORTdbg Trig for debugging
;Dio equ 2 ; PORTtm TM16xx DIO
;swMode equ 3 ; PORTsw Mode Switch
;Dl equ 4 ; PORTI2C SDA
;Cl equ 5 ; PORTI2C SCL
;Clk equ 5 ; PORTtm TM16xx CLK
;DHT11 equ 5 ; PORTdht DHT11 one wire signal
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTI2C ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTI2C equ PORTA ;
Dl equ 4 ; I2C Data line = SDA
Cl equ 5 ; I2C Clock line = SCL
LATI2C equ LATA ; LATch for I2C port
TRISI2C equ TRISA ; TRIS reg for I2C
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTtm ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTtm equ PORTA ;
Dio equ 2 ; TM16xx Data line = DIO
Clk equ 5 ; TM16xx Clock line = CLK
LATtm equ LATA ; Latch for tm port
TRIStm equ TRISA ; TRIS for tm
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTdht ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdht equ PORTA ;
DHT11 equ 5 ; DHT11 one-wire signal
LATdht equ LATA ; Latch for dht port
TRISdht equ TRISA ; TRIS for dht
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTsw ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTsw equ PORTA
swSet equ 0 ; Set switch input pulled-up
swTime equ 1 ; Time switch input pulled-up
swMode equ 3 ; Mode switch input ulled-up
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** Logical PORTdbg ; Change this when port changed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA
TRISdbg equ TRISA
WPUdbg equ WPUA
LED equ 1 ; LED when debugging
Trig equ 1 ; Trigger for DSO when debugging
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Values & Characters ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Equations for RTC DS3231
Clkt equ 1 ; Clock-time/4 multiplier of 2.5μS
Clkq equ 1 ; Quick time within clock 2μS
DS3231 equ H'D0' ; RTC DS3231 address (to write)
RTCdata equ BCDsec ; RTC memory data top
ModeMax equ 6 ; RTC data pointer ModeN max
ModeMin equ 0 ; RTC data pointer ModeN minimum
;
secMax equ H'59'
secMin equ 0
;
minMax equ H'59'
minMin equ 0
;
hrMax equ H'23'
hrMin equ 0
;
dowMax equ H'07'
dowMin equ H'01'
;
dayMax equ H'31'
dayMin equ H'01'
;
monMax equ H'12'
monMin equ H'01'
;
Modeyr equ 6
yrMax equ H'99'
yrMin equ 0
;
; 7 segment LED characters for TM1637
Ch7Y equ H'6E'
Ch7Eq equ H'48'
Ch7M equ H'37'
Ch7d equ H'5E'
Ch7w equ H'1C'
Ch7h equ H'74'
Ch7m equ H'54'
Ch7S equ H'6D'
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; For Debug ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PORTdbg equ PORTA ;
Trig equ 1 ; DSO trigger pulse port for test use
TrigpV equ B'00000010' ; = 2^Trig
;
Dmp8V equ D'8' ; Debug display bit counter initial value
Debugb equ D'8' ; number of blinkings to show Debugging
Abendb equ D'25' ; number of blinkings to notify Abend
; Flags byte
LEDpH equ 0 ; LED pin was High before debug use
LEDpIn equ 1 ; LED pin was input before debug use
TrigpIn equ 2 ; Trigger pin was input before debug use
TrigpH equ 3 ; Trigger pin was High before debug use
;
page
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Initializing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 0
goto Startp ; Go to start entry
org 4 ; This is Interrupt entry
retfie ;
;
Startp DEVset ; Define ports
clrf FSR0H ; Clear FSR0H forever
clrf FSR1H ; Clear FSR1H forever
clrf Flags ; Clear all bits of Flags
;
Milli D'50' ; Wait devices stabilized
call IniTMr ; Set-up TM1638 display
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Main program loop ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mainp call RTCrdr ; Read clock
call Dsptime ; Display time
Secs 1 ; for 1 second
;
btfss PORTsw,swSet ; Set switch when time displayed ?
call RTCupdr
Secs 1 ; Time for another second
;
call DHTrd ; Read DHT11
call DspCT ; Display celsium degree
Secs 2 ; for 2 seconds
call DspHT ; Disuplay relative humidity
Secs 2 ; for 2 seconds
;
goto Mainp ; Contilue infinite loop
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC updating routine ;
; Display value for current ModeN ;
; If swMode pushed, display next unit to update ;
; If swTime pushed, increase value and display it ;
; If swSet pushed, update RTC (RTCwtr) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCupdr btfss PORTsw,swSet ; swSet still on?
goto $-1 ; then wait for off
movlw Modeyr ; set initial mode year
movwf ModeN
;
RTCudm movf ModeN,W ; Large loop on ModeN
brw
goto Mdsecr ; case ModeN=0
goto Mdminr ; case ModeN=1
goto Mdhrr ; case ModeN=2
goto Mddowr ; case ModeN=3
goto Mddayr ; case ModeN=4
goto Mdmonr ; case ModeN=5
goto Mdyrr ; case ModeN=6
;
; Macro used within this section
Mdsetup macro T7c,Rmax,Rmin
movlw T7c
movwf T7Chr
movlw Rmax
movwf RvMax
movlw Rmin
movwf RvMin
goto Mdnext
endm
;
; set up environment for update and display
Mdsecr Mdsetup Ch7S,secMax,secMin
Mdminr Mdsetup Ch7m,minMax,minMin
Mdhrr Mdsetup Ch7h,hrMax,hrMin
Mddowr Mdsetup Ch7w,dowMax,dowMin
Mddayr Mdsetup Ch7d,dayMax,dayMin
Mdmonr Mdsetup Ch7M,monMax,monMin
Mdyrr Mdsetup Ch7Y,yrMax,yrMin
;
Mdnext call Rdspr ; Display X=nn
btfss PORTsw,swTime ; Is Time pushed ?
goto Rinc ; Yes, goto Rinc
btfss PORTsw,swMode ; Is Mode pushed ?
goto Rnxtm ; Yes, goto Rnxtm
btfss PORTsw,swSet ; Is Set pushed ?
goto Rwrite ; Yes, goto Rwrite
goto Mdnext ; If no button, small loop for button
;
; Time pushed here
Rinc call Rincr ; Increase value in that mode
Mil100 2 ; 0.2 sec for increasing value
goto Mdnext ; return to loop for button
;
; Mode pushed here
Rnxtm btfss PORTsw,swMode ; Mode button still pushed
goto $-1 ; then wait for release
CalEO ModeN,0,Msmax ; If current ModeN=0 goto Msmax
decf ModeN,F ; set next mode
Rnxtme goto RTCudm ; and return to large loop for mode
;
Msmax movlw Modeyr ; get maximum mode
movwf ModeN ; and set it
goto RTCudm ; and return to large loop for mode
;
Rwrite btfss PORTsw,swSet ; Set button still on?
goto $-1 ; then wait for release
call RTCwtr ; and write to RTC
;
return ; exit from RTC updating routine
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Display value pointed by ModeN ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Rdspr movf T7Chr,W
movwf Dig1000
movlw Ch7Eq
movwf Dig100
;
movlw BCDsec ; Point BCD area top
movwf FSR1L ; set it to FSR1L
movf ModeN,W ; Get Mode number
addwf FSR1L,F ; Point current BCD area
swapf INDF1,W ; get high nibble to low in W
call TMser ; clear high nibble & edit
movwf Dig10 ; set it to Dig10
movf INDF1,W ; get low nibble to low
call TMser ; clear high nibble to low
movwf Dig1 ; set it to Dig1
;
call TMdspr
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Increase value pointed by ModeN ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Rincr movlw BCDsec ; Point BCD area top
movwf FSR1L ; set it to pointer
movf ModeN,W ; get ModeN to add
addwf FSR1L,F ; Point current BCD area
;
CabSO INDF1,RvMax,Rigo ;If smaller than max, goto Rigo
movf RvMin,W ; Else, get minimum value
movwf INDF1 ; and set it to INDF1 (BCD area)
return
;
Rigo movf INDF1,W ; Get BCD value
andlw H'0F' ; clear left nibble
movwf Bytel ; and set to Bytel
swapf INDF1,W ; Get BCD nibbles swapped
andlw H'0F' ; clear left nibble
movwf Byteh ; and set to Byteh
;
incf Bytel,F ; Bytel+1
CalSO Bytel,D'10',Rie ; If Bytel≦9,goto Rie
movlw D'16' ; Else increase digit 10
addwf INDF1,F ;
movlw H'F0' ; and clear digit 1
andwf INDF1,F
return
Rie incf INDF1,F ; Increase BCD value
return ; and return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Displaying Time routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Dsptime movf BCDmin,W ; get minute dig 1
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig1 ; set it to Digit 1
;
swapf BCDmin,W ; get minutes dig 10
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig10 ; set it to Digit 10
;
movf BCDhr,W ; get hour dig 1
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig100 ; set it to Digit 100
bsf Dig100,7 ; set colon after Digit 100
;
swapf BCDhr,W ; get hour dig 10
call TMser ; edit bit 0-3 value to 7 seg char
movwf Dig1000 ; set it to Digit 1000
;
call TMdspr ; show them to TM1637
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC reading routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCrdr clrf RTCmem ; set RTC memory addr 0
I2Csnd DS3231,RTCmem,1 ; send it to DS3231
Milli 1 ; wait for readiness (unnecessary?)
I2Crcv DS3231,RTCdata,7 ; receive 7 byte data from DS3231
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RTC writing routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTCwtr clrf RTCmem ; Set memory address zero
I2Csnd DS3231,RTCmem,8 ; Send data, with memory addr on top
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DHT11 Reading routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DHTrd movlw 5 ; Set # of DHT bytes 5
movwf Bytectr ; to Bytectr
;
movlw DHTrh ; Point top of DHT data input
movwf FSR0L ; Set it to INDF0
;
; Start signal
bcf PORTdht,DHT11 ; Set DHT-line L
;
Milli D'20' ; for 20mS
bsf PORTdht,DHT11 ; Set DHT-line H
Mic2 D'10' ; for 20 micro sec
;
;Header checking from DHT11
BANKSEL TRISdht ; Point tris bank
bsf TRISdht,DHT11 ; Set TRIS-dht input
clrf BSR ; Point bank 0
Mic ; wait 1 micro sec for ready
;
btfsc PORTdht,DHT11 ; Wait response 1/2 from DHT L
goto $-1 ; until L
Mic5 D'13' ; Wait 65 within 80 micS
;
btfss PORTdht,DHT11 ; Wait response 2/2 from DHT H
goto $-1 ; until H
Mic5 D'13' ; Wait 65 within 80 micS
;
btfsc PORTdht,DHT11 ; Wait Start (L 50 mic sec) from DHT
goto $-1
Mic5 D'6' ; When L, wait for 30 mic sec
;
; Read each byte from DHT11
DHbc movlw 8 ; Set # of bits = 8 in a byte of DHT
movwf Bitctr ; to Bitctr
;
DHbcl btfss PORTdht,DHT11 ; Wait Data signal H from DHT
goto $-1
Mic50 1 ; When H (1=70,0=27 micS), wait 50 micS
; Trigger ; *** for timing-validation use only ***
;
btfss PORTdht,DHT11 ; If still on then data is one, else zero
goto DHszero
;
DHsone bsf Sbyte,0 ; Set 1 to Sbyte bit 0
Mic5 D'4' ; Consume residual H 20 mic S of "1"
goto DHeck ; Goto Check end of one byte
;
DHszero bcf Sbyte,0 ; Set zero to Sbyte bit 0
DHeck decfsz Bitctr,F ; One byte (8 bits) end ?
goto DHnxtbi ; No, goto continue bit proc
;
DHbye movf Sbyte,W ; If one byte end, here
movwf INDF0 ; Set data to DHTdata entry
incf FSR0L,F ; Point next entry of DHTdata
;
decfsz Bytectr,F ; All bytes end?
goto DHbc ; If not end of bytes, next byte
goto DHcksr ; If end, checksum validation
;
DHnxtbi rlf Sbyte,F ; Bit continues. Shift left.
goto DHbcl ; and next bit checking
;
DHcksr equ $ ; Checksum validation, if needed
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of receive ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Change data line mode to ooutput
; Wait the last space ending
Mic2 D'40' ; Residual 28 mic sec space + alpha
; ; + 50 mic sec until pull-down end
BANKSEL LATdht ; Data line high when output mode
bsf LATdht,DHT11 ; Lat-DHT11 high
BANKSEL TRISdht ; Select tris bank
bcf TRISdht,DHT11 ; Set DHT11 output mode
clrf BSR ; Select bank 0
;
Mic ; Wait one micro Sec
bsf PORTdht,DHT11 ; Signal high
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Display Celsius to TM1637 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DspCT clrf Dig1000 ; Clear Dig1000
movf DHTt,W ; Get DHTt
movwf Dig100 ; set it to Dig100
;
DspCTc CalSO Dig100,D'10',CTnext
incf Dig1000,F ; carry over to 1000
movlw D'10' ; and subtract 10
subwf Dig100,F ; from Dig100
goto DspCTc ; repeat check
;
CTnext CalEO Dig1000,0,CTnxtg ; IF top zero goto CTnxtg
movf Dig1000,W
call TMser ; Convert Dig1000 to 7 seg pattern
movwf Dig1000
;
CTnxtg movf Dig100,W
call TMser ; Convert Dig100 to 7seg pattern
movwf Dig100
;
movlw H'63' ; Char Degree
movwf Dig10
movlw H'39' ; Char C
movwf Dig1
;
call TMdspr
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Display Humidity to TM1637 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DspHT clrf Dig1000 ; Clear Dig1000
movf DHTrh,W ; Get DHTrh
movwf Dig100 ; set it to Dig100
;
DspHTc CalSO Dig100,D'10',HTnext
incf Dig1000,F ; carry over to 1000
movlw D'10' ; and subtract 10
subwf Dig100,F ; from Dig100
goto DspHTc ; repeat check
;
HTnext CalEO Dig1000,0,HTnxtg ; IF top zero goto HTnxtg
movf Dig1000,W
call TMser ; Convert Dig1000 to 7 seg pattern
movwf Dig1000
;
HTnxtg movf Dig100,W
call TMser ; Convert Dig100 to 7seg pattern
movwf Dig100
;
movlw H'63' ; Char % 1/2
movwf Dig10
movlw H'5C' ; Char % 2/2
movwf Dig1
;
call TMdspr
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Send byte-string ;
; when called, ;
; I2C device adr in I2Cadr byte ;
; Data length in DataLen ;
; Data Addr in FSR0L (INDF0) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Csndr movf I2Cadr,W
movwf Sbyte
; rlf Sbyte,F ; shift leftt (if adr for Arduino)
bcf Sbyte,0 ; indicate write
;
I2Cstat ; Start I2C
call Sendr
Sdata movf INDF0,W ; Get a sending character
movwf Sbyte ; Set it to Sbyte
call Sendr ; Send it to the device
;
incf FSR0L,F ; point next char
decfsz DataLen,F ; Have all chars sent ?
goto Sdata ; No, loop
;
; Stop signal and return
I2Cstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Receive byte-string ;
; when called, ;
; I2C device adr in I2Cadr byte ;
; Data length in DataLen ;
; Data Addr in FSR0L (INDF0) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Crcvr equ $
I2Cstat ; Start I2C
movf I2Cadr,W ; Get I2C dev addr
movwf Sbyte ; Set it into Sbyte
; rlf Sbyte,F ; Shift left (if adr for Arduino)
bsf Sbyte,0 ; indicate read
call Sendr ; Send slave addr to read
;
I2Crbyt equ $
BANKSEL TRISI2C ;
bsf TRISI2C,Dl ; Set Dline input mode
clrf BSR ; Point Bank 0
;
movlw 8 ; Bits in a reciving byte
movwf Bitctr ; into loop counter
I2Crblp Mic2p5 2*Clkt ; Timing before raising clock
bsf PORTI2C,Cl ; Set clock high
Mic2p5 Clkt ; Timing after raising clock
;
btfsc PORTI2C,Dl
goto Rbith
; goto Rbitl
;
Rbitl bcf Sbyte,0 ; Clear bit 0
goto Rbitnxt ; and goto next
;
Rbith bsf Sbyte,0 ; Set bit 0
Rbitnxt Mic2 Clkq ; Timing after checking
bcf PORTI2C,Cl ; Set clock low
; Mic2p5 Clkt ; Timing after clock falling
decfsz Bitctr,F ; Still bits?
goto Rbcont ; Yes, continue
goto Rbend ; No, end of one byte
;
Rbcont rlf Sbyte,F ; Shit left
goto I2Crblp ; and goto loop
;
Rbend movf Sbyte,W ; Get received byte
movwf INDF0 ; Set it to INDF0
incf FSR0L,F ; increase index
decfsz DataLen,F ; DataLen-1
goto Sackr ; Send Ack and continue
goto Snackr ; Send Nack and stop
;
;Set Dl output mode and send Ack to conitinue
Sackr equ $
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
;
bcf PORTI2C,Dl ; Send Ack
Mic2 Clkq ; Timing after clock falling
bsf PORTI2C,Cl ; Show Ack
Mic2p5 2*Clkt
bcf PORTI2C,Cl ; Set clock low
Mic2 Clkq
bsf PORTI2C,Dl ; Return Dline to high
goto I2Crbyt ; Next byte process
;
;Set Dl output mode and send Nack
Snackr equ $
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
;
bsf PORTI2C,Dl ; Send Nack
Mic2 Clkq ; Timing after clock falling
bsf PORTI2C,Cl ; Show Nack
Mic2p5 2*Clkt
bcf PORTI2C,Cl ; Set clock low
Mic2p5 Clkt
I2Cstop ; and stop I2C once
Mic5 D'6' ; for 30 micro sec
;
I2Cstat ; then start I2C again
movf I2Cadr,W ; Get I2C dev addr
movwf Sbyte ; Set it into Sbyte
; rlf Sbyte,F ; Shift left (if adr for Arduino)
bcf Sbyte,0 ; indicate write
call Sendr ; Send it
;
I2Cstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Start signal routine ;
; when dataline mode is output ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Cstar bcf PORTI2C,Dl ; set SDA low
Mic2 Clkq
bcf PORTI2C,Cl ; set SCL low
Mic2p5 2*Clkt
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C Stop signal routine ;
; when dataline mode is output ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I2Cstpr bcf PORTI2C,Cl ; set SCL low
Mic2 Clkq
bcf PORTI2C,Dl ; set SDA low
Mic2p5 2*Clkt
bsf PORTI2C,Cl ; Clock line rasing
Mic2p5 Clkt
bsf PORTI2C,Dl ; Data line rasing
Mic2 Clkq
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I2C One-byte sending routine ;
; with data in Sbyte ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Sendr movlw 8 ; Set bit count in a byte
movwf Bitctr ; into loop counter
;
Sloop btfsc Sbyte,7 ; Check top bit of Sbyte
goto Slpdh ;
bcf PORTI2C,Dl ; If bit low then Data L
goto Slpnxt
Slpdh bsf PORTI2C,Dl ; If bit high then Data H
;
Slpnxt Mic2 Clkq
bsf PORTI2C,Cl ; Show bit
Mic2p5 2*Clkt
bcf PORTI2C,Cl ;
Mic2 Clkq
;
rlf Sbyte,F ; Shift left
decfsz Bitctr,F ; All bits done?
goto Sloop ; No, loop within a byte
;
;Receive Ack
; set data line input mode
BANKSEL TRISI2C ;
bsf TRISI2C,Dl ; Set Dline input mode
clrf BSR ; Point Bank 0
;
Mic2 Clkq ; wait for Ack timing
bsf PORTI2C,Cl ; Clock H for Acq confirmation
Mic2p5 2*Clkt ;
bcf PORTI2C,Cl ; Cl L for Dl release by slave
Mic2p5 2*Clkt
;
; Set Data line output
BANKSEL LATI2C ; Data line high when output mode
bsf LATI2C,Dl ; Lat-Dl on
BANKSEL TRISI2C ;
bcf TRISI2C,Dl ; Set Dl output mode
clrf BSR ; Point Bank 0
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 support routines ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 display brightness setting ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IniTMr equ $
; TM brightness initial setting ;
; H'88'+ duty ratio:
; H'00'=1/16, H'01'=2/16, H'02'=4/16, H'03'=10/16
; H'04'=11/16, H'05'=12/16, H'06'=13/16, H'07'=14/16
movlw H'88'+H'02' ; Initial brightness value
movwf Sbyte ; Set to Sbyte
TMstart
TMsendB Sbyte
TMstop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM 1637 Char to 7 segment editing routine ;
; replaceubg Char in W with 7 seg in W ;
; 7 seg format is B'xgfe-dcba' ;
; if colon required,IOR H'80' to Dig100 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMser andlw H'0F' ; Prevent wild branch
brw
Case0 retlw H'3F'
Case1 retlw H'06'
Case2 retlw H'5B'
Case3 retlw H'4F'
Case4 retlw H'66'
Case5 retlw H'6D'
Case6 retlw H'7D'
Case7 retlw H'07'
Case8 retlw H'7F'
Case9 retlw H'6F'
CaseA retlw H'77' ; A
CaseB retlw H'7C' ; b
CaseC retlw H'39' ; C
CaseD retlw H'5E' ; d
CaseE retlw H'79' ; E
CaseF retlw H'71' ; F
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 4digits displaying routine ;
; using Dig1000 to Dig1 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMdspr movlw Dig1000 ; Point Byte0 address
movwf FSR0L ; set it to use INDF0
movlw 4 ; Set four digits
movwf Bytectr ; to Byte counter
;
TMstart
TMsendL H'40' ;
TMstop ;
;
TMstart
TMsendL H'C0' ; Set addr zero of TM
;
TMdspl movf INDF0,W ; Get byte contents
movwf Sbyte ; Set them to Sbyte
TMsendB Sbyte ;
incf FSR0L,F ; point next byte
decfsz Bytectr,F ; Check if all done
goto TMdspl ; No. loop
;
TMstop ; When all sent, Stop
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Start sending routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMstrtr nop
BANKSEL TRIStm
bsf LATtm,Dio ; Dio high beforhand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; return to Bank0
;
bsf PORTtm,Dio ; Dio high
Mic2 Clkq
bsf PORTtm,Clk ; Clk high
Mic2 Clkq
bcf PORTtm,Dio ; Dio low
Mic2 Clkq
bcf PORTtm,Clk ; Clk low
Mic2 Clkq
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Stop sending routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMstopr nop
BANKSEL TRIStm
bcf LATtm,Dio ; Dio low beforehand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; Return to Bank0
;
Mic2 Clkq
bsf PORTtm,Clk ; Clk high
Mic2 Clkq
bsf PORTtm,Dio ; Data high
Mic2p5 D'10'
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TM1637 Byte sending routine ;
; called by TMsendB with Sbyte or ;
; TMsendL with value in W reg ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TMsndLr movwf Sbyte ; Set sending byte
;
TMsndBr movlw 8 ; Set bit count
movwf Bitctr ; into loop counter
;
Tloop btfsc Sbyte,0 ; Check LSb for little-endian-
goto Tlpdh ;
bcf PORTtm,Dio ; If bit low then Data L
goto Tlpnxt
;
Tlpdh bsf PORTtm,Dio ; If bit high then Data H
Tlpnxt Mic2 Clkq;
bsf PORTtm,Clk ; Clock high
Mic2p5 2*Clkt ; (5 micro sec if standard)
bcf PORTtm,Clk ; Clock low
Mic2 Clkq
rrf Sbyte,F ; Shift right for little-endian
decfsz Bitctr,F
goto Tloop
;
; Receiving Ack ;
BANKSEL TRIStm
bsf TRIStm,Dio ; Set Dio input mode
clrf BSR ; return to Bank0
Mic2p5 Clkt ; Wait for Ack=low
bsf PORTtm,Clk ; Clk high for Ack confirmation
Mic2p5 2*Clkt ; (5 micro sec if standard)
bcf PORTtm,Clk ; Clk L for Data release to H by Slave
Mic2p5 Clkt ; Wait for Dio set H
;
BANKSEL TRIStm
bsf LATtm,Dio ; Dio high beforhand
bcf TRIStm,Dio ; Set Dio output
clrf BSR ; return to Bank0
Mic2p5 5 ; Enough time for TM1637 after Ack
return ;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Timing subrooutines for general purposes ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.0 micro S x n (Mic2) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic2r movwf Mic25c ; + Wset + call = 1 micro sec
;
Mic2l decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic2li ; else go out (2nd time 1.75 mic sec)
return
;
Mic2li goto $+1 ; (2nd time 2.25 mic sec)
nop ; (2nd time 2.5 mic sec)
goto Mic2l ; go back (2nd time 3 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make 2.5 micro S x n (Mic2p5) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mic25r movwf Mic25c ; + Wset + call = 1 micro sec
nop ; 1.25 micro sec
;
Mic25l nop ; 1.5 micro sec (2nd time 4 mic sec)
decfsz Mic25c,F ; If exhausted, 1 micro S hereafter
goto Mic25li ; else go out (2nd time 2.25 mic sec)
return
;
Mic25li Mic ; (2nd time 3.25 mic sec)
goto Mic25l ; go back (2nd time 3.75 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 50 Microseconds x n Mic50 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Mic50r movwf Mic50c ; set how many 50 microsec (1 micro sec to here)
nop ; 1.25 micro sec up to here
;
Mic50l Mic2p5 D'19' ; + 47.5 = 48.75 mic sec (2nd time 98.75 mic sec)
nop ; + 0.25 = 49 micro sec (2nd time 99 mic sec)
;
decfsz Mic50c,F ; If exhausted then 1 mic S hereafter
goto Mic50li ; else go out (2nd time 49.75 mic sec)
return
;
;
Mic50li Mic ; (2nd time 50.75 mic sec)
goto Mic50l ; go back (2nd time 51.25 mic sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Milliseconds x n (Milli) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Millir movwf Millic ; set how many 1 mil sec (1 mic S up to here)
nop ; 1.25 micro sec
;
Millil Mic50 D'19' ; + 50 mic x 19 = 951.25 mic S (2nd, 1951.25)
Mic2p5 D'19' ; + 47.5 mic = 998.75 micro S (2nd, 1998.75)
nop ; +0.25 mic = 999 micro sec (2nd, 1999)
;
decfsz Millic,F ; If exhausted then 1 micro sec hereafter
goto Millili ; else go out (2nd, 999.75 mic S)
return
;
Millili Mic ; (2nd time 1000.75 mic S)
goto Millil ; go back (2nd time 1001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 100 Milliseconds x n (Mil100);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Mil100r movwf Mil100c ;set how many 100 ms(1 micr sec up to here)
nop ; 1.25 micro sec
;
Milhl Milli D'99' ;+1ms x 99 = 99001.25 micS (2nd,199001.25mic)
Mic50 D'19' ; + 950 mic = 99951.25 micS(2nd.199951.25mic)
Mic2p5 D'19' ; + 47.5 mic = 99998.75micS(2nd,199998.75mic)
nop ; + 0.25 mic = 99999 mic S (2nd,199999 micS)
;
decfsz Mil100c,F ; If exhausted then 1 micro sec hereafter
goto Milhli ; else go out (2nd time, 99999.75 mic S)
return
;
Milhli Mic ; (2nd time, 100000.75 mic S)
goto Milhl ; (2nd time, 100001.25 mic S)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Seconds x n (Secs) ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Secsr movwf Secsc ; set how many sec ( 1 mic sec up to here)
nop ; 1.25 micro sec
;
Secsl Mil100 D'9' ;
Milli D'99' ; + 999 milli sec = 999001.25 micro sec
;
Mic50 D'19' ; + 950 mic = 999951.25 micro sec
Mic2p5 D'19' ; + 47.5 mic = 999998.75 micro sec
nop ; + 0.25 mic = 999999 micro sec
;
decfsz Secsc,F ; If exhausted then 1 micro sec hereafter
goto Secsli ; else, go out
return
;
Secsli Mic
goto Secsl ; (Second time, Sec + 1.25 micro sec)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Minutes x n (Mins) ;
; Overhead ignored, that is only ;
; 751.25 Mic S even when 100 Min ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Minsr movwf Minsc ;set how many minutes from parameter
;
Minsl Secs D'60' ; 1 Seconds x 60
decfsz Minsc,F
goto Minsl
return
;
space
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; User debug subroutine ;
; Show bit 7 to 0 ;
; of specified byte ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Udbgr clrf BSR ; Set Bank=0
movwf DmpA ; move data to Dmpa
;
btfss PORTdbg,LED ; Check if LED=on (on=High)
goto UdbLoff ; if LED=off(Low), skip saving process
bsf Flags,LEDpH ; Save LEDon status
LEDoff ; and off LED
Mil100 D'10' ; wait for a second in case LED has been on
;
UdbLoff movlw Dmp8V ; set counter 8
movwf Dmp8C ; to Dmp8C
;
Udblp Ublink Debugb ; Blink for Debug = 8 times
btfsc DmpA,7 ; check top bit 7
goto UdbOn ; if on then to UdbOn
goto UdbOff ; if off then to UdbOff
;
UdbOn LEDon
Mil100 D'30' ;
goto Udbeck
;
UdbOff LEDoff
Mil100 D'30' ;
; goto Udbeck
;
Udbeck decfsz Dmp8C,F
goto Udbnext
goto Udbend
;
Udbnext rlf DmpA,F
goto Udblp
;
Udbend Ublink Debugb ; end blinking and
Mil100 D'100' ; blank for 10 seconds to write down
;
btfss Flags,LEDpH ; Check if LED was on
goto Udbret ; no, goto return
LEDon ; if it was on, then on again
bcf Flags,LEDpH ; Clear LED save flag
;
Udbret return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Blinking to show debug or abend ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ublinkr movwf BlinkC
Ublinkl LEDon ; LED on
Milli D'30' ; for 30ms
LEDoff ; LED off
Milli D'200' ; for 200ms
;
decfsz BlinkC,F
goto Ublinkl
return
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Abend routine ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Uabendr clrf BSR
movwf Abendn ; Set Uabend number
;
Ublink Abendb ; Blink 25 times
Udebug Abendn ; Show Abend number
goto $
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of program ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end