view src/menu_processor.asm @ 591:146e50d2672f

BUGFIX: handle two deco gases configured to the same change depth
author heinrichsweikamp
date Thu, 15 Mar 2018 20:43:38 +0100
parents b455b31ce022
children ca4556fb60b9
line wrap: on
line source

;=============================================================================
;
;   File menu_processor.asm							REFACTORED VERSION V2.98
;
;   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 "convert.inc"
#include "hwos.inc"
#include "strings.inc"
#include "tft.inc"
#include "varargs.inc"
#include "wait.inc"
#include "start.inc"
#include "surfmode.inc"
#include "divemode.inc"
#include "tft_outputs.inc"
#include "eeprom_rs232.inc"
#include "adc_lightsensor.inc"


;NOTE: should be identical in .inc and .asm !
#define MENU_LINES_MAX			.7			; Number of lines per screen?
#define MENU_TITLE_FONT			WIN_STD		; Font should contains lower/UPPER alpha
#define MENU_LINE_FONT			WIN_SMALL	; Font should contains lower/UPPER alpha
#define MENU_LEFT				.20			; Position of first menu item
#define MENU_HEIGHT				.27			; Spacing between menu lines.
#define MENU_VCENTER			.125		; Position on screen.
#define MENU_LINE_MAX_LENGTH	.20			; Length in characters
#define option_item				proc_item

; Other needed references
	extern	aa_wordprocessor
	extern	option_inc
	extern	option_draw
	extern	comm_mode
	extern	TFT_clear_divemode_menu
	extern	TFT_divemask_color
	extern	rtc_set_rtc
	extern	divemode_option0_return
	extern	TFT_fillup_with_spaces


basic	CODE

;=============================================================================
; menu handler.
;
; Input:    TBLPTR = addr of menu block.
	global	menu_processor
menu_processor:
	banksel	common							; Bank1
	btfss	divemode						; Not in divemode
	call	speed_fastest					; Make it quick !
	;---- Read menu block ------------------------------------------------
	VARARGS_BEGIN							; Read inline PROM data
	clrf	STKPTR							; Never return, anyway...
	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 divemode?
	bra		menu_processor0					; No
	; Required for menus with less entries then the calling menu but not so nice when setting up gas 6.... mH
	movlw	.1
	cpfsgt	menupos1						; only if menupos1 = 1...
	call	TFT_clear_divemode_menu			; ... Clear the menu!
	; Draw one frame around the divemode 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					; Yes, skip some lines here

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:
	movlw	FT_SMALL
	movff	WREG, win_font

	;---- Select menu type -----------------------------------------------
	bra		menu_vertical

	global	menu_processor_bottom_line
menu_processor_bottom_line:
	;---- Draw bottom line -----------------------------------------------
	TEXT_TINY .5,         .240-.16, tNext
	TEXT_TINY .160-.6*.6, .240-.16, tEnter
	WIN_COLOR color_greenish
	; Serial and Firmware Version
	WIN_TINY .57,.240-.16
	STRCPY	"#"
	call	TFT_cat_serial
	STRCAT	" v"
	call	TFT_cat_firmware
	STRCAT_PRINT ""
	call	TFT_standard_color
	bcf		win_invert
	return

;=============================================================================
; (re-)draw menu title.
;
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
	rcall	menu_processor_call_title		; add gas, detail and color.
	bra		menu_processor_title_1

menu_processor_static_title:
	movff	menu_title+0,FSR1L				; Just copy string.
	movff	menu_title+1,FSR1H
	call	strcpy_text

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
	movff	WREG,buffer+.17					; limit to 17chars (Std font max.)
	call	aa_wordprocessor
	call	TFT_standard_color
	return

;=============================================================================
; Call dynamic proc for menu title:

menu_processor_call_title:
	movff	menu_title+2,PCLATU				; Just execute computed goto.
	movff	menu_title+1,PCLATH
	movf	menu_title+0,W
	movwf	PCL

;=============================================================================
; Restart with first icon/line selected.
	global	menu_processor_reset
menu_processor_reset:
	banksel	menustack
	lfsr	FSR2,menustack
	clrf	POSTINC2
	clrf	POSTINC2
	clrf	POSTINC2
	clrf	POSTINC2
	clrf	POSTINC2
	banksel	common
	clrf	selected_item
	return

	global	menu_processor_pop
menu_processor_pop:
	movff	menustack+0,selected_item
	movff	menustack+1,menustack+0
	movff	menustack+2,menustack+1
	movff	menustack+3,menustack+2
	movff	menustack+4,menustack+3
	return

	global	menu_processor_double_pop
menu_processor_double_pop:
	movff	menustack+1,selected_item
	movff	menustack+2,menustack+0
	movff	menustack+3,menustack+1
	movff	menustack+4,menustack+2
	return

menu_processor_push:
	movff	menustack+3,menustack+4
	movff	menustack+2,menustack+3
	movff	menustack+1,menustack+2
	movff	menustack+0,menustack+1
	movff	selected_item,menustack+0
	clrf	selected_item
	return

;---- Execute menu selection -------------------------------------------------
do_menu_item:
	bcf		switch_right					; Avoid loops.
	call	speed_normal					; Back to normal speed.
	movf	selected_item,W					; Reread proc address from table.
	rcall	menu_read_item					; (destroy PROD)
	movff	selected_item,PRODL				; Pass along selected line
	rcall	menu_processor_push				; Remember where we get 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

;=============================================================================
; Get current item from table.
;
; Input : Item number in WREG, menu_block.
;
; Output: icon_large, text_item, proc_item 16bits pointers.
;
; Trashed: PROD, WREG
menu_read_item:
	mullw	.10								; 10 bytes per item.
	movf	PRODL,W							; Then do a 24bits 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

	return

;=============================================================================
; Vertical menu : set of line/value to choose from.
; Entry point to update lines already shown.
;
	global	menu_vertical
menu_vertical:
	btfss	divemode						; Not in divemode
	clrf	timeout_counter2				; Reset timeout

menu_vertical_2:
	rcall	menu_draw_lines					; Always re-draw whole menu
	movlw	CCP1CON_VALUE					; See hwos.inc
	btfss	divemode						; Not in divemode
	movwf	CCP1CON							; Power-on backlight

menu_vertical_1:
	movf	selected_item,W					; Get current item data
	rcall	menu_read_item
	movf	proc_item+0,W					; Check if pro address is NULL ?
	iorwf	proc_item+1,W
	bz		next_line_menu					; YES: not selectable !
	btfss	divemode						; Not in divemode
	rcall	menu_draw_selected_line
	btfsc	in_color_menu					; =1: In the color scheme menu
	call	TFT_show_color_schemes			; Yes, update the color schemes
	btfss	settime_setdate					; In the Set Time or Set Date menu?
	bra		menu_line_loop_pre2				; no, skip all following
	movff	month,lo						; new month
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.28
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.30
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.30
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.30
	dcfsnz	lo,F
	movlw	.31
	dcfsnz	lo,F
	movlw	.30
	dcfsnz	lo,F
	movlw	.31
	cpfsgt	day								; day ok?
	bra		menu_line_loop_pre1				; OK!
	movlw	.1								; not OK, set to 1st
	movwf	day

menu_line_loop_pre1:
	btfsc	switch_right					; Enter pressed?
	call	rtc_set_rtc						; Yes, update mins,sec,hours,day,month and year to RTC module
	call	TFT_show_time_date_menu			; Update clock

menu_line_loop_pre2:
	bcf		switch_right
	bcf		switch_left
	btfss	divemode						; Not in divemode
	call	speed_normal

menu_line_loop_pre3:
	btfsc	divemode						; In divemode?
	goto	divemode_option0_return			; Yes, return to it

menu_line_loop:
	btfsc	switch_right
	bra		do_line_menu					; Type dependent
	btfsc	switch_left
	bra		next_line_menu
	btfss	quarter_second_update			; 1/4 second?
	bra		menu_line_loop1					; Not yet...
	btfsc	menu_show_sensors2				; In the "Calibrate" menu?
	call	TFT_menu_calibrate				; Yes, update mV data
	bcf		quarter_second_update			; Clear flag

menu_line_loop1:
	btfss	onesecupdate					; New second
	bra		menu_line_loop2					; not yet...
	call	timeout_surfmode				; timeout on timeout_counter2
	call	set_dive_modes					; check, if divemode must be entered
	call	get_battery_voltage				; gets battery voltage
	btfsc	settime_setdate					; In the Set Time or Set Date menu?
	call	TFT_show_time_date_menu			; Yes, update clock
	bcf		onesecupdate					; one second updates done

menu_line_loop2:
	btfsc	sleepmode						; Timeout?
	goto	restart							; Yes, back to surfacemode
	btfsc	divemode
	goto	restart							; Enter divemode if required
	btfsc	enable_screen_dumps				; =1: Ignore vin_usb, wait for "l" command (Screen dump)
	bra		menu_line_loop3
	btfsc	vusb_in							; USB plugged in?
	call	comm_mode						; Start COMM mode
	bra		menu_line_loop4
menu_line_loop3:
	btfss	vusb_in							; USB (still) plugged in?
	bcf		enable_screen_dumps				; No, clear flag
	call	rs232_get_byte
	btfsc	rs232_receive_overflow
	bra		menu_line_loop4
	movlw	"l"
	cpfseq	RCREG1
	bra		menu_line_loop4
	call	TFT_dump_screen					; Dump the screen contents
menu_line_loop4:
	bra		menu_line_loop

;---- Move to menu's next line
next_line_menu:
	btfss	divemode						; not in divemode
	call	speed_fastest
	bcf		switch_left						; Avoid looping.
	incf	selected_item,F					; Select next item.
	movf	selected_item,W					; Index == max ?
	cpfseq	item_max
	bra		menu_vertical_1					; NO: redraw cursor.
	clrf	selected_item					; YES: restart for item 0.
	bra	menu_vertical_1						; Then redraw cursor.

	global	do_line_menu
do_line_menu:
	btfss	divemode						; not in divemode
	call	speed_fastest
;	bcf		switch_right					; Avoid looping.
	decf	menupos1,W						; menu_processor needs 0-5...
	btfsc	divemode						; only in divemode
	movwf	selected_item
	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...

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

;---- 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_2					; redraw all lines...

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

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,menupos4				; Copy item_max for divemode cursor routine
	bra		menu_draw_lines_2

menu_draw_lines:
	btfsc	divemode						; in divemode?
	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				; Init 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)				; (max - 7)
	bnn		menu_draw_long_menu				; bra if (max >= 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						; This is <0 ?
	clrf	WREG							; YES: start from top instead.
	movwf	start_item

menu_draw_lines_2:
	movff	start_item, menu_item

menu_draw_lines_1:
	call	TFT_standard_color				; Restore color after disabled lines.
	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	settime_setdate					; Not in Time/Date menu...
	call	option_draw
	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 divemode?
	bra	menu_draw_line_none_divemode		; Yes
	movlw	MENU_LINE_MAX_LENGTH
	call	TFT_fillup_with_spaces			; Fillup 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
	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					; Already done 6 lines ?
	btfsc	STATUS,Z
	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!
	banksel	common
	bcf		win_invert						; Reset invert flag
	banksel	win_top
	movlw	.24								; divemode menu spacing
	addwf	win_top,F
	incf	menu_item,F						; inc loop counter
	movlw	.3
	cpfseq	menu_item						; At pos 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.

;-----------------------------------------------------------------------------
; Put a mark in front of the current line
menu_draw_selected_line:
	clrf	timeout_counter2				; Reset timeout
	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 pos.
	STRCPY_PRINT "\xb7"						; print cursor
	return

	END