diff 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 diff
--- a/src/menu_processor.asm	Thu Mar 05 15:06:14 2020 +0100
+++ b/src/menu_processor.asm	Tue Apr 28 17:34:31 2020 +0200
@@ -1,6 +1,6 @@
 ;=============================================================================
 ;
-;   File menu_processor.asm                   combined next generation V3.08.6
+;   File menu_processor.asm                 * combined next generation V3.09.5
 ;
 ;   Routines to handle all hwOS graphic/text menus.
 ;
@@ -24,139 +24,136 @@
 #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_TITLE_FONT			WIN_STD		; font needs to contain lower and UPPER chars
-#define MENU_LINE_FONT			WIN_SMALL	; font needs to contain lower and UPPER chars
 #define MENU_LEFT				.20			; position of first menu item
-#define MENU_HEIGHT				.27			; spacing between menu lines
+#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 MENU_LINE_MAX_LENGTH	.20			; length in characters
-#define option_item				proc_item
+#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
 
-
-	extern	aa_wordprocessor
-	extern	option_inc
-	extern	option_draw
-	extern	TFT_clear_divemode_menu
-	extern	TFT_divemask_color
-	extern	rtc_set_rtc
-	extern	divemode_option_divemenu_return
-	extern	TFT_fillup_with_spaces
+; Alias for easier code reading
+#define option_addr				item_funct_addr
 
 
-menu_proc	CODE
-
-;=============================================================================
-; menu handler
-;
-; Input:    TBLPTR = addr of menu block
-
-	global	menu_processor
-menu_processor:
-;	btfss	divemode						; in dive mode?
-;	call	request_speed_fastest			; NO  - request CPU speed change to fastest speed
-	;---- Read menu block ------------------------------------------------
-	VARARGS_BEGIN							; read inline PROM data
-	clrf	STKPTR							; never return from here
-	VARARGS_GET8	item_max				; get number of items
-	VARARGS_GET8	menu_flags				; get flags
-	VARARGS_GET24	menu_title				; get pointer to menu title
-	VARARGS_GET8	menu_center				; vertical position
-	movff	TBLPTRL, menu_block+0			; save base address for menu_read_item
-	movff	TBLPTRH, menu_block+1			; ...
-	movff	TBLPTRU, menu_block+2			; ...
-	btfss	divemode						; in dive mode?
-	bra		menu_processor0					; NO
+	extern	option_adjust_group_member
+	extern	option_inc
+	extern	option_dec
+	extern	option_draw
 
-	; Required for menus with less entries than the calling menu but not so nice when setting up gas 6.... mH
-	movlw	.1
-	cpfsgt	menu_pos_cur					; only if menu_pos_cur = 1...
-	call	TFT_clear_divemode_menu			; ... clear the menu!
-	; Draw one frame around the dive mode menu
-	call	TFT_divemask_color
-	WIN_FRAME_COLOR16 dm_menu_row, dm_menu_lower, dm_menu_left ,dm_menu_right	; top, bottom, left, right
-	call	TFT_standard_color
-
-	bra		menu_processor1					; skip next code segment in dive mode
-
-menu_processor0:
-	;---- draw menu title ------------------------------------------------
-	clrf	CCP1CON							; stop PWM
-	bcf		PORTC,2							; pull PWM out to GND
-	call	TFT_ClearScreen
-	rcall	menu_processor_title
-	rcall	menu_processor_bottom_line
-
-menu_processor1:
-	WIN_FONT FT_SMALL
-
-	;---- Select menu type -----------------------------------------------
-	bra		menu_vertical
+	extern	rtc_set_rtc
+	extern	divemode_option_divemenu_return
 
 
 ;=============================================================================
-; draw menu bottom line
-;
-menu_processor_bottom_line:
-	;---- Draw bottom line -----------------------------------------------
-	TEXT_TINY .5,         .240-.16, tNext
-	TEXT_TINY .160-.6*.6, .240-.16, tEnter
-	goto	TFT_standard_color				; ...and return
+menu_proc	CODE
+;=============================================================================
 
-;=============================================================================
-; (re-)draw menu title
+
+;-----------------------------------------------------------------------------
+; Entry Point for Menu Processor, called by MENU_BEGIN Macros
 ;
-menu_processor_title:
-	WIN_BOX_BLACK   .2,.23,.0,.159			; clear menu title
-	MENU_TITLE_FONT .0, .2					; menu title positioning
-	btfss	menu_flags,0					; static or dynamic title?
-	bra		menu_processor_static_title		; static  title
-	rcall	menu_processor_call_title		; dynamic title - add gas, detail and color
-	bra		menu_processor_title_1
+	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:
 
-menu_processor_static_title:
-	movff	menu_title+0,FSR1L				; just copy string
-	movff	menu_title+1,FSR1H
-	call	strcpy_text
+	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_title_1:
-	WIN_COLOR color_greenish
-	movf	FSR2L,W							; get title length
-	mullw	.9								; convert to half pixels
-	bcf		STATUS,C						; clear carry
-	rrcf	PRODL							; /2
-	movf	PRODL,W							; back to WREG
-	sublw	.80								; 80 - width
-	movwf	win_leftx2						; aligned to center
-	movlw	.0								; string termination code
-	movff	WREG,buffer+.17					; limit to 17 chars (std font max.)
-	call	aa_wordprocessor
-	call	TFT_standard_color
-	return
+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
 
-;=============================================================================
-; Call dynamic proc for 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+2,PCLATU				; execute computed goto
-	movff	menu_title+1,PCLATH
-	movf	menu_title+0,W
-	movwf	PCL
+	movff	menu_title_addr+2,PCLATU		; execute computed goto
+	movff	menu_title_addr+1,PCLATH		; ...
+	movf	menu_title_addr+0,W				; ...
+	movwf	PCL								; ...
 
-;=============================================================================
-; Restart with first icon/line selected
+
+;-----------------------------------------------------------------------------
+; 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 last menu item to first item
-	return
+	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:
@@ -167,300 +164,362 @@
 	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 menu item from 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 menu item to stack
+	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 to first item in new menu
+	clrf	selected_item					; set cursor to first item in new menu
 	return									; done
 
 
-;---- Execute menu selection -------------------------------------------------
-do_menu_item:
-	bcf		switch_right					; clear left-over button event
-	movf	selected_item,W					; reread proc address from table
-	rcall	menu_read_item					; (destroys PROD)
-	movff	selected_item,PRODL				; pass along selected line
-	rcall	menu_processor_push				; remember where we got from (clears selected_item)
-	movff	proc_item+2,PCLATU				; then execute computed goto
-	movff	proc_item+1,PCLATH
-	movf	proc_item+0,W
-	movwf	PCL
+;-----------------------------------------------------------------------------
+; 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			; ...
 
-;=============================================================================
-; Get current item from table.
-;
-; Input  : Item number in WREG, menu_block.
-; Output : icon_large, text_item, proc_item 16bits pointers.
-; Trashed: PROD, WREG
+
+;-----------------------------------------------------------------------------
+; Read Menu Item Data
 ;
-menu_read_item:
-	mullw	.10								; 10 bytes per item
-	movf	PRODL,W							; then do a 24 bits add
-	addwf	menu_block+0,W					; with menu_block, and
-	movwf	TBLPTRL							; setup TBLPTR
-	movf	PRODH,W
-	addwfc	menu_block+1,W
-	movwf	TBLPTRH
-	movlw	0
-	addwfc	menu_block+2,W
-	movwf	TBLPTRU
-	VARARGS_GET8	value_type				; read 10 bytes of item data
-	VARARGS_GET24	dynamic_item
-	VARARGS_GET24	proc_item
-	VARARGS_GET8	WREG					; skip dummy byte
-	VARARGS_GET16	text_item
+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
 
-	return
+	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
 
-;=============================================================================
-; Vertical menu - set of line/value to choose from,
-;                 entry point to update lines already shown
+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_lines					; always re-draw whole menu
-	movlw	CCP1CON_VALUE					; see hwos.inc
+	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_1:
-	movf	selected_item,W					; copy current menu item selection to WREG
-	rcall	menu_read_item					; get current menu item data
-	movf	proc_item+0,W					; check if proc address is NULL
-	iorwf	proc_item+1,W
-	bz		next_line_menu					; YES - not selectable
-	btfss	divemode						; in dive mode?
-	rcall	menu_draw_selected_line			; NO
-	btfss	imprint_time_date				; currently imprinting the current time & date?
-	bra		menu_line_loop_pre1				; NO
-	btfss	switch_right					; YES - right button pressed, i.e. time or date changed?
-	bra		menu_line_loop_pre1				;       NO
-	call	TFT_show_time_date_menu_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_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:
-	btfsc	imprint_color_schemes			; in the color scheme menu?
-	call	TFT_show_color_schemes			; YES - update the color schemes
-
-menu_line_loop_pre2:
 	bcf		switch_right					; clear left-over right button event
 	bcf		switch_left						; clear left-over left  button event
 
-menu_line_loop_pre3:
+menu_line_loop_pre2:
 	btfsc	divemode						; in dive mode?
 	goto	divemode_option_divemenu_return	; YES - return to it
-	;bra	menu_line_loop_surface			; NO  - proceed to surface mode dispatcher
+	call	reset_timeout_surfmode			; NO  - reset timeout
 
-; dispatcher for surface mode menus
-menu_line_loop_surface:
-	call	reset_timeout_surfmode			; 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 - type dependent
-	btfsc	switch_left						; left button pressed?
-	bra		next_line_menu					; YES - goto next item
-	bra		menu_line_loop					; NO to both - 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
 
 
-;---- Move to menu's next line
-next_line_menu:
-	bcf		switch_left						; clear button event
-	incf	selected_item,F					; select next item
-	movf	selected_item,W					; copy item number to WREG
-	cpfseq	item_max						; item number == max ?
-	bra		menu_vertical_1					; NO  - redraw cursor
-	clrf	selected_item					; YES - wrap-around to first item
-	bra		menu_vertical_1					; then redraw cursor
-
+;-----------------------------------------------------------------------------
+; Execute Menu Item Function
+;
 	global	do_line_menu
 do_line_menu:
-	decf	menu_pos_cur,W					; menu_processor needs 0-5
+	decf	menu_pos_cur,W					; get selected menu item (0-5) into WREG
 	btfsc	divemode						; in dive mode?
-	movwf	selected_item					; YES - set selected item from WREG
-	movf	selected_item,W					; read selected descriptor
-	rcall	menu_read_item
-	movf	value_type,W					; switch on data type
-	bz		menu_do_line_call				; CALL
-	dcfsnz	WREG
-	bra		menu_do_line_call				; STRING: do as call
-	dcfsnz	WREG
-	bra		menu_do_line_option				; OPTION
-	dcfsnz	WREG
-	bra		menu_do_line_call				; DYNAMIC: do as call
-	bra		menu_line_loop_pre3				; else do nothing
+	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
 
-;---- CALL
-menu_do_line_call:
-	rcall	do_menu_item					; same as icon menu: calculated goto
-	rcall	menu_processor_pop				; back to same line,
-	bra		menu_vertical					; then continue into menu...
+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			; ...
+
 
-;---- Call option specific increment subroutine
-menu_do_line_option:
-	movff	option_item+0,FSR0L				; get option handle
-	movff	option_item+1,FSR0H
-	call	option_inc						; increment
-	movff	selected_item,PRODL				; pass selection to callback
-	rcall	menu_text_call
-	bra		menu_vertical					; redraw all lines
+;-----------------------------------------------------------------------------
+; 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
 
 ;-----------------------------------------------------------------------------
 
-	global	menu_draw_lines_divemode		; entry point for re-drawing of the menu to update color-coding of gases
-menu_draw_lines_divemode:
-	movlw	dm_menu_item1_row
-	movff	WREG,win_top
-	movlw	dm_menu_item1_column
-	movff	WREG,win_leftx2
-	clrf	start_item
-	movff	item_max,menu_pos_max			; copy item_max for dive mode cursor routine
-	bra		menu_draw_lines_2
-
-menu_draw_lines:
-	btfsc	divemode						; in dive mode?
-	bra		menu_draw_lines_divemode		; YES
-	btfsc	menu_flags,0					; dynamic title?
-	rcall	menu_processor_title			; YES - redraw it then
-	MENU_LINE_FONT MENU_LEFT, 0				; initialize start position/font
-	movff	menu_center,win_top				; computed in menu block
-
-	; Does the menu have more than 6 lines ?
-	movf	item_max,W
-	addlw	-(MENU_LINES_MAX+1)				;
-	bnn		menu_draw_long_menu				; bra if >= 7
-	clrf	start_item
-	bra		menu_draw_lines_2
-
-menu_draw_long_menu:
-	movf	selected_item,W					; start at selected-6
-	addlw	-(MENU_LINES_MAX-1)
-	btfsc	STATUS,N						; is this < 0 ?
-	clrf	WREG							; YES - start from top instead
-	movwf	start_item
-
-menu_draw_lines_2:
-	movff	start_item, menu_item
-	WIN_FONT FT_SMALL						; set font size
-
-menu_draw_lines_1:
-	call	TFT_standard_color				; set default text color
-	movf	menu_item,W
-	rcall	menu_read_item
-	movf	value_type,W					; switch on data type
-	bz		menu_draw_line_call
-	dcfsnz	WREG
-	bra		menu_draw_line_string
-	dcfsnz	WREG
-	bra		menu_draw_line_option
-	dcfsnz	WREG
-	bra		menu_draw_line_dynamic
-	bra		menu_draw_line_none
-
-menu_draw_line_string:
-	movff	text_item+0,TBLPTRL				; read not-translated string from PROM
-	movff	text_item+1,TBLPTRH
-	call	strcpy_prom						; copy in buffer
-	bra		menu_draw_line_none
-
-menu_draw_line_call:
-	movff	text_item+0,FSR1L				; read string from PROM
-	movff	text_item+1,FSR1H
-	call	strcpy_text						; copy in buffer
-	bra		menu_draw_line_none
-
-menu_draw_line_option:
-	movff	text_item+0,FSR1L				; read string from PROM
-	movff	text_item+1,FSR1H
-	call	strcpy_text						; copy in buffer
-	movff	option_item+0,FSR0L				; retrieve option handle
-	movff	option_item+1,FSR0H
-	btfss	block_option_value				; display of option value suspended?
-	call	option_draw						; NO - draw option (do not do it when setting time or date)
-	bra		menu_draw_line_none
-
-menu_draw_line_dynamic:
-	lfsr	FSR2,buffer
-	movff	menu_item,PRODL					; pass item to callback
-	rcall	menu_text_call					; push return address
-	bra		menu_draw_line_none
-
-; Computed goto to pointer inside dynamic_item:
-menu_text_call:
-	movf	dynamic_item+0,W				; check if callback is NULL
-	iorwf	dynamic_item+1,W
-	iorwf	dynamic_item+2,W
-	btfsc	STATUS,Z
-	return									; YES - don't call it
-	movff	dynamic_item+2,PCLATU			; prepare...
-	movff	dynamic_item+1,PCLATH
-	movf	dynamic_item+0,W
-	movwf	PCL								; ...and jump
-
-menu_draw_line_none:
-	btfsc	divemode						; in dive mode?
-	bra		menu_draw_line_none_divemode	; YES
-	movlw	MENU_LINE_MAX_LENGTH
-	call	TFT_fillup_with_spaces			; fill up FSR2 with spaces (total string length in #WREG)
-	clrf	WREG
-	movff	WREG,buffer+MENU_LINE_MAX_LENGTH ; NO - make sure won't be longer than MENU_LINE_MAX_LENGTH ch
-	call	aa_wordprocessor
-	bcf		win_invert						; clear flag for inverted output by default
-	movlw	MENU_HEIGHT						; NO - move to next line
-	addwf	win_top,F
-	incf	menu_item,F						; inc loop counter
-	movf	start_item,W					; first line (scrolled)
-	subwf	menu_item,W						; current - first
-	xorlw	MENU_LINES_MAX					; get max number of lines
-	btfsc	STATUS,Z						; already done max number of lines?
-	return									; YES
-menu_draw_line_none2:
-	movf	menu_item,W						; done item_max lines?
-	xorwf	item_max,W
-	btfss	STATUS,Z
-	bra		menu_draw_lines_1				; NO - loop...
-	return
-
-menu_draw_line_none_divemode:
-	movlw	.10
-	call	TFT_fillup_with_spaces			; fill up FSR2 with spaces (total string length in #WREG)
-	clrf	WREG
-	movff	WREG,buffer+.10
-	call	aa_wordprocessor				; draw the line
-	bcf		win_invert						; reset invert flag
-	movlw	.24								; dive mode menu spacing
-	addwf	win_top,F
-	incf	menu_item,F						; inc loop counter
-	movlw	.3
-	cpfseq	menu_item						; at position 4?
-	bra		menu_draw_line_none2			; NO
-	movlw	dm_menu_item4_row
-	movff	WREG,win_top					; reset row
-	movlw	dm_menu_item4_column
-	movff	WREG,win_leftx2					; new column
-	bra		menu_draw_line_none2			; done
-
-;-----------------------------------------------------------------------------
-; draw cursor
-menu_draw_selected_line:
-	WIN_BOX_BLACK .34,.221,MENU_LEFT-8,MENU_LEFT-2 ; clear left column
-	call	TFT_standard_color
-	WIN_SMALL MENU_LEFT-8, 0				; arrow symbol only in small font
-	movf	start_item,W					; first line (scrolled)
-	subwf	selected_item,W					; selected - first
-	mullw	MENU_HEIGHT						; 30 pixel by line
-	movf	PRODL,W							; result
-	addwf	menu_center,W					; added to first line
-	movwf	win_top							; and stored to position
-	STRCPY_PRINT "\xb7"						; print cursor
-	return
-
-	END
\ No newline at end of file
+	END