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




; ***************************************************************************
; Source file for fan controller node on AtTiny 861
;
; This is for the full system (i.e. not the boot loader).
;
; All definitions and changes should go into this file.
;
;
; ***************************************************************************


;.equ clock=1000000 ; Define the clock frequency
.equ clock=8000000 ; Define the clock frequency



.nolist
.include "include/tn861Adef.inc" ; Define device ATtiny861A
.list

.include "../defs.asm"
.include "./data.asm"

.include "version.asm"
.include "devices/all/defs.asm"
.include "common/calls.asm"
.include "common/utils_io.asm"
.include "common/utils_wait.asm"



; ***************************************************************************
; defines

; ---------------------------------------------------------------------------
; generic

.equ NET_BUFFERS_NUM            =  6
.equ NET_MSGNUMINBUF_SIZE       =  8 ; max buffer nums in ringbuffer (global incoming)
.equ NET_IFACE_OUTMSGBUF_SIZE   =  8 ; max buffer nums in ringbuffer (per interface outbound)



; ---------------------------------------------------------------------------
; firmware settings including list of modules used

; #define MODULES_TIMER
#define MODULES_CLOCK
#define MODULES_LED1
;#define MODULES_LED2
;#define MODULES_LED3
#define MODULES_NETWORK
#define MODULES_COM2W2
;#define MODULES_TWI_MASTER
;#define MODULES_LCD
;#define LCD_MINIMAL_FONT
;#define MODULES_SI7021
;#define MODULES_SGP30
;#define MODULES_SGP40
;#define MODULES_OWI_MASTER
;#define MODULES_DS18B20
;#define MODULES_CCS811
;#define MODULES_BRIGHTNESS

#define MODULES_MULTIFAN


#define APPS_NETWORK
;#define APPS_MOTION
#define APPS_FANCONTROL
#define APPS_REPORTSENSORS
#define APPS_STATS


; defines for modules

; #define LED1_NETWORK_ACTIVITY



; ---------------------------------------------------------------------------
; defines for values

.equ VALUE_ID_FAN1_DUTY         = 0x88 ; 0-100
.equ VALUE_ID_FAN1_SPEED        = 0x08 ; RPM

.equ VALUE_ID_FAN2_DUTY         = 0x89 ; 0-100
.equ VALUE_ID_FAN2_SPEED        = 0x09 ; RPM

.equ VALUE_ID_FAN3_DUTY         = 0x8a ; 0-100
.equ VALUE_ID_FAN3_SPEED        = 0x0a ; RPM

; new values
.equ VALUE_ID_FANCTRL_STATE       = 0x07
.equ VALUE_ID_FANCTRL_GUARDSRC    = 0x90
.equ VALUE_ID_FANCTRL_GUARDLIM    = 0x91
.equ VALUE_ID_FANCTRL_TRIGGER1SRC = 0x92
.equ VALUE_ID_FANCTRL_TRIGGER1LIM = 0x93
.equ VALUE_ID_FANCTRL_TRIGGER2SRC = 0x94
.equ VALUE_ID_FANCTRL_TRIGGER2LIM = 0x95
.equ VALUE_ID_FANCTRL_VALUE       = 0x96
.equ VALUE_ID_FANCTRL_HOLDTIME    = 0x97
.equ VALUE_ID_FANCTRL_MODE        = 0x98



; ***************************************************************************
; code segment

.cseg
.org 000000



; ---------------------------------------------------------------------------
; Reset and interrupt vectors
  rjmp BOOTLOADER_ADDR       ;  1: Reset vector  Reset Vector
  reti                       ;  2: INT0          External Interrupt 0
  rjmp multiFanPinChangeIsr  ;  3: PCI           Pin Change Interrupt
  reti                       ;  4: OC1A          Timer/Counter1 Compare Match 1A
  reti                       ;  5: OC1B          Timer/Counter1 Compare Match 1B
  reti                       ;  6: OVF1          Timer/Counter1 Overflow
  reti                       ;  7: OVF0          Timer/Counter0 Overflow
  reti                       ;  8: USI_START     USI Start
  reti                       ;  9: USI_OVF       USI Overflow
  reti                       ; 10: ERDY          EEPROM Ready
  reti                       ; 11: ACI           Analog Comparator
  reti                       ; 12: ADCC          ADC Conversion Complete
  reti                       ; 13: WDT           Watchdog Time-Out
  rjmp com2w2PcintIsr        ; 14: INT1          External Interrupt 1
  rjmp baseTimerIrqOC0A      ; 15: OC0A          Timer/Counter0 Compare Match A
  reti                       ; 16: OC0B          Timer/Counter0 Compare Match B
  reti                       ; 17: ICP0          Interrupt Capture Event for Timer/Counter0
  reti                       ; 18: OC1D          Timer/Counter1 Compare Match D
  reti                       ; 19: FAULT_PROT    Timer/Counter1 Fault Protection

devInfoBlock:        ; 12 bytes
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
devInfoId:           .db DEVICEINFO_ID, 0
devInfoVersion:      .db DEVICEINFO_VERSION, DEVICEINFO_REVISION             ; version, revision
firmwareVersion:     .db FIRMWARE_VARIANT_TEMP_WINDOW, FIRMWARE_VERSION_MAJOR
                     .db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL



; ---------------------------------------------------------------------------
; @routine firmwareStart @global

firmwareStart:
  rjmp main
; @end



; ---------------------------------------------------------------------------
; @routine onSystemStart

onSystemStart:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine onMessageReceived
;
; Called on every message received

onMessageReceived:
  clc
  ret
; @end



; ---------------------------------------------------------------------------
; @routine onEvery100ms
;
; Called every 100ms. Add your routine calls here. No arguments, no results.

onEvery100ms:
onEverySecond:
onEveryMinute:
onEveryHour:
onEveryDay:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine onEveryLoop
;
; Called on every loop (i.e. after awakening from sleep).
;
onEveryLoop:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine comSetupIrq
;
; setup IRQ for COM2W module

comIrqSetup:
  inr r16, MCUCR
  cbr r16, (1<<ISC01) | (1<<ISC00)
  ori r16, (1<<ISC01) | (0<<ISC00) ; falling edge triggers irq
  outr MCUCR, r16

  inr r16, GIFR
  sbr r16, (1<<INTF1)
  outr GIFR, r16

  ret
; @end



; ---------------------------------------------------------------------------
; @routine comIrqEnable
;
; enable IRQ for COM2W module

comIrqEnable:
  push r16
    inr r16, GIMSK
    sbr r16, (1<<INT1) ; enable INT1 interrupt
    outr GIMSK, r16
  pop r16
  ret
; @end



; ---------------------------------------------------------------------------
; @routine comIrqEnable
;
; disable IRQ for COM2W module

comIrqDisable:
  push r16
    inr r16, GIMSK
    cbr r16, (1<<INT1) ; disable INT1 interrupt
    outr GIMSK, r16
  pop r16
  ret
; @end



.equ COM_SETUPIRQ_FN   = comIrqSetup
.equ COM_ENABLEIRQ_FN  = comIrqEnable
.equ COM_DISABLEIRQ_FN = comIrqDisable



; ---------------------------------------------------------------------------
; @routine multiFanIrqSetup
;
; setup IRQ for MULTIFAN module

multiFanIrqSetup:
  inr r16, PCMSK1
  sbr r16, (1<<PCINT10) | (1<<PCINT12) | (PCINT14); tacho1-3
  outr PCMSK1, r16
  
  inr r16, GIMSK
  sbr r16, (1<<PCIE1) | (1<<PCIE0)
  outr GIMSK, r16
  
  inr r16, GIFR
  sbr r16, (1<<PCIF)
  outr GIFR, r16

  ret
; @end



.equ MULTIFAN_SETUPIRQ_FN = multiFanIrqSetup




; ***************************************************************************
; includes

.include "devices/all/hw_tn861.asm"
.include "devices/all/includes.asm"
.include "common/divide.asm"
.include "common/debug.asm"
.include "common/eeprom_tlv.asm"



; ---------------------------------------------------------------------------
; defines for network interface

.equ netInterfaceData = com2w2_iface



deviceCodeEnd:
  .if deviceCodeEnd >= BOOTLOADER_ADDR
    .warning "Code reaches into boot loader!"
  .endif

