; ***************************************************************************
; copyright   : (C) 2025 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.   *
; ***************************************************************************

; Hardware routine  for AtMega 644P devices


.cseg


; ---------------------------------------------------------------------------
; @routine systemInitHardware
;

systemInitHardware:
  ; set all ports as inputs and enable internal pull-up resistors
  ldi r16, 0xff
  clr r17

  out DDRA, r17  ; all input
  out PORTA, r16 ; enable pull-up on all

  out DDRB, r17  ; all input
  out PORTB, r16 ; enable pull-up on all

  out DDRC, r17  ; all input
  out PORTC, r16 ; enable pull-up on all

  out DDRD, r17  ; all input
  out PORTD, r16 ; enable pull-up on all

  ret
; @end



; ---------------------------------------------------------------------------
; @routine systemSetSpeed
;

systemSetSpeed:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine systemSleep
;

systemSleep:
  ; only modify SE, SM2, SM1 and SM0
  cli

  inr r16, SMCR
  cbr r16, (1<<SE) | (0<<SM2) | (0<<SM1) | (0<<SM0)
  outr SMCR, r16

  sei                        ; make sure interrupts really are enabled

  inr r16, SMCR       ; enable sleep mode
  sbr r16, (1<<SE)
  outr SMCR, r16

  sleep                      ; sleep, wait for interrupt

  inr r16, SMCR       ; disable sleep mode
  cbr r16, (1<<SE)
  outr SMCR, r16

  ret
; @end





; ---------------------------------------------------------------------------
; @routine systemSetupTimer0
;

systemSetupTimer0:            ; setup timer for IRQ every 100ms
  ldi r16, (1<<WGM01) | (0<<WGM00)  ; Prescaler 1024, CTC mode
  outr TCCR0A, r16

  ldi r16, (1<<CS02) | (0<<CS01) | (1<<CS00) | (0<<WGM02) ; Prescaler 1024, CTC mode
  outr TCCR0B, r16

;
; Settings for clock 1Mhz (default)
; use timer0 with OCR0A=98-1 (irq every 97.65625 millisecs), baseTimerModuleReloadValue 1
;
.if clock == 1000000
  ; CMP-A interrupt about every 100ms
  ldi r16, 98-1      ; (1,000,000/1024)/10 = 97.65625
  outr OCR0A, r16

  ldi r16, 1
  sts baseTimerModuleReloadValue, r16
  sts baseTimerModuleTickCounter, r16

; Settings for clock 8Mhz
; use timer0 with OCR0=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
;
.elif clock == 8000000
  ; CMP interrupt about every 10ms
  ldi r16, 78-1
  outr OCR0A, r16

  ldi r16, 10
  sts baseTimerModuleReloadValue, r16
  sts baseTimerModuleTickCounter, r16
.elif clock == 10000000
  ; CMP-A interrupt about every 10ms
  ldi r16, 98-1      ; (10,000,000/1024)/10 = 97.65625
  outr OCR0A, r16

  ldi r16, 10
  sts baseTimerModuleReloadValue, r16
  sts baseTimerModuleTickCounter, r16
.elif clock == 20000000
  ; CMP-A interrupt about every 5ms
  ldi r16, 98-1
  outr OCR0A, r16

  ldi r16, 20
  sts baseTimerModuleReloadValue, r16
  sts baseTimerModuleTickCounter, r16
.elif clock == 16000000
  ; CMP-A interrupt about every 10ms
  ldi r16, 98-1      ; (16,000,000 Hz/1024/10) = 156.25 Hz = 6.4ms
  outr OCR0A, r16

  ldi r16, 16
  sts baseTimerModuleReloadValue, r16
  sts baseTimerModuleTickCounter, r16
.else
  .error "Unhandled clock frequency"
.endif

  ldi r16, (1<<OCF0A)         ; clear pending interrupts
  outr TIFR0, r16
  
  inr r16, TIMSK0
  sbr r16, (1<<OCIE0A)        ; Timer/Counter0 Output Compare Match A Interrupt Enable
  outr TIMSK0, r16
.endif

  sec
  ret
; @end




