2014年11月02日 04:03
loop232:具体的な挙動は次のようになる。
movlw 0xF8
addwf GPIO,W ;0xF8を足すことでGPIO[3]をCに入れる
movlw 1<<TXPIN
rrf dat232,F ;ローテートでCをバッファに、バッファの反対端をCに
btfsc STATUS,C
xorwf GPIO ;送信データに応じてGPIOの送信ピンをトグル
decfsz cnt232
goto loop232
getmonthattr:
addwf PCL,F
dt .95, .28, .63, .94, .47, .78,
dt .31,.111, .30, .95,.126, .79,
dt .31,.125
list p=10F200
#include p10f200.inc
radix dec
__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF
cblock 0x10
dat232
yearh, yearl, month
cnt, dowcnt, daycnt, cnt232
day
temp
endc
;ピン
#define TXPIN 0
;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 dat232,W
movwf yearh ;*1
addwf yearh,F ;*2
call rx232
movf dat232,W
addwf yearh,F
;年下位 = 10c+d
call rx232
movf dat232,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 dat232,W
addwf yearl,F
;"M?>"
call newline
movlw 'M'
call tx232
movlw '?'
call tx232
movlw '>'
call tx232
;月2桁受信: ef
call rx232
movf dat232,W
andlw 0x01 ;1っぽければ10をセット
btfss STATUS,Z
movlw .10
movwf month
call rx232
movf dat232,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 getmonthattr
addwf doworg,F
andlw 0x0F
iorlw 0x10
movwf daycnt
;mod7を求めるが、簡略化のため、
;7を加算していきキャリーが出た時点で終了する。
;256%7=4だけずれるのでデータ側で補正済
movlw .7
mod7loop:
addwf doworg,F
btfss STATUS,C
goto mod7loop
;ループ用に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
;下位4bitが「当該月の日数」であり、
;全体が「基準の年の当該月1日の曜日+4」とmod7で等しいような数を返す
getmonthattr:
addwf PCL,F
dt .95, .28, .63, .94, .47, .78,
dt .31,.111, .30, .95,.126, .79,
dt .31,.125
;RS232Cで1バイト受信し、下位ニブルのみ返す
rx232:
btfss GPIO,3 ;rx start [0,3)
goto $-1
clrf dat232
goto $+1
goto f
;RS232Cで1バイト送信する
tx232:
movwf dat232
bcf STATUS,C
rlf dat232,W
xorwf dat232,F
bsf GPIO,TXPIN ;tx start 0
f:
bsf cnt232,3
loop232:
movlw 0xF8
addwf GPIO,W ;read [9,12)+9n
movlw 1