; ***************************************************************************
; 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.   *
; ***************************************************************************




; ***************************************************************************
; Source file for temperature sensor node on AtTiny 84
;
; This is for the full system (i.e. not the boot loader).
;
; All definitions and changes should go into this file.
;
;
;                                 AtTiny84
;                                 --------
;                            VCC  1     14  GND
;                            PB0  2     13  PA0  REED_OUT
;                            PB1  3     12  PA1  COM-DATA
;                  /RESET    PB3  4     11  PA2  REED_IN1
;                  [KEY1]    PB2  5     10  PA3  LED
;                  COM_ATTN  PA7  6      9  PA4  TWI-SCL
;                  TWI-SDA   PA6  7      8  PA5  REED_IN2
;                                 --------
;
; ***************************************************************************



.nolist
.include "include/tn84def.inc" ; Define device ATtiny84
.list

.include "defs.asm"



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

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

.equ clock=1000000 ; Define the clock frequency

.include "common/utils_wait.asm"


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

#define FW_TYPE    AQHOME_FW_TYPE_ATT84_TEMP1
#define FW_VERSION 0x0001


#define MODULES_TIMER
#define MODULES_COM
#define MODULES_COM_WITH_ADDR_PROTO
#define MODULES_LED
#define MODULES_TWI_MASTER
;#define MODULES_LCD
#define MODULES_SI7021
#define MODULES_STATS
;#define MODULES_CNY70
#define MODULES_REED


.set MODULES_MASK = 0
#ifdef MODULES_TIMER
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_TIMER)
#endif
#ifdef MODULES_COM
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_COM)
#endif
#ifdef MODULES_LED
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_LED)
#endif
#ifdef MODULES_TWI_MASTER
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_TWIMASTER)
#endif
#ifdef MODULES_LCD
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_LCD)
#endif
#ifdef MODULES_SI7021
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_SI7021)
#endif
#ifdef MODULES_STATS
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_STATS)
#endif
#ifdef MODULES_CNY70
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_CNY70)
#endif
#ifdef MODULES_REED
.set MODULES_MASK = MODULES_MASK | (1<<AQHOME_FW_MODULE_REED)
#endif



; ---------------------------------------------------------------------------
; defines for modules

#define LCD_MINIMAL_FONT


.equ VALUE_ID_TEMP1 = 0x01
.equ VALUE_ID_HUM1  = 0x02

.equ VALUE_ID_ADC   = 0x03
.equ VALUE_ID_REED1 = 0x04
.equ VALUE_ID_REED2 = 0x05


; ---------------------------------------------------------------------------
; COM module

.equ COM_BIT_LENGTH      = 52000 ; 104000=9600, 52000=19200, 26000=38400

.equ COM_DDR_DATA        = DDRA
.equ COM_PORT_DATA       = PORTA
.equ COM_PIN_DATA        = PINA
.equ COM_PINNUM_DATA     = PORTA1

.equ COM_DDR_ATTN        = DDRA
.equ COM_PORT_ATTN       = PORTA
.equ COM_PIN_ATTN        = PINA
.equ COM_PINNUM_ATTN     = PORTA7

.equ COM_IRQ_ADDR_ATTN   = PCMSK0
.equ COM_IRQ_BIT_ATTN    = 7              ; bit 7 in PCMSK0
.equ COM_IRQ_GIFR_ATTN   = PCIF0
.equ COM_IRQ_GIMSK_ATTN  = PCIE0



; ---------------------------------------------------------------------------
; TWI master module

.equ TWI_DDR_SCL          = DDRA
.equ TWI_PORT_SCL         = PORTA
.equ TWI_PIN_SCL          = PINA
.equ TWI_PINNUM_SCL       = PORTA4

.equ TWI_DDR_SDA          = DDRA
.equ TWI_PORT_SDA         = PORTA
.equ TWI_PIN_SDA          = PINA
.equ TWI_PINNUM_SDA       = PORTA6



; ---------------------------------------------------------------------------
; LCD module

.equ LCD_TWI_ADDRESS      = 0x3c



; ---------------------------------------------------------------------------
; BMP 280

.equ BMP280_ADDR          = 0x76



; ---------------------------------------------------------------------------
; SI 7021

.equ SI7021_ADDR          = 0x40



; ---------------------------------------------------------------------------
; ADC/CNY70


.equ CNY70_PORT_LED       = PORTB1
.equ CNY70_DDR_LED        = DDRB
.equ CNY70_PINNUM_LED     = PORTB1

.equ CNY70_PORT_ADC       = PORTA5 ; adc5
.equ CNY70_DDR_ADC        = DDRB
.equ CNY70_PINNUM_ADC     = PORTA5
.equ CNY70_MUX_ADC        = MUX5
.equ CNY70_ADCSRB_ADC     = ADC5D




; ---------------------------------------------------------------------------
; Reed
;

.equ REEDOUT_DDR          = DDRA
.equ REEDOUT_PORT         = PORTA
.equ REEDOUT_PIN          = PINA
.equ REEDOUT_PINNUM       = PORTA0

.equ REED1_DDR            = DDRA
.equ REED1_PORT           = PORTA
.equ REED1_PIN            = PINA
.equ REED1_PINNUM         = PORTA2

.equ REED2_DDR            = DDRA
.equ REED2_PORT           = PORTA
.equ REED2_PIN            = PINA
.equ REED2_PINNUM         = PORTA5




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

.cseg
.org 000000



; ---------------------------------------------------------------------------
; Reset and interrupt vectors (will be removed as soon as we can flash data over COM)

;	rjmp main ; Reset vector
        rjmp AQHOME_BOOTLOADER_ADDR ; Reset vector  ; use this for flashed system
	reti ; EXT_INT0
	rjmp com2IsrPcint0 ; PCI0
	reti ; PCI1
	reti ; WATCHDOG
	reti ; ICP1
	reti ; OC1A
	reti ; OC1B
	reti ; OVF1
        rjmp timerIrqOC0A ; OC0A
	reti ; OC0B
	reti ; OVF0
	reti ; ACI
#ifdef MODULES_CNY70
	rjmp cny70Isr ; ADCC
#else
        reti ; ADCC
#endif
	reti ; ERDY
	reti ; USI_STR
	reti ; USI_OVF


firmwareType:    .dw FW_TYPE
firmwareVersion: .dw FW_VERSION
firmwareModules: .dw MODULES_MASK
firmwareStart:   rjmp main


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

.include "common/utils.asm"
.include "common/utils_wait_fixed.asm"
.include "common/crc8.asm"

#ifdef MODULES_TIMER
  .include "modules/timer/main.asm"
#endif
#ifdef MODULES_LED
.include "modules/led/main.asm"
#endif
#ifdef MODULES_COM
  .include "modules/com2/defs.asm"
  .include "modules/com2/main.asm"
  #ifdef MODULES_COM_WITH_ADDR_PROTO
    .include "modules/comproto/defs.asm"
    .include "modules/comproto/main.asm"
    .include "modules/comproto/addr.asm"
    .include "modules/comproto/msg_recvstats.asm"
    .include "modules/comproto/msg_sendstats.asm"
    .include "modules/comproto/msg_sysstats.asm"
    .include "modules/comproto/msg_memstats.asm"
    .include "modules/comproto/msg_pong.asm"
    .include "modules/comproto/msg_value.asm"
    .include "modules/comproto/msg_device.asm"
    .include "modules/comproto/msg_reboot.asm"
  #endif
#endif
#ifdef MODULES_TWI_MASTER
  .include "modules/twimaster/main.asm"
#endif
#ifdef MODULES_LCD
  .include "modules/lcd/main.asm"
#endif
#ifdef MODULES_SI7021
  .include "modules/si7021/main.asm"
#endif
#ifdef MODULES_STATS
  .include "modules/stats/main.asm"
#endif
#ifdef MODULES_CNY70
  .include "modules/cny70/main.asm"
#endif
#ifdef MODULES_REED
  .include "modules/reed/main.asm"
#endif



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

.dseg


#ifdef MODULES_LCD
  sramTimerWriteStats:       .byte 2
#endif
sramTimerEnqueueValues:      .byte 2
#ifdef MODULES_SI7021
  sramTimerSI7021Measure:      .byte 2
  sramTimerSI7021SendTemp:     .byte 2
  sramTimerSI7021SendHumidity: .byte 2
#endif
#ifdef MODULES_CNY70
  sramTimerCny70SendAdc:       .byte 2
#endif
#ifdef MODULES_LCD
  sramPeriodicalLcdMark:       .byte 2
#endif


; ***************************************************************************
; data in FLASH

.cseg

ledA3Flash:    .db DDRA+0x20, PORTA+0x20, PINA+0x20, (1<<PORTA3)
blinkPattern:  .db 2, 50, 0xff, 0xff   ; 1 short blink, 5s pause, restart
;blinkPattern2: .db 2, 2, 0xff, 0xff   ; 1 short blink, short pause, restart




; ---------------------------------------------------------------------------
; timer list


timerList:
;     SRAM variable/counter        routine                     flags                secs (0=don't start or restart)
#ifdef MODULES_COM_WITH_ADDR_PROTO
  .dw cproAddresModeTimer,         CPRO_Address_OnTimer,       0,                   0     ; (no restart)
#endif
#ifdef MODULES_STATS
  .dw statsSendTimer,              Stats_Timer,                TIMER_FLAGS_IF_ADDR, 300   ; every 5m
#endif
#ifdef MODULES_LCD
  .dw sramPeriodicalLcdMark,       periodicalLcdMark,          0,                    1    ; every sec
  .dw sramTimerWriteStats,         writeStats,                 0,                   10
#endif
#ifdef MODULES_SI7021
  .dw sramTimerSI7021Measure,      SI7021_PeriodicMeasurement, 0,                   30    ; every 30s
  .dw sramTimerSI7021SendTemp,     sendTemp,                   TIMER_FLAGS_IF_ADDR, 60    ; every 60s
  .dw sramTimerSI7021SendHumidity, sendHumidity,               TIMER_FLAGS_IF_ADDR, 60    ; every 60s
#endif
#ifdef MODULES_CNY70
  .dw sramTimerCny70SendAdc,       sendAdc,                    TIMER_FLAGS_IF_ADDR, 30    ; every 30s
#endif
  .dw 0 ; end of list





.include "main.asm"


; ---------------------------------------------------------------------------
; Called on first time run, i.e. on system start. No arguments, no results.

onSystemStart:
  ret


#ifdef MODULES_LCD
periodicalLcdMark:
  rcall printTimerMark
  ret


writeStats:
  rcall printSendStats
  ret
#endif



#ifdef MODULES_SI7021

sendHumidity:
  rcall SI7021_SendHumidity
  brcs sendHumidity_okay
  ; set timer to 1s to retry later
  ldi xl, LOW(sramTimerSI7021SendHumidity)
  ldi xh, HIGH(sramTimerSI7021SendHumidity)
  rjmp Timer_SetValueTo1s
sendHumidity_okay:
  ret


sendTemp:
  rcall SI7021_SendTemp
  brcs sendTemp_okay
  ; set timer to 1s to retry later
  ldi xl, LOW(sramTimerSI7021SendTemp)
  ldi xh, HIGH(sramTimerSI7021SendTemp)
  rjmp Timer_SetValueTo1s
sendTemp_okay:
  ret

#endif



#ifdef MODULES_CNY70
sendAdc:
  rcall CNY70_SendAdc
  brcs sendAdc_okay
  ; set timer to 1s to retry later
  ldi xl, LOW(sramTimerCny70SendAdc)
  ldi xh, HIGH(sramTimerCny70SendAdc)
  rjmp Timer_SetValueTo1s
sendAdc_okay:
  ret
#endif



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

onEvery100ms:
#ifdef MODULES_LED
  ; ticker for LED module
  ldi zl, LOW(ledA3Flash)
  ldi zh, HIGH(ledA3Flash)
  ldi yl, LOW(ledA3Sram)
  ldi yh, HIGH(ledA3Sram)
  rcall Led_Tick
#endif

#ifdef MODULES_CNY70
  rcall CNY70_Every100ms
#endif

#ifdef MODULES_REED
  rcall REED_Every100ms
#endif

  ret



; ---------------------------------------------------------------------------
; onPacketReceived:
;
; Called after a packet was received via COM module. Add your routine calls here.
;
; The packet will be released in any case after return from this call.
; IN:
; - X  : pointer to received buffer
; OUT:
; - CFLAG: set if handled, cleared otherwise
; USED: depending on called routines

onPacketReceived:
  rcall CPRO_OnPacketReceived
  ret



