2014年10月30日 01:12
;### PIC10F200 Calendar###
;by Ikadzuchi (@Pleist)
list p=10F200
#include p10f200.inc
radix dec
__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF
cblock 0x10
txdat, rxdat
yearh, yearl, month
cnt, dowcnt, daycnt, cnt232
day
temp
endc
;ピン
#define TXPIN 0
#define RXPIN 3
org 0
init:
movwf OSCCAL ;クロック補正値セット
movlw b'11001000'
;設定データ。プルアップOFF、他Don'tCare
;ちょうど下位3bitがDon'tCareなのでI/O設定と共用
clrf GPIO ;出力ピンを全Lowに
tris GPIO ;I/Oモード設定
option ;設定
main:
clrf cnt
clrf cnt232
;"Y?>"
movlw 'Y'
call tx232
movlw '?'
call tx232
movlw '>'
call tx232
;年4桁受信: abcd
;年上位 = 10a+b ≡ 2a+b
call rx232
movf rxdat,W
movwf yearh ;*1
addwf yearh,F ;*2
call rx232
movf rxdat,W
addwf yearh,F
;年下位 = 10c+d
call rx232
movf rxdat,W
movwf yearl ;*1
bcf STATUS,C
rlf yearl,F ;*2
rlf yearl,F ;*4
addwf yearl,F ;*5
rlf yearl,F ;*10
call rx232
movf rxdat,W
addwf yearl,F
;"M?>"
call newline
movlw 'M'
call tx232
movlw '?'
call tx232
movlw '>'
call tx232
;月2桁受信: ef
call rx232
movf rxdat,W
andlw 0x01 ;1っぽければ10をセット
btfss STATUS,Z
movlw .10
movwf month
call rx232
movf rxdat,W
andlw 0x0F
addwf month,F ;C0
;閏年判定
movf yearl,W ;年下位を取り、
btfsc STATUS,Z ;0なら
movf yearh,W ;年上位を取り、
andlw 0x03 ;下位2bitが
btfss STATUS,Z ;0でなければ
goto notleap ;平年。
;閏年1,2月を13,14月扱い
movlw .3
subwf month,W
movlw .12
btfss STATUS,C
addwf month,F
notleap:
;年ごとの曜日の基準を算出
;年下位 + 年下位/4 + (年上位%4)*2
rrf yearl,W
movwf temp
rrf temp,W
andlw 0x3F
addwf yearl,F
rlf yearh,W
andlw 0x06
subwf yearl,F
#define doworg yearl ;名前変更: DoW origin
;当月日数を取得
decf month,W
call getdaysinmonth
movwf daycnt
;当月の曜日の差分を取得し基準に足す
decf month,W
call getfirstdayinmonth
addwf doworg,F
;%=7
movlw .7
mod7loop:
subwf doworg,F
btfsc STATUS,C
goto mod7loop
addwf doworg,F
;ループ用にNと(6-N)を生成、コードの都合上+1
movlw .8
movwf dowcnt
incf doworg,W
subwf dowcnt
movwf cnt
call newline
;月初めの日まで空白で埋める
goto dayadjstart
dayadjloop:
movlw ' '
call tx232
movlw ' '
call tx232
movlw ' '
call tx232
dayadjstart:
decfsz cnt,F
goto dayadjloop
clrf day
dayoutloop:
;表示用日(BCD)を++
movlw .7
addwf day,F
movlw .6
btfss STATUS,DC
subwf day,F
;1日分の表示
movlw ' '
call tx232
swapf day,W
andlw 0x0F
btfsc STATUS,Z
movlw ' '
btfss STATUS,Z
iorlw 0x30
call tx232
movf day,W
andlw 0x0F
iorlw 0x30
call tx232
decf daycnt,F
btfsc STATUS,Z
goto break ;1月分出力完了で抜ける
decfsz dowcnt,F
goto dayoutloop ;日ループ
movlw .7
movwf dowcnt
call newline
goto dayoutloop ;週ループ
break:
call newline
goto main
;### subroutine ###
;改行を出力
newline:
movlw '\r'
call tx232
movlw '\n'
call tx232
retlw 0
;当該月の日数を返す
getdaysinmonth:
addwf PCL,F
dt .31, .28, .31, .30, .31, .30 ;1~12月
dt .31, .31, .30, .31, .30, .31
dt .31, .29 ;閏年1,2月
#define ADJ .7 ;負にならないよう補正するため
;基準の年の当該月1日の曜日を返す
getfirstdayinmonth:
addwf PCL,F
dt 0+ADJ, 3+ADJ, 3+ADJ, 6+ADJ, 1+ADJ, 4+ADJ ;1~12月
dt 6+ADJ, 2+ADJ, 5+ADJ, 0+ADJ, 3+ADJ, 5+ADJ
dt 6+ADJ, 2+ADJ ;閏年1,2月
;RS232Cで1バイト送信する
tx232:
movwf txdat
bsf GPIO,TXPIN ;start 0
bsf cnt232,3
tx232loop:
rrf txdat,F
movf GPIO,W
andlw ~(1