;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; File Name    : wlddef.asm
; Purpose      : World Time Application Default State Manager
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;DO NOT MODIFY THE FOLLOWING SUBROUTINE DEFINITION;;;;;;;;;;;;;;;;;

                IF @DEF('SUBROUTINE')
                    UNDEF SUBROUTINE
                ENDIF
                DEFINE  SUBROUTINE      "'wlddef'"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Module Name : wldDefaultStateManager
; Description : World Time Application Default State Manager.
; Assumptions : Display is cleared on first time entry into the state.
; Input(s)    : CORECurrentEvent  - system event to be processed
;               COREEventArgument - event extra information
; Output(s)   : None
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                GLOBAL  wldDefaultStateManager

wldDefaultStateManager:

                ld      A, [CORECurrentEvent]

                ; Check if display update event.
                cp      A, #TOD_DISPLAYUPDATETODRES
                jr      Z, wldProcessBlinkingColon

                ; Check if state entry event.
                cp      A, #WLD_STATEENTRY
                jr      Z, wldDefaultStateStateEntryEvent

                ; Check if mode depress event.
                cp      A, #WLD_MODEDEPRESS
                jr      Z, wldDefaultStateModeDepressEvent

                ; Check if crown set event.
                cp      A, #WLD_CROWNSET
                jr      Z, wldDefaultPulledCrownEvent

                ; Check if user selected the next city with wraparound
                cp      A, #WLD_NEXTCITY
                jr      Z, wldDefaultSelectNextCity

                ; Check if user selected the previous city with wraparound
                cp      A, #WLD_PREVIOUSCITY
                jr      Z, wldDefaultSelectPreviousCity

                ;TODO: Add more events detection here
                ;There are more events, add your own as needed

                ret


                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; EVENT HANDLERS
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



wldDefaultPulledCrownEvent:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; CROWN SET
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ld      B, #WLDYOUROCKSETSTATE
                CORE_REQ_STATE_CHANGE
                ret


wldDefaultStateModeDepressEvent:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; MODE DEPRESS
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;This is default to go to the next mode
                CORE_REQ_MODE_CHANGE_NEXT
                ret


wldDefaultStateStateEntryEvent:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; STATE ENTRY
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ; autoreturn since the scrolling will kill the battery
                CORE_SET_AUTORETURN

				; allow on the mode and ring events to be passed to the application for processing
				CORE_ALLOW_KEYS (bCOREModeSwitch|bCORECWSwitch|bCORECCWSwitch)

wldLoadNewCityAndComputeDateAndTime:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ; Read the current city record
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ; Setup the number of records stored in the database
                ld      HL, [CORECurrentADDAddress]
                ld      [DBExternalMemoryAddress], HL
                DB_OPEN_FILE
                ld      HL, [DBNumberOfRecords]
                ld      [WLDNumberOfRecords], HL
                DB_CLOSE_FILE

                ; read in the current city record
                car     wldReadCurrentCityRecord

                ; display city name with scrolling
                ld      IY, #WLDCityName
                LCD_SCROLL_RAM_OR_ROM_MSG_MAIN_DM_LINE2 EVENT_OFF


                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ; expand current city GMT code into BCD hour and minute with sign
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ; compensate for GMT.  Reformat the GMT code if nescessary
                ld      HL, #WLDCityGMTCode
                car     wldReformatGMTCode

                ; expand hour
                ld      A, [WLDCityGMTCode]
                and     A, #WLD_HOURMASK
                srl     A
                srl     A
                ld      L, A
                UTL_CONVERT_HEX_TO_2DIGIT_BCD
                ld      [WLDCityHourOffsetBCD], A

                ; expand sign
                ld      A, [WLDCityGMTCode]
                and     A, #WLD_SIGNMASK
                ld      [WLDCityHourSign], A

                ; expand minute
                ld      A, #0
                ld      B, [WLDCityGMTCode]
                and     B, #WLD_MINUTEMASK
                cp      B, #0
                jr      Z, wldgmtminuteokay

                UTL_DECIMAL_MATH_MODE

wldgmtminuteloop:
                add     A, #015H
                djr     NZ, wldgmtminuteloop
wldgmtminuteokay:

                UTL_BINARY_MATH_MODE
                ld      [WLDCityMinuteOffsetBCD], A

                ; Enable display event request from tod resource.
                ld      A, [COREPTZIndex]
                KTOD_ENABLE_DISP_UPD_SEC_EVENT



wldUpdateCityTimeAndDate:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; Compute the city time and date
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ; get PTZ time and date structure into work buffer
                ld      A,  [COREPTZIndex]
                ld      IY, #WLDCityTimeMinute
                KTOD_COPY_TIME_MIN_TO_DOW_FROM_RESOURCE

                ; get PTZ GMT code
                ld      A, [COREPTZIndex]
                ld      L, #(TODTZIDOFFSET+1)
                mlt
                add     HL, #TODTZ1ID
                ld      A, [HL]
                ld      [WLDPTZGMTCode], A

                ; expand PTZ GMT code into BCD hour and minute with sign

                ; compensate for GMT.  Reformat the GMT code if nescessary
                ld      HL, #WLDPTZGMTCode
                car     wldReformatGMTCode

                ; expand hour
                ld      A, [WLDPTZGMTCode]
                and     A, #WLD_HOURMASK
                srl     A
                srl     A
                ld      L, A
                UTL_CONVERT_HEX_TO_2DIGIT_BCD
                ld      [WLDPTZHourOffsetBCD], A

                ; expand sign
                ld      A, [WLDPTZGMTCode]
                and     A, #WLD_SIGNMASK
                ld      [WLDPTZHourSign], A

                ; expand minute
                ld      A, #0
                ld      B, [WLDPTZGMTCode]
                and     B, #WLD_MINUTEMASK
                cp      B, #0
                jr      Z, wldgmtminuteokay2

                UTL_DECIMAL_MATH_MODE

wldgmtminuteloop2:
                add     A, #015H
                djr     NZ, wldgmtminuteloop2

wldgmtminuteokay2:

                UTL_BINARY_MATH_MODE
                ld      [WLDPTZMinuteOffsetBCD], A

                ; compute the GMT time 
                ld      HL,   #WLDPTZHourSign
                xor     [HL], #WLD_SIGNMASK             ; reverse sign so we can compute the GMT time
                car     wldIncorporateOffsetIntoTimeStructure
                xor     [HL], #WLD_SIGNMASK             ; restore sign


                ; compute the city time
                ld      HL,   #WLDCityHourSign
                car     wldIncorporateOffsetIntoTimeStructure

                ; display city hour minute data
                ld      HL, #WLDCityTimeMinute
                UTL_DISPLAY_HR_MIN_DATA_L1


				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; Display city DOW in upper dot matrix
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

				ld 		A, [WLDCityTimeDOW]
				UTL_DISPLAY_DAY_OF_WEEK				

				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; display month and date in segment region using primary time zone display format
				;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                
                ; Get the TZ display format and mask bits 0 & 1.  
                ;   This contains the date format.
                ld      B, [COREPTZFormat]
                and     B, #TODMASKDATEFORMAT

                ; Check the date format.
                cp      B, #TODDDMMYY
                jr      NZ, wldDisplayMDYorYMD

                ;--------------------------------------------------------------
                ; D-M-Y is the display format.
                ;--------------------------------------------------------------

                ; Display dot between date and month.
                LCD_UPD_PER2_FLAG ON
            
                ; Display date at segment 34.
                ld      A, [WLDCityTimeDate]
                car     wldDisplayDualDigitAtSeg34
                
                ; Display month at segment 56.
                ld      A, [WLDCityTimeMonth]

wldDisplayDualDigitAtSeg56:

                ld      IX, #LCDSEGDIGIT5
                LCD_DISP_2DIG_SEG_DATA_NO_ZERO_SUP
                ret 


wldDisplayMDYorYMD:

                ;--------------------------------------------------------------
                ; M-D-Y or Y-M-D is the display format.
                ;--------------------------------------------------------------

                ; Display dash between month and date.
                LCD_UPD_DASH2_FLAG ON

                ; Display date at segment 56.
                ld      A, [WLDCityTimeDate]
                car     wldDisplayDualDigitAtSeg56

                ; Display month at segment 34.
                ld      A, [WLDCityTimeMonth]

wldDisplayDualDigitAtSeg34:

                ld      IX, #LCDSEGDIGIT3
                LCD_DISP_2DIG_SEG_DATA_SUP_ZERO_MSD
                ret

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


wldProcessBlinkingColon:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;
                ; UPDATE TIME ON MINUTE ROLLOVER
                ;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;check for the update bits.  if minute update, then update minute...
                ld      A, [COREPTZIndex]
                KTOD_GET_UPDATE_FLAGS
                bit     A, #bKTODMinuteUpd
                jr      NZ, wldUpdateCityTimeAndDate
                ret


                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wldDefaultSelectNextCity:

                ; get current record number
                ld      IX, [CORECurrentASDAddress]
                ld      BA, [IX]

                ; get maximum number of records in the database
                ld      HL, [WLDNumberOfRecords]

                ; check if the next record number is valid, else, do a wraparound
                inc     BA
                cp      BA, HL
                jr      C, wldRecordIsOkay

                ; wraparound back to record 0
                ld      BA, #0000H

wldRecordIsOkay:

                ; store the new record to display
                ld      [IX], BA
                jr      wldLoadNewCityAndComputeDateAndTime



                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wldDefaultSelectPreviousCity:

                ; get current record number
                ld      IX, [CORECurrentASDAddress]
                ld      BA, [IX]

                ; get maximum number of records in the database
                ld      HL, [WLDNumberOfRecords]

                ; check if the next record number is valid, else, do a wraparound
                cp      BA, #0000H
                jr      NZ, wldRecordNot0

                ; get the maximum number of records
                ld      BA, HL

wldRecordNot0:

                ; compute the new record number
                dec     BA
                jr      wldRecordIsOkay
