Files
aqhomecontrol/avr/modules/lcd2/gui2/screensavers/simple.asm
2026-04-13 00:20:47 +02:00

493 lines
13 KiB
NASM

; ***************************************************************************
; 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. *
; ***************************************************************************
#ifndef AQH_AVR_GUI_SCREENSAVER_SIMPLE_ASM
#define AQH_AVR_GUI_SCREENSAVER_SIMPLE_ASM
; ***************************************************************************
; defines
.equ SIMPLESAVER_TIMER100ms = 6000 ; 10mins
;.equ SIMPLESAVER_TIMER100ms = 100 ; 10secs
; widget data
.equ SIMPLESAVER_OFFS_BEGIN = MAINWINDOW_SIZE
.equ SIMPLESAVER_OFFS_TIMER_LO = SIMPLESAVER_OFFS_BEGIN+0
.equ SIMPLESAVER_OFFS_TIMER_HI = SIMPLESAVER_OFFS_BEGIN+1
.equ SIMPLESAVER_OFFS_RELOAD_LO = SIMPLESAVER_OFFS_BEGIN+2
.equ SIMPLESAVER_OFFS_RELOAD_HI = SIMPLESAVER_OFFS_BEGIN+3
.equ SIMPLESAVER_OFFS_NODEADDR1 = SIMPLESAVER_OFFS_BEGIN+4
.equ SIMPLESAVER_OFFS_VALUEID1 = SIMPLESAVER_OFFS_BEGIN+5
.equ SIMPLESAVER_OFFS_NODEADDR2 = SIMPLESAVER_OFFS_BEGIN+6
.equ SIMPLESAVER_OFFS_VALUEID2 = SIMPLESAVER_OFFS_BEGIN+7
.equ SIMPLESAVER_SIZE = SIMPLESAVER_OFFS_BEGIN+8
; EEPROM data
.equ SIMPLESAVER_EE_OFFS_NODEADDR1 = 0
.equ SIMPLESAVER_EE_OFFS_VALUEID1 = 1
.equ SIMPLESAVER_EE_OFFS_NODEADDR2 = 2
.equ SIMPLESAVER_EE_OFFS_VALUEID2 = 3
.equ SIMPLESAVER_EE_SIZE = 4
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine SimpleSaver_new @global
;
; @return CFLAG set of okay, cleared otherwise
; @return Y address of newly created object
; @param X parent widget
; @param r16 value for OBJECT_OFFS_OPTS
; @param r17 value for WIDGET_OFFS_PACK
; @clobbers any
SimpleSaver_new:
ldi r24, LOW(SIMPLESAVER_SIZE)
ldi r25, HIGH(SIMPLESAVER_SIZE)
bigcall Object_Alloc ; (!r16, !r17, !X)
brcc SimpleSaver_new_ret
rcall SimpleSaver_Init ; (r16, r17, X)
sec
SimpleSaver_new_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine SimpleSaver_Init @global
;
; @return CFLAG set of okay, cleared otherwise
; @return Y address of newly created object
; @param X parent widget
; @param r16 value for OBJECT_OFFS_OPTS
; @param r17 value for WIDGET_OFFS_PACK
; @clobbers any
SimpleSaver_Init:
; call base class
bigcall MainWindow_Init
; set default signal map
ldi r16, LOW(SimpleSaver_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
ldi r16, HIGH(SimpleSaver_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_HI, r16
; set style which has no spacing and no borders
ldi r16, LOW(SimpleSaver_DefaultStyle*2)
std Y+WIDGET_OFFS_STYLE_LO, r16
ldi r16, HIGH(SimpleSaver_DefaultStyle*2)
std Y+WIDGET_OFFS_STYLE_HI, r16
; read config from eeprom
rcall simpleSaverReadFromEeprom
; preset and start timer
ldi r16, LOW(SIMPLESAVER_TIMER100ms)
ldi r17, HIGH(SIMPLESAVER_TIMER100ms)
std Y+SIMPLESAVER_OFFS_RELOAD_LO, r16
std Y+SIMPLESAVER_OFFS_RELOAD_HI, r17
std Y+SIMPLESAVER_OFFS_TIMER_LO, r16
std Y+SIMPLESAVER_OFFS_TIMER_HI, r17
ret
; @end
SimpleSaver_Enter:
bigcall Widget_GetApp
push yl
push yh
mov xl, yl
mov xh, yh
mov yl, r18
mov yh, r19
bigcall GuiApp_EnterWindow
pop yh
pop yl
ret
; @end
SimpleSaver_Leave:
ldd r16, Y+OBJECT_OFFS_FLAGS
andi r16, (1<<WIDGET_FLAGS_VISIBLE_BIT)
breq SimpleSaver_Leave_ret ; jump if not active
bigcall Widget_GetApp
push yl
push yh
mov yl, r18
mov yh, r19
bigcall GuiApp_LeaveWindow
pop yh
pop yl
SimpleSaver_Leave_ret:
ret
; @end
SimpleSaver_KeepAlive:
; restart timer
ldd r16, Y+SIMPLESAVER_OFFS_RELOAD_LO
ldd r17, Y+SIMPLESAVER_OFFS_RELOAD_HI
std Y+SIMPLESAVER_OFFS_TIMER_LO, r16
std Y+SIMPLESAVER_OFFS_TIMER_HI, r17
; screen saver active?
ldd r16, Y+OBJECT_OFFS_FLAGS
andi r16, (1<<WIDGET_FLAGS_VISIBLE_BIT)
breq SimpleSaver_KeepAlive_ret ; jump if not active
rcall SimpleSaver_Leave
SimpleSaver_KeepAlive_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine simpleSaverWriteToEeprom
;
; @param Y widget
; @return CFLAG set if data found and read, cleared on error
; @clobbers R16, R17, R18, R20, R21, X
simpleSaverWriteToEeprom:
ldi r16, EEID_SCREENSAVER
bigcall EepromTlv_FindFirst ; (R18)
brcs simpleSaverWriteToEeprom_write
ldi r16, EEID_SCREENSAVER
ldi r17, SIMPLESAVER_EE_SIZE
bigcall EepromTlv_AddTlv ; X=pointer to EEPROM data (R16, R18, R20, R21)
brcc simpleSaverWriteToEeprom_ret
simpleSaverWriteToEeprom_write:
push yl
push yh
adiw yh:yl, SIMPLESAVER_OFFS_NODEADDR1
ldi r18, SIMPLESAVER_EE_SIZE
simpleSaverWriteToEeprom_loop:
ld r16, Y+
bigcall Eeprom_WriteByteIfChanged ; (R17)
brcc simpleSaverWriteToEeprom_ret
adiw xh:xl, 1
dec r18
brne simpleSaverWriteToEeprom_loop
pop yh
pop yl
sec
simpleSaverWriteToEeprom_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine simpleSaverReadFromEeprom
;
; @param Y widget
; @return CFLAG set if data found and read, cleared on error
; @clobbers R16, R18, X
simpleSaverReadFromEeprom:
ldi r16, EEID_SCREENSAVER
bigcall EepromTlv_FindFirst ; (R18)
brcc simpleSaverReadFromEeprom_ret
push yl
push yh
adiw yh:yl, SIMPLESAVER_OFFS_NODEADDR1
ldi r18, SIMPLESAVER_EE_SIZE
simpleSaverReadFromEeprom_loop:
bigcall Eeprom_ReadByte ; R16=byte (none)
brcc simpleSaverReadFromEeprom_ret
st Y+, r16
adiw xh:xl, 1
dec r18
brne simpleSaverReadFromEeprom_loop
pop yh
pop yl
sec
simpleSaverReadFromEeprom_ret:
ret
; @end
; ***************************************************************************
; signal handlers
SimpleSaver_OnTimer:
ldd r16, Y+OBJECT_OFFS_FLAGS
andi r16, (1<<WIDGET_FLAGS_VISIBLE_BIT)
brne SimpleSaver_OnTimer_ret ; jump if active
; check timer
ldd r24, Y+SIMPLESAVER_OFFS_TIMER_LO
ldd r25, Y+SIMPLESAVER_OFFS_TIMER_HI
mov r16, r24
or r16, r25
breq SimpleSaver_OnTimer_ret
sbiw r25:r24, 1
std Y+SIMPLESAVER_OFFS_TIMER_LO, r24
std Y+SIMPLESAVER_OFFS_TIMER_HI, r25
brne SimpleSaver_OnTimer_ret
; timer elapsed, enter screensaver
rcall SimpleSaver_Enter
SimpleSaver_OnTimer_ret:
sec
ret
; @end
SimpleSaver_OnTouch:
; read touch signal data from X
adiw xh:xl, WIDGET_TOUCH_OFFS_STATE
ld r22, X ; WIDGET_DATA_TOUCH_OFFS_STATE
sbiw xh:xl, WIDGET_TOUCH_OFFS_STATE
sbrs r22, DISPLAY_IFLAGS_PRESSED_BIT
rjmp SimpleSaver_OnTouch_up
; down (active touch), switch display on
ldi r16, 0xff
bigcall Display_SetBacklight
rjmp SimpleSaver_OnTouch_ret
SimpleSaver_OnTouch_up:
rcall SimpleSaver_KeepAlive
SimpleSaver_OnTouch_ret:
sec
ret
; @end
SimpleSaver_OnMsgReceived:
push zl
push zh
mov yl, zl
mov yh, zh
ldi zl, LOW(SimpleSaver_MsgTable*2)
ldi zh, HIGH(SimpleSaver_MsgTable*2)
bigcall Main_HandleValueMsg ; (any)
pop zh
pop zl
sec
ret
; @end
SimpleSaver_OnShow:
; stop timer
clr r16
std Y+SIMPLESAVER_OFFS_TIMER_LO, r16
std Y+SIMPLESAVER_OFFS_TIMER_HI, r16
; force redraw (black background)
ldd r16, Y+OBJECT_OFFS_FLAGS
sbr r16, (1<<WIDGET_FLAGS_DIRTY_BIT) | (1<<WIDGET_FLAGS_VISIBLE_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
; turn off backlight
clr r16
bigcall Display_SetBacklight
sec
ret
; @end
SimpleSaver_OnHide:
ldd r16, Y+OBJECT_OFFS_FLAGS
cbr r16, (1<<WIDGET_FLAGS_VISIBLE_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
; restart timer
ldd r16, Y+SIMPLESAVER_OFFS_RELOAD_LO
ldd r17, Y+SIMPLESAVER_OFFS_RELOAD_HI
std Y+SIMPLESAVER_OFFS_TIMER_LO, r16
std Y+SIMPLESAVER_OFFS_TIMER_HI, r17
; turn backlight on
ldi r16, 0xff
bigcall Display_SetBacklight
sec
ret
; @end
SimpleSaver_OnKeepAlive:
rcall SimpleSaver_KeepAlive
sec
ret
; @end
; ***************************************************************************
; message handlers
; ---------------------------------------------------------------------------
; @routine simpleSaverHandleSetSource1
;
; @param Y widget
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG set if ACK/NACK requested
; @return R23 command value for ACK/NACK message
; @clobbers R16, R17, R18, R20, R21, X, Y, Z
simpleSaverHandleSetSource1:
std Y+SIMPLESAVER_OFFS_NODEADDR1, r18
std Y+SIMPLESAVER_OFFS_VALUEID1, r19
rcall simpleSaverWriteToEeprom ; (R16, R17, R18, R20, R21, X, Y)
ldi r23, NETMSG_CMD_VALUE_SET_ACK
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine simpleSaverHandleSetSource2
;
; @param Y widget
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG set if ACK/NACK requested
; @return R23 command value for ACK/NACK message
; @clobbers R16, R17, R18, R20, R21, X, Y, Z
simpleSaverHandleSetSource2:
std Y+SIMPLESAVER_OFFS_NODEADDR1, r18
std Y+SIMPLESAVER_OFFS_VALUEID1, r19
rcall simpleSaverWriteToEeprom ; (R16, R17, R18, R20, R21, X, Y)
ldi r23, NETMSG_CMD_VALUE_SET_ACK
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine simpleSaverHandleReport
;
; @param Y widget
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG cleared (no ACK/NACK requested)
; @clobbers any
simpleSaverHandleReport:
mov r16, r18 ; check for non-zero value
or r16, r19
breq simpleSaverHandleReport_end
ldd r16, Y+SIMPLESAVER_OFFS_NODEADDR1
cp r16, r22
brne simpleSaverHandleReport_l1
ldd r16, Y+SIMPLESAVER_OFFS_VALUEID1
cp r16, r17
breq simpleSaverHandleReport_matches
simpleSaverHandleReport_l1:
ldd r16, Y+SIMPLESAVER_OFFS_NODEADDR2
cp r16, r22
brne simpleSaverHandleReport_end
ldd r16, Y+SIMPLESAVER_OFFS_VALUEID2
cp r16, r17
brne simpleSaverHandleReport_end
simpleSaverHandleReport_matches:
rcall SimpleSaver_KeepAlive
simpleSaverHandleReport_end:
clc ; no ACK needed
ret
; @end
; ***************************************************************************
; data in FLASH
SimpleSaver_DefaultStyle:
.dw DISPLAY_COLOR_LIGHTGREY ; frontCol_norm
.dw DISPLAY_COLOR_BLACK ; backCol_norm
.dw DISPLAY_COLOR_BLACK ; borderCol_norm
.dw DISPLAY_COLOR_WHITE ; shadowCol_norm
.dw DISPLAY_COLOR_WHITE ; frontCol_activated
.dw DISPLAY_COLOR_NAVY ; backCol_activated
.dw DISPLAY_COLOR_BLACK ; borderCol_activated
.dw DISPLAY_COLOR_WHITE ; shadowCol_activated
.db 0, 1 ; outerBorderSize, innerBorderSize
.dw ili9341Font12x16_1*2 ; font
.db 12, 16 ; charWidth, charHeight
SimpleSaver_MsgTable:
.dw NETMSG_CMD_VALUE_SET | (VALUE_ID_SCREENSAVER_SETSOURCE1<<8), simpleSaverHandleSetSource1
.dw NETMSG_CMD_VALUE_SET | (VALUE_ID_SCREENSAVER_SETSOURCE2<<8), simpleSaverHandleSetSource2
.dw NETMSG_CMD_VALUE_REPORT, simpleSaverHandleReport
.dw 0, 0
SimpleSaver_DefaultSignalmap:
; header
.dw MainWindow_DefaultSignalmap*2 ; next table to use
; entries
.db 0, OBJECT_SIGNAL_TIMER, LOW(SimpleSaver_OnTimer), HIGH(SimpleSaver_OnTimer)
.db 0, WIDGET_SIGNAL_KEEPALIVE, LOW(SimpleSaver_OnKeepAlive), HIGH(SimpleSaver_OnKeepAlive)
.db 0, WIDGET_SIGNAL_SHOW, LOW(SimpleSaver_OnShow), HIGH(SimpleSaver_OnShow)
.db 0, WIDGET_SIGNAL_HIDE, LOW(SimpleSaver_OnHide), HIGH(SimpleSaver_OnHide)
.db 0, WIDGET_SIGNAL_TOUCH, LOW(SimpleSaver_OnTouch), HIGH(SimpleSaver_OnTouch)
.db 0, OBJECT_SIGNAL_RECVMSG, LOW(SimpleSaver_OnMsgReceived), HIGH(SimpleSaver_OnMsgReceived)
.db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw)
.db 0, 0, 0, 0 ; end of table
#endif