view src/menu_processor.asm @ 634:4050675965ea

3.10 stable release
author heinrichsweikamp
date Tue, 28 Apr 2020 17:34:31 +0200
parents 185ba2f91f59
children 8c1f1f334275
line wrap: on
line source

;=============================================================================
;
;   File menu_processor.asm                 * combined next generation V3.09.5
;
;   Routines to handle all hwOS graphic/text menus.
;
;   Copyright (c) 2011, JD Gascuel, HeinrichsWeikamp, all right reserved.
;=============================================================================
; HISTORY
;   2012-11-02 : [jDG] Cleanup for hwOS: removed icons. Added scrolling.
;                But need a font with lower/upper alpha chars...

#include "hwos.inc"
#include "convert.inc"
#include "strings.inc"
#include "tft.inc"
#include "varargs.inc"
#include "start.inc"
#include "surfmode.inc"
#include "divemode.inc"
#include "tft_outputs.inc"
#include "eeprom_rs232.inc"
#include "adc_lightsensor.inc"
#include "i2c.inc"
#include "rtc.inc"
#include "wait.inc"
#include "colorschemes.inc"


; NOTE: needs to be identical in .inc and .asm !
;
#define MENU_LINES_MAX			.7			; maximum number of lines per screen
#define MENU_LEFT				.20			; position of first menu item
#define MENU_HEIGHT_SURF		.27			; spacing between menu item in surface mode (pixel)
#define MENU_HEIGHT_DIVE		.24			; spacing between menu item in surface mode (pixel)
#define MENU_VCENTER			.125		; position on screen
#define MAX_LINE_LENGTH_TITLE	.17			; max menu title length                   (characters)
#define MAX_LINE_LENGTH_SURF	.20			; max menu item  length in surface   menu (characters)
#define MAX_LINE_LENGTH_DIVE	.10			; max menu item  length in dive mode menu (characters)
#define MENU_ITEM_DATA_SIZE		.4			; size of a menu item data block

; Alias for easier code reading
#define option_addr				item_funct_addr


	extern	option_adjust_group_member
	extern	option_inc
	extern	option_dec
	extern	option_draw

	extern	rtc_set_rtc
	extern	divemode_option_divemenu_return


;=============================================================================
menu_proc	CODE
;=============================================================================


;-----------------------------------------------------------------------------
; Entry Point for Menu Processor, called by MENU_BEGIN Macros
;
	global	menu_processor
menu_processor:
	; read menu header
	VARARGS_BEGIN							; load TBLPTR with start address of the menu header data
	clrf	STKPTR							; never return from here

	VARARGS_GET8	menu_item_count			; get number of items
	VARARGS_GET8	menu_vertical_start		; get vertical start position of 1st menu item

	movf	menu_vertical_start,W			; excite flags
	bz		menu_processor_no_title			; no menu title text -> skip reading menu title text address

	VARARGS_GET16	menu_title_addr			; get address of menu title text

menu_processor_no_title:

	movff	TBLPTRL, menu_item_data_start+0	; store base address for menu_read_menu_item_data
	movff	TBLPTRH, menu_item_data_start+1	; ...
	movff	TBLPTRU, menu_item_data_start+2	; ...

	btfss	divemode						; in dive mode?
	bra		menu_processor_menu_title		; NO  - no frame in surface mode menu

	; required for menus with less entries than the calling menu but not so nice when setting up gas 6.... mH
	movlw	.1								; menu_pos_cur = 1 ?
	cpfsgt	menu_pos_cur					; ...
	call	TFT_clear_divemode_menu			; YES - clear the menu

	; draw a frame around the dive mode menu
	movf	pallet_color_mask,W				; get mask color into WREG
	WIN_FRAME_COLOR dm_menu_row, dm_menu_lower, dm_menu_left ,dm_menu_right	; top, bottom, left, right
	bra		menu_processor_menu_body		; the dive mode menu has no menu title and footer

menu_processor_menu_title:
	; prepare screen
	clrf	CCP1CON							; stop PWM
	bcf		PORTC,2							; fade out backlight
	call	TFT_ClearScreen					; clear screen

	; draw menu title
	WIN_BOX_BLACK   .2,.23,.0,.159			; clear menu title area
	WIN_STD .0, .2							; set menu title font and position
	FONT_COLOR color_greenish				; set menu title font color
	movff	menu_title_addr+0,FSR1L			; point to multi-lingual menu title text
	movff	menu_title_addr+1,FSR1H			; ...
	call	strcpy_text_FSR					; copy translated text into the buffer
	movf	FSR2L,W							; get title text length
	mullw	.9								; compute title length in pixels_x2
	bcf		STATUS,C						; divide by 2
	rrcf	PRODL							; ...
	movf	PRODL,W							; get result into WREG
	sublw	.80								; compute 80 (screen center position) - half title width in pixel_x2
	movwf	win_leftx2						; set result as horizontal start position
	movlw	MAX_LINE_LENGTH_TITLE			; load max allowed length of a menu title
	movwf	FSR2L							; set buffer pointer to end of max length
	clrf	INDF2							; terminate string          at max length
	PRINT									; output menu title

	; draw footer line
	FONT_COLOR_MEMO							; select default color
	WIN_TINY   .5, .224						; tiny font, left position
	STRCPY_TEXT_PRINT tNext					; print "Next"
	WIN_TINY .124, .224						; tiny font, righ position
	STRCPY_TEXT_PRINT tEnter				; print "Enter"

menu_processor_menu_body:
	FONT_SIZE FT_SMALL						; select font size
	bra		menu_vertical					; draw the menu items


;-----------------------------------------------------------------------------
; Helper Function - call Callback-Function to draw the Menu Item Title
;
menu_processor_call_title:
	movff	menu_title_addr+2,PCLATU		; execute computed goto
	movff	menu_title_addr+1,PCLATH		; ...
	movf	menu_title_addr+0,W				; ...
	movwf	PCL								; ...


;-----------------------------------------------------------------------------
; Clear all memorized Menu Item Selections and restart with Cursor on first Item
;
	global	menu_processor_reset
menu_processor_reset:
	clrf	menustack						; clear                  first stack position
	clrf	menustack_pointer				; set stack pointer   to first stack position
	clrf	selected_item					; set cursor position to first menu item
	return									; done


;-----------------------------------------------------------------------------
; Pull / Double-Pull Cursor Position from Stack
;
	global	menu_processor_double_pop
	global	menu_processor_pop
menu_processor_double_pop:
	decf	menustack_pointer,F				; decrement stack pointer
menu_processor_pop:
	decf	menustack_pointer,F				; decrement stack pointer
	btfsc	menustack_pointer,7				; did the stack pointer under-run?
	clrf	menustack_pointer				; YES - reset stack pointer to first stack position
	movf	menustack_pointer,W				; load stack pointer into WREG
	lfsr	FSR2,menustack					; load base  address of menu stack
	movff	PLUSW2,selected_item			; retrieve cursor position from stack
	return									; done


;-----------------------------------------------------------------------------
; Push Cursor Position onto Stack
;
menu_processor_push:
	lfsr	FSR2,menustack					; load base  address of menu stack
	movf	menustack_pointer,W				; load stack pointer into WREG
	movff	selected_item,PLUSW2			; save cursor position to stack
	incf	menustack_pointer,W				; increment stack pointer, park result in WREG
	btfss	WREG,3							; result < 8 ?
	movwf	menustack_pointer				; YES - update stack pointer
	clrf	selected_item					; set cursor to first item in new menu
	return									; done


;-----------------------------------------------------------------------------
; Helper Function - call Menu Item Function
;
menu_call_item_function:
	bcf		switch_right					; clear button event
	movf	selected_item,W					; copy current cursor position to WREG
	rcall	menu_read_menu_item_data		; read item function address
	movff	selected_item,PRODL				; pass cursor position (menu item number) to call function
	rcall	menu_processor_push				; push current cursor position onto stack
	clrf	                  PCLATU		; execute computed goto
	movff	item_funct_addr+1,PCLATH		; ...
	movf	item_funct_addr+0,W				; ...
	movwf	                  PCL			; ...


;-----------------------------------------------------------------------------
; Read Menu Item Data
;
menu_read_menu_item_data:
	cpfsgt	menu_item_count					; selected menu item valid?				|| * Safety Check * to prevent any computed
	clrf	WREG							; NO - change selection to first item	|| goto to an illegal random target address

	mullw	MENU_ITEM_DATA_SIZE				; compute menu item data offset
	movf	PRODL,W							; add offset to base address of menu data block and set up TBLPTR
	addwf	menu_item_data_start+0,W		; ...
	movwf	TBLPTRL							; ...
	movf	PRODH,W							; ...
	addwfc	menu_item_data_start+1,W		; ...
	movwf	TBLPTRH							; ...
	movlw	0								; ...
	addwfc	menu_item_data_start+2,W		; ...
	movwf	TBLPTRU							; ...

	VARARGS_GET16	item_title_addr			; read address of item title function or title text             | with embedded
	VARARGS_GET16	item_funct_addr			; read address of item call  function or option definition data | menu item type

	movlw	.2								; probe for menu item type = OPTION
	btfsc	item_funct_addr,0				; is type OPTION?
	bra		menu_read_menu_item_data_1		; YES

	movlw	.1								; probe for menu item type = MENU_CALL
	btfsc	item_title_addr,0				; is type MENU_CALL?
	bra		menu_read_menu_item_data_1		; YES

	movlw	.0								; must be MENU_DYNAMIC

menu_read_menu_item_data_1:
	movwf	item_type						; store menu item type
	bcf		item_title_addr+0,0				; strip menu item type encoding from addresses (reset to even addresses)
	bcf		item_funct_addr+0,0				; ...

	return									; done


;-----------------------------------------------------------------------------
; Menu HMI Operation
;
	global	menu_vertical
menu_vertical:
	rcall	menu_draw_menu_items			; draw all menu items
	movlw	CCP1CON_VALUE					; load PWM setting
	btfss	divemode						; in dive mode?
	movwf	CCP1CON							; NO - power-on backlight

menu_vertical_loop:
	movf	selected_item,W					; get cursor position into WREG
	rcall	menu_read_menu_item_data		; read menu item data
	movf	item_funct_addr+0,W				; check if execute function call address is NULL
	iorwf	item_funct_addr+1,W				; ...
	bz		next_line_menu					; YES - not selectable, step cursor to next menu item
	btfss	divemode						; NO  - in dive mode?
	rcall	menu_draw_cursor_surf			;       NO  - draw the cursor (main menu style)
	btfss	imprint_time_date				;     - currently imprinting the current time & date?
	bra		menu_line_loop_pre1				;       NO  - skip
	btfss	switch_right					;       YES - right button pressed, i.e. time or date changed?
	bra		menu_line_loop_pre1				;             NO  - skip
	call	TFT_imprint_time_date_fast		;             YES - show a fast response on the screen (may momentarily show an illegal day/month combination)
	call	rtc_set_rtc						;                 - update time and date on RTC module (corrects illegal day/month combinations)

menu_line_loop_pre1:
	bcf		switch_right					; clear left-over right button event
	bcf		switch_left						; clear left-over left  button event

menu_line_loop_pre2:
	btfsc	divemode						; in dive mode?
	goto	divemode_option_divemenu_return	; YES - return to it
	call	reset_timeout_surfmode			; NO  - reset timeout

menu_line_loop:
	call	housekeeping					;     - handle data imprinting, screen dump request, timeout and entering dive mode
	btfsc	switch_right					;     - right button pressed?
	bra		do_line_menu					;       YES - execute menu item function
	btfss	switch_left						;       NO  - left button pressed?
	bra		menu_line_loop					;             NO  - loop
next_line_menu:								;             YES - step cursor to next menu item
	bcf		switch_left						;                 - clear button event
	incf	selected_item,F					;                 - increment cursor position to next item
	movf	selected_item,W					;                 - copy new item number to WREG
	cpfseq	menu_item_count					;                 - new item number beyond number of menu items?
	bra		menu_vertical_loop				;                   NO  - redraw cursor
	clrf	selected_item					;                   YES - reset cursor position to first item
	bra		menu_vertical_loop				;                       - redraw cursor


;-----------------------------------------------------------------------------
; Execute Menu Item Function
;
	global	do_line_menu
do_line_menu:
	decf	menu_pos_cur,W					; get selected menu item (0-5) into WREG
	btfsc	divemode						; in dive mode?
	movwf	selected_item					; YES - take selected menu item from dive mode
	movf	selected_item,W					; copy       selected menu item to WREG
	rcall	menu_read_menu_item_data		; read menu item data
	movf	item_type,W						; switch on menu item type
	bz		menu_do_line_call				; -> 0: call (with dynamic title)
	dcfsnz	WREG							;
	bra		menu_do_line_call				; -> 1: call (with fixed   title)
	dcfsnz	WREG							;
	bra		menu_do_line_option				; -> 2: option
	bra		menu_line_loop_pre2				; else do nothing

menu_do_line_call:
	rcall	menu_call_item_function			; push current cursor position onto stack and call menu item function
	rcall	menu_processor_pop				; get back cursor position
	bra		menu_vertical					; re-draw the menu

menu_do_line_option:
	movff	option_addr+0,FSR0L				; get address of option definition data
	movff	option_addr+1,FSR0H				; ...
	btfsc	option_addr+1,4					; shall stop at max value?
	bsf		option_stop_at_max				; YES - set flag
	btfsc	option_addr+1,6					; is the selected option an  option group member?
	call	option_adjust_group_member		; YES -  adjust address to selected group member
	btfss	option_addr+1,5					; shall increment?
	call	option_inc						; YES - increment option value
	btfsc	option_addr+1,5					; shall decrement?
	call	option_dec						; YES - decrement option value
	bcf		option_stop_at_max				; revert to default (= wrap-around after max value)
	bra		menu_vertical					; re-draw the menu


;-----------------------------------------------------------------------------
; Draw all Menu Items
;
menu_draw_menu_items:
	btfss	divemode						; in dive mode?
	bra		menu_draw_lines_surfmode		; NO
	;bra	menu_draw_lines_divemode		; YES

	global	menu_draw_lines_divemode
menu_draw_lines_divemode:
	movlw	dm_menu_item1_row				; get row    position for 1st item
	movwf	win_top							; set vertical  output position
	movlw	dm_menu_item1_column			; get column position for 1st item
	movwf	win_leftx2						; set horizontal output position
	clrf	menu_item_start					; set first item in menu block as first item to draw
	movff	menu_item_count,menu_pos_max	; copy number of item in menu block to menu_pos_max
	bra		menu_draw_menu_items_common		; continue with common part

menu_draw_lines_surfmode:
	WIN_SMALL MENU_LEFT, 0					; initialize start position and font
	movff	menu_vertical_start,win_top		; set vertical output position
	clrf	menu_item_start					; set first item in menu block as first item to draw

 IFDEF scrolling_menu_enabled
	; does the menu have more than 7 item ?
	movf	menu_item_count,W				; get number of menu items
	addlw	-(MENU_LINES_MAX+1)				; more than 7 item?
	bn		menu_draw_menu_items_common		; NO - continue with common part
	movf	selected_item,W					; YES - compute first item to be drawn as current cursor position - 6
	addlw	-(MENU_LINES_MAX-1)				;     - ...
	btfsc	STATUS,N						;     - is this < 0 ?
	clrf	WREG							;       YES - revert to starting from first item
	movwf	menu_item_start					;     - set first item to be drawn
 ENDIF	; scrolling_menu_enabled

menu_draw_menu_items_common:
	movff	menu_item_start,menu_item_curr	; initialize menu item counter
	FONT_SIZE FT_SMALL						; set font size

menu_draw_menu_items_loop:
	FONT_COLOR_MEMO							; set default font color (may be changed by dynamic titles)
	movf	menu_item_curr,W				; get menu item to draw
	rcall	menu_read_menu_item_data		; read menu item data
	movf	item_type,W						; switch on menu item type:
	bz		 menu_draw_menu_item_dynamic 	; -> 0: call with dynamic title
	dcfsnz	WREG							;
	bra		menu_draw_menu_item_call		; -> 1: call with fixed   title
	dcfsnz	WREG							;
	bra		menu_draw_menu_item_option		; -> 2: option increment
	bra		menu_draw_menu_item_print		; no output in case of illegal type

menu_draw_menu_item_dynamic:

	movf	item_title_addr+0,W				; check if call address is NULL
	iorwf	item_title_addr+1,W				; ...
	btfsc	STATUS,Z						; is null?
	bra		menu_draw_menu_item_no_print	; YES - no printing on this menu line
	INIT_BUFFER								; NO  - initialize buffer
	movff	menu_item_curr,PRODL			;     - pass menu item position to call function
	rcall	menu_text_call					;     - call dynamic title function
	bra		menu_draw_menu_item_print		;     - print menu item

menu_draw_menu_item_call:
	movff	item_title_addr+0,FSR1L			; point to multi-lingual text
	movff	item_title_addr+1,FSR1H			; ...
	call	strcpy_text_FSR					; copy translated text to buffer
	bra		menu_draw_menu_item_print		; print menu item

menu_draw_menu_item_option:
	movff	item_title_addr+0,FSR1L			; point to multi-lingual text
	movff	item_title_addr+1,FSR1H			; ...
	call	strcpy_text_FSR					; copy translated text to buffer
	movff	option_addr+0,FSR0L				; hand over address of option definition data
	movff	option_addr+1,FSR0H				; ...
	btfsc	option_addr+1,6					; is the selected option an  option group member?
	call	option_adjust_group_member		; YES -  adjust address to selected group member
	btfss	block_option_value				; displaying of option value suspended?
	call	option_draw						; NO - draw option value
	;bra	menu_draw_menu_item_print		; print menu item

menu_draw_menu_item_print:
	movlw	MAX_LINE_LENGTH_SURF			; load               maximum length for a surface   menu item
	btfsc	divemode						; in dive mode?
	movlw	MAX_LINE_LENGTH_DIVE			; YES - replace with maximum length for a dive mode menu item
	call	TFT_buffer_trim_length			; fill up or cut buffer to max length
	PRINT									; print menu item to screen
	;bra	menu_draw_menu_item_no_print	; continue with after-print actions

menu_draw_menu_item_no_print:
	movlw	MENU_HEIGHT_SURF				; get menu items     vertical spacing for surface mode
	btfsc	divemode						; in dive mode?
	movlw	MENU_HEIGHT_DIVE				; YES - replace with vertical spacing for dive    mode

	addwf	win_top,F						; adjust vertical output position
	incf	menu_item_curr,F				; go to next menu item

	btfss	divemode						; in dive mode?
	bra		menu_draw_menu_item_surfmode	; NO
	;bra	menu_draw_menu_item_divemode	; YES

menu_draw_menu_item_divemode:
	movlw	.3								; load a 3
	cpfseq	menu_item_curr					; just done menu item 3 ?
	bra		menu_draw_menu_item_common		; NO  - continue with common part
	movlw	dm_menu_item4_row				; YES - set vertical   position for 2nd column
	movff	WREG,win_top					;     - ...
	movlw	dm_menu_item4_column			;     - set horizontal position for 2nd column
	movff	WREG,win_leftx2					;     - ...
	bra		menu_draw_menu_item_common		;     - continue with common part

menu_draw_menu_item_surfmode:
 IFDEF scrolling_menu_enabled
	movf	menu_item_start,W				; get the number of the menu item that menu drawing started with
	subwf	menu_item_curr,W				; compute how many item have been drawn already
	xorlw	MENU_LINES_MAX					; compare with how max item fit the screen
	btfsc	STATUS,Z						; screen full?
	return									; YES - done
	;bra	menu_draw_menu_item_common		; NO  - continue with common part
 ENDIF	; scrolling_menu_enabled

menu_draw_menu_item_common:
	movf	menu_item_curr,W				; get current menu item
	xorwf	menu_item_count,W				; compare with total number of menu items, more item to do?
	bnz		menu_draw_menu_items_loop		; YES - loop
	return									; NO  - done


;-----------------------------------------------------------------------------
; Helper Function - call Function for dynamic Title
;
menu_text_call:
	clrf	                  PCLATU		; execute a computed goto
	movff	item_title_addr+1,PCLATH		; ...
	movf	item_title_addr+0,W				; ...
	movwf	                  PCL			; ...


;-----------------------------------------------------------------------------
; Draw the Cursor (Main Menu Style)
;
menu_draw_cursor_surf:
	WIN_LEFT 	MENU_LEFT-8					; set horizontal  start of cursor column
	WIN_WIDTH	.6							; set width             of cursor column
	WIN_HEIGHT	.223						; set preliminary hight of cursor column

	movf	menu_vertical_start,W			; get vertical    start of menu items
	movwf	win_top							; set vertical    start of cursor column
	subwf	win_height,F					; final hight = prelim.height - vertical start

	clrf	WREG							; set color to black
	BOX_COLOR								; clear cursor area

	movf	menu_item_start,W				; get number of menu item that is on the first line
	subwf	selected_item,W					; compute line number of current menu item

	mullw	MENU_HEIGHT_SURF				; multiply line number with vertical menu items spacing
	movf	PRODL,W							; get computed vertical offset
	addwf	menu_vertical_start,W			; add offset to vertical start position
	movwf	win_top							; set final vertical position
	bra		menu_draw_cursor_common			; print cursor and return


;-----------------------------------------------------------------------------
; Draw the Cursor (Dive Mode Style)
;
	global	menu_draw_cursor_dive
menu_draw_cursor_dive:
	; clear cursor areas
	WIN_BOX_BLACK dm_menu_row+.1, dm_menu_lower-.1, dm_menu_item1_column-.8, dm_menu_item1_column-.1
	WIN_BOX_BLACK dm_menu_row+.1, dm_menu_lower-.1, dm_menu_item4_column-.8, dm_menu_item4_column-.1

	movlw	dm_menu_item1_column-.8			; load position of left column
	btfsc	menu_pos_cur,2					; cursor at menu item 4..6 ?
	movlw	dm_menu_item4_column-.8			; YES - replace with position of right column
	movwf	win_leftx2						; set horizontal position

	decf	menu_pos_cur,W					; get cursor position as 0..5 into WREG
	btfsc	menu_pos_cur,2					; cursor at menu item 4..6 ?
	addlw	-.3								; YES - subtract 3 to get line number in right column

	mullw	MENU_HEIGHT_DIVE				; multiply line number with vertical menu items spacing
	movf	PRODL,W							; get computed vertical offset
	addlw	dm_menu_item1_row				; add offset to vertical start position
	movwf	win_top							; set final vertical position
	;bra	menu_draw_cursor_common			; print cursor and return


;-----------------------------------------------------------------------------
; Helper Function - common Part of drawing the Cursor
;
menu_draw_cursor_common:
	FONT_COLOR_MEMO							; set font color
	FONT_SIZE FT_SMALL						; set font size
	STRCPY_PRINT "\xb7"						; print cursor
	return									; done

;-----------------------------------------------------------------------------

	END