; ***************************************************************************
; copyright   : (C) 2023 by Martin Preuss
; email       : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome".                              *
; * Please see toplevel file COPYING of that project for license details.   *
; ***************************************************************************


; ***************************************************************************
; data in SRAM

.dseg


#ifdef MODULES_LED
  ledA3Sram:   .byte LED_SRAM_SIZE
#endif



; ***************************************************************************
; code


.cseg



; ---------------------------------------------------------------------------
; main
;

main:
  ; setup stack
  .ifdef SPH               ; if SPH is defined
    ldi r16, High(RAMEND)
    out SPH, r16           ; init MSB stack pointer
  .endif
  ldi r16, Low(RAMEND)
  out SPL, r16             ; init LSB stack pointer

;  rcall watchdogOff        ; turn off watchdog timer (sometimes it stays on after reboot)
  
  rcall initModules

  rcall Utils_SetupUid

  rcall initialWait
  sei ; Enable interrupts

  rcall onSystemStart


#ifdef MODULES_LED
  ldi xl, LOW(blinkPattern)  ; debug: set blink pattern
  ldi xh, HIGH(blinkPattern)
  ldi zl, LOW(ledA3Flash)
  ldi zh, HIGH(ledA3Flash)
  ldi yl, LOW(ledA3Sram)
  ldi yh, HIGH(ledA3Sram)
  rcall Led_SetPattern
#endif

;    sbi DDRA, PORTA2 ; debug
;    sbi PINA, PORTA2 ; debug (toggle)
;    cbi PORTA, PORTA2 ; debug (on)
;    sbi PORTA, PORTA2 ; debug (off)

;  ldi r16, 1
;  sts twiMasterScanEnabled, r16

main_loop:
    rcall runModulesUntilIdle

    sei ; make sure interrupts really are enabled
    ; only modify SE, SM1 and SM0
    in r16, MCUCR
    ldi r17, (1<<SE) | (1<<SM1) | (1<<SM0)
    neg r17
    and r16, r17
    ori r16, (1<<SE)           ; sleep mode "idle", enable
    out MCUCR, r16
    sleep                      ; sleep, wait for interrupt
  rjmp main_loop




; ---------------------------------------------------------------------------
; initModules
;
; Call init functions of the used modules. Add your routine calls here.
;
; IN:
; - nothing
; OUT:
; - nothing
; USED: depending on called routines

initModules:
  rcall Utils_Init

#ifdef MODULES_TIMER
  rcall Timer_Init
#endif

#ifdef MODULES_LED
  ldi zl, LOW(ledA3Flash)
  ldi zh, HIGH(ledA3Flash)
  ldi yl, LOW(ledA3Sram)
  ldi yh, HIGH(ledA3Sram)
  rcall Led_Init
#endif
  
#ifdef MODULES_COM
  rcall Com2_Init   ; init COM module
  rcall CPRO_Init   ; init COM protocol module
#endif
#ifdef MODULES_TWI_MASTER
  rcall TWI_Master_Init
#endif
#ifdef MODULES_LCD
  rcall LCD_Init
#endif
#ifdef MODULES_BMP280
  rcall BMP280_Init
#endif

#ifdef MODULES_SI7021
  rcall SI7021_Init
#endif

#ifdef MODULES_STATS
  rcall Stats_Init
#endif

#ifdef MODULES_CNY70
  rcall CNY70_Init
#endif

#ifdef MODULES_REED
  rcall REED_Init
#endif

  ; done
  ret



; ---------------------------------------------------------------------------
; runModulesUntilIdle
;
; Call run functions of the used modules. Add your routine calls here.
;
; IN:
; - nothing
; OUT:
; - nothing
; USED: depending on called routines

runModulesUntilIdle:

#ifdef MODULES_TIMER
  ; TIMER module
  rcall Timer_Run
#endif

#ifdef MODULES_COM
; COM module (call until carry flag cleared but at most 10 times to not starve other modules)
  ldi r16, 10
runModulesUntilIdle_Com:
    push r16
      rcall Com2_Run
    pop r16
    brcc runModulesUntilIdle_ComEnd
    dec r16
  brne runModulesUntilIdle_Com
runModulesUntilIdle_ComEnd:  
  
#endif

#ifdef MODULES_STATS
  rcall Stats_Run
#endif

#ifdef MODULES_REED
  rcall REED_Run
#endif

  ; add more modules here
  ret



; ---------------------------------------------------------------------------
; initialWait
;
; Initial wait to desync nodes.
;
; This routine waits for between 10 to 2560 milliseconds (derived from UID)
;
; IN:
; - nothing
; OUT:
; - nothing
; USED: r16, r17, r18, r19, r20, r21, r22, X

initialWait:
  ; setup initial wait loop
  rcall Utils_ReadUid             ; (R16, X)
  clr r16
  eor r16, r18
  eor r16, r19
  eor r16, r20
  eor r16, r21

initialWait_l1:    ; wait R16 x 10 milliseconds
    ldi r17, 200
initialWait_l2: ; wait for 10ms
     Utils_WaitNanoSecs 50000, 0, r22 ; wait for 50 microseconds
     dec r17
    brne  initialWait_l2
    dec r16
  brne initialWait_l1
  ret





#ifdef MODULES_LCD

printTimerMark:
  in r15, SREG ; debug
  push r15
    cli
    ldi r18, 1
    ldi r19, 1
    rcall LCD_SetCursor
    lds r16, timerModuleCounterSecs
    rcall LCD_PrintHexByte
  pop r15
  out SREG, r15
  ret


printSendStats:
  in r15, SREG ; debug
  push r15
    cli

    ldi r18, 0
    ldi r19, 2
    rcall LCD_SetCursor
    ldi zl, LOW(textUid)
    ldi zh, HIGH(textUid)
    rcall LCD_PrintFromFlash
    push xh                           ; 1-4: UID
      push xl
        rcall Utils_ReadUid           ; (R16, X)
      pop xl
    pop xh
    push r18
      push r19
        mov r18, r20
        mov r19, r21
        rcall LCD_PrintHexWord
      pop r19
    pop r18
    rcall LCD_PrintHexWord

    ldi r18, 0
    ldi r19, 3
    rcall LCD_SetCursor
    ldi zl, LOW(textAddress)
    ldi zh, HIGH(textAddress)
    rcall LCD_PrintFromFlash
    lds r16, com2Address
    rcall LCD_PrintHexByte
    ldi r16, 32
    rcall LCD_PrintChar
    lds r16, cproMode
    rcall LCD_PrintHexByte
    ldi r16, 32
    rcall LCD_PrintChar
    lds r16, cproAddrRangeBegin
    rcall LCD_PrintHexByte

    ldi r18, 0
    ldi r19, 4
    rcall LCD_SetCursor
    ldi zl, LOW(textBitmap)
    ldi zh, HIGH(textBitmap)
    rcall LCD_PrintFromFlash
    lds r16, cproUsedAddresses
    rcall LCD_PrintHexByte
    lds r16, cproUsedAddresses+1
    rcall LCD_PrintHexByte
    lds r16, cproUsedAddresses+2
    rcall LCD_PrintHexByte
    lds r16, cproUsedAddresses+3
    rcall LCD_PrintHexByte

#ifdef MODULES_COM
    ldi r18, 0
    ldi r19, 5
    rcall LCD_SetCursor
    ldi zl, LOW(textStatsPacketsIn)
    ldi zh, HIGH(textStatsPacketsIn)
    rcall LCD_PrintFromFlash
    lds r18, com2StatsPacketsIn
    lds r19, com2StatsPacketsIn+1
    rcall LCD_PrintHexWord
  
    ldi r18, 0
    ldi r19, 6
    rcall LCD_SetCursor
    ldi zl, LOW(textStatsPacketsOut)
    ldi zh, HIGH(textStatsPacketsOut)
    rcall LCD_PrintFromFlash
    lds r18, com2StatsPacketsOut
    lds r19, com2StatsPacketsOut+1
    rcall LCD_PrintHexWord
#endif
 
  pop r15
  out SREG, r15
  ret
#endif



#ifdef MODULES_SI7021
#ifdef MODULES_COM

#if 0
Main_SendValueMsg:
  in r15, SREG
  push r15
    cli
    lds r16, com2Address                ; do we have an address assigned?
    tst r16
    breq sendValueMsg_done             ; no, do nothing
    ; send message for current temp
    lds r22, si7021Flags
    mov r16, r22
    andi r16, SI7021_FLAGS_TEMP_VALID
    breq sendValueMsg_checkHum
    ldi r16, 0xff                      ; destination address
    ldi r17, VALUE_ID_TEMP1            ; value id
    push r22
      ldi r22, AQHOME_VALUETYPE_TEMP
      lds r18, si7021LastTemp            ; value
      lds r19, si7021LastTemp+1
      ldi r20, 100                       ; denominator
      clr r21
      rcall CPRO_EnqueueValue
    pop r22
sendValueMsg_checkHum:
    mov r16, r22
    andi r16, SI7021_FLAGS_HUM_VALID
    breq sendValueMsg_done
    ldi r16, 0xff                      ; destination address
    ldi r17, VALUE_ID_HUM1             ; value id
    push r22
      ldi r22, AQHOME_VALUETYPE_HUMIDITY
      lds r18, si7021LastHumidity        ; value
      lds r19, si7021LastHumidity+1
      ldi r20, 1                         ; denominator
      clr r21
      rcall CPRO_EnqueueValue
    pop r22
sendValueMsg_done:
  pop r15
  out SREG, r15
  ret
#endif


#ifdef MODULES_LCD
  textStatsPacketsIn:      .db "In     : ", 0
  textStatsPacketsRecvErr: .db "RecvErr: ", 0
  textStatsPacketsOut:     .db "Out    : ", 0
  textUid:                 .db "UID    : ", 0
  textAddress:             .db "ADDR   :", 0, 0
  textBitmap:              .db "BITMAP :", 0, 0
#endif

#endif
#endif




