Chipping away at some code and I think I have finally identified the segment that deals with correlating the unit and system clocks.
However, I'm having a bit of difficulty visualizing how the time is calculated and stored. I'm not entirely sure if it is just a 7-day rollover or if it is some offset beyond 1/1/1980.
I'm hoping that someone a bit more familiar with assembly-level math and 6801 / HC11 assembly can see what I cannot.
If I can get a better understanding of what's going on here, it will help "unlock" some more of the code for me.
Variables:
NVR_46 - NVR_48: local time register
NVR_49 - NVR_4B: system time register
SRM_C0 - SRM_C2: likely a scratchpad area
SRM_D1 - SRM_D2: time difference temp register?
timeDiff: Time difference (for setting time sync flag and calculating time on battery)
app_DAB
LDX #NVR_49
JSR sub_687
STD SRM_D1
LDX #NVR_46
JSR sub_687
SUBD SRM_D1
BCC app_DC0 ; higher or same?
ADDD #$9D80
app_DC0
STD SRM_D1
LDAA NVR_47
CMPA NVR_4A
BEQ app_DDE
LDX #$0008
CPX SRM_D1
BLT app_DDE
BCS app_DDE ; lower?
STAB timeDiff
(continued)
app_DDE
(continued)
; Some type of time calculation
; Accumulators A / B hold result (16-bit value in Accumulator D)
sub_687 LDAB $02,X
LDAA #$90
MUL
ADDB $01,X
ADCA #$00
STAA SRM_C0
LDAA #$14
MUL
STD SRM_C1
LDAA SRM_C0
LDAB #$14
MUL
TBA
CLRB
ADDD SRM_C1
ADDB $00,X
ADCA #$00
RTS
Disclaimer: AFAIK I have zero experience with this architecture.
Procedure sub_687 seems to be doing:2880 * t[2] + 20 * t[0] + t[1]
… where t is the i-th byte in an NVR_x triplet. Yes, the order is “2, 0, 1”, not “2, 1, 0”. The operation is split into multiplying by 144 (8-bit · 8-bit → 16-bit) and then by 20 (16-bit · 8-bit → 16-bit). Doing 16-bit multiplication seems to be the cause of all the temporary values shuffling: it’s split into two 8-bit multiplications.
Unless there is some deeper meaning behind these values,(1) it may be packing values into a single 16-bit number, so they can be cheaply compared in their lexicographical order. If that is true, the ranges would be limited to:- [0, 19] for t[1]
- [0, 143] for t[0]
- [0, 22] for t[2]
This way the above expression would fit the values into 16 bits without collisions. Does any number, which fits in these ranges (likely smaller than any of them) make any sense in the context of how these triplets are used elsewhere?
The only thing, which pops up, is 2880, which is twice 1440 (the number of minutes in a day). So, hypothetically pair (t[0], t[1]) may be storing half-minutes of a day in some convoluted little-endian format, and t[2] counts days. t[0] may be 10-minute periods of the day, and t[1] half-minutes in the current 10-minute period.
0x9D80 is exactly the number of half-minutes in 14 days. Also exactly the number of hours in 240 weeks, but that is less likely. I have no idea, why it would be added to local time in case system time is greater.
0x0008 may be a number chosen to fit the alredy existing values, without any meaning by itself. But if the half-minutes hypothesis is right, it would indicate 4 minutes. Do 4 minutes manifest themselves anywhere?
(1) Due to a mistake I already managed to discover subsequence (positions 54–68) of OEIS A025642 in your code. And 0x9D80 is 8!. So who knows? ;)
Definitely on the right track... here's one routine that makes use of the above:
; Subroutine
; First call loads X register with the pointer to LMT time (previous NVR_46)
; Second call loads X register with the pointer to system time (previous NVR_49)
; Other variables:
; SRM_D1 - 8-bit value
; SRM_D2 - 8-bit value
; Outside of this routine, SRM_D1 and SRM_D2 are handled as a single 16-bit value
; SRM_D4 - 16 bit value - probably load profile-related (only other use is routine that works with load profile data)
; NVR_4F - may be schedule? Code below suggests addresses $0C4F - $0C56 is used for this
; NVR_59 / NVR_5A - 16 bit value, no other calls from LMT ROM - is likely written by absent DCT ROM
; There is a routine that wipes most of upper RAM ($0C28 to $0CFC aka NVR_28 to NVR_FC), so assume NVR_59 & NVR_5A are 0 for now
sub_6A5 LDAA flgTosSch ; is schedule flag clear (i.e., active)
ORAA flgTmSync ; is time sync flag clear (i.e., LMT is synced to system time)
BEQ sub_6B1
CLR outBits ; No. Clear PIA output buffer and exit
RTS
; Unit is in sync with system time and schedule is active. Continue.
sub_6B1 LDAA $02,X ; Current day
PSHX
INCA
ANDA #$0E
STAA SRM_D1
LDD NVR_59
DEC SRM_D1
sub_6BF DEC SRM_D1
BLE sub_6C7
LSRD
BRA sub_6BF
sub_6C7 LDAA #$00
ANDB #$03
BEQ sub_6D2
CMPB #$01
BNE sub_71D
LDAA #$05
sub_6D2 STAA SRM_D2
LDAB #$04
STAB SRM_D1
LDAB #$00
PULX
LDAA $02,X ; Current day
ANDA #$01
BEQ sub_6E2
LDAB #$90
sub_6E2 LDAA #$00
ADDD #$0090
SUBB $01,X ; Minutes in current interval
SBCA #$00
STD SRM_D4
PSHX
LDX #NVR_4F
LDAB SRM_D2
ABX
LDD SRM_D4
PSHA
PSHB
LDAA #$00
LDAB $00,X
STD SRM_D4
PULB
PULA
SUBD SRM_D4
BLT sub_722
sub_6F7 INX
DEC SRM_D1
BEQ sub_703
STD SRM_D4
LDD SRM_D4
PSHA
PSHB
LDAA #$00
LDAB $00,X
STD SRM_D4
PULB
PULA
SUBD SRM_D4
BGE sub_6F7
sub_703 LDX #NVR_4F
LDAB SRM_D2
ADDB #$04
ABX
LDAA $00,X
LDAB SRM_D1
BEQ sub_716
sub_711 ASRA
ASRA
DECB
BNE sub_711
sub_716 ANDA #$03
CMPA #$03
BNE sub_71D
LDAA #$00
sub_71D STAA outBits ; Set TOU rate: 0 = base, 1 = lower peak, 2 = upper peak
PULX
RTS
sub_722 PULX
LDAB $02,X ; Current day
INCB
BITB #$01
BNE sub_72B
INCB
sub_72B CMPB #$0F
BNE sub_731
LDAB #$01
sub_731 LDAA #$01
STD tmSysMin ; B register: tmSysDay
RTS