Mercurial > public > hwos_code
diff src/menu_processor.asm @ 604:ca4556fb60b9
bump to 2.99beta, work on 3.00 stable
author | heinrichsweikamp |
---|---|
date | Thu, 22 Nov 2018 19:47:26 +0100 |
parents | b455b31ce022 |
children | c5151a490d88 |
line wrap: on
line diff
--- a/src/menu_processor.asm Thu Oct 11 21:06:29 2018 +0200 +++ b/src/menu_processor.asm Thu Nov 22 19:47:26 2018 +0100 @@ -1,6 +1,6 @@ ;============================================================================= ; -; File menu_processor.asm REFACTORED VERSION V2.98 +; File menu_processor.asm REFACTORED VERSION V2.99d ; ; Routines to handle all hwOS graphic/text menus. ; @@ -10,8 +10,8 @@ ; 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 "hwos.inc" #include "strings.inc" #include "tft.inc" #include "varargs.inc" @@ -22,16 +22,17 @@ #include "tft_outputs.inc" #include "eeprom_rs232.inc" #include "adc_lightsensor.inc" +#include "i2c.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 +; NOTE: needs to be identical in .inc and .asm ! +#define MENU_LINES_MAX .7 ; 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_VCENTER .125 ; position on screen +#define MENU_LINE_MAX_LENGTH .20 ; length in characters #define option_item proc_item ; Other needed references @@ -46,7 +47,7 @@ extern TFT_fillup_with_spaces -basic CODE +menu_proc CODE ;============================================================================= ; menu handler. @@ -54,36 +55,36 @@ ; 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 ! + banksel common ; bank 1 + btfss divemode ; in divemode? + call speed_fastest ; NO - 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 + 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 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 + btfss divemode ; in divemode? + bra menu_processor0 ; NO + ; Required for menus with less entries than 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! + 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 + bra menu_processor1 ; skip next code segment in divemode menu_processor0: ;---- draw menu title ------------------------------------------------ clrf CCP1CON ; stop PWM - bcf PORTC,2 ; Pull PWM out to GND + bcf PORTC,2 ; pull PWM out to GND call TFT_ClearScreen rcall menu_processor_title rcall menu_processor_bottom_line @@ -95,50 +96,57 @@ ;---- Select menu type ----------------------------------------------- bra menu_vertical - global menu_processor_bottom_line + +;============================================================================= +; draw menu bottom line +; + global menu_processor_bottom_line,menu_processor_bottom_line_comm 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 +menu_processor_bottom_line_comm: + ; Serial Number and Firmware Version + WIN_TINY .32,.240-.16 STRCPY "#" call TFT_cat_serial STRCAT " v" call TFT_cat_firmware + STRCAT " " + call TFT_cat_beta_release STRCAT_PRINT "" call TFT_standard_color bcf win_invert return ;============================================================================= -; (re-)draw menu title. +; (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. + 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 menu_processor_static_title: - movff menu_title+0,FSR1L ; Just copy string. + 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 + 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 + 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.) + 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 @@ -147,13 +155,14 @@ ; Call dynamic proc for menu title: menu_processor_call_title: - movff menu_title+2,PCLATU ; Just execute computed goto. + movff menu_title+2,PCLATU ; execute computed goto movff menu_title+1,PCLATH movf menu_title+0,W movwf PCL ;============================================================================= -; Restart with first icon/line selected. +; Restart with first icon/line selected +; global menu_processor_reset menu_processor_reset: banksel menustack @@ -195,13 +204,13 @@ ;---- 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. + 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 ; (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 @@ -209,14 +218,13 @@ ;============================================================================= ; Get current item from table. ; -; Input : Item number in WREG, menu_block. -; -; Output: icon_large, text_item, proc_item 16bits pointers. +; Input : Item number in WREG, menu_block. +; Output : icon_large, text_item, proc_item 16bits pointers. +; Trashed: PROD, WREG ; -; Trashed: PROD, WREG menu_read_item: - mullw .10 ; 10 bytes per item. - movf PRODL,W ; Then do a 24bits add + 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 @@ -225,41 +233,41 @@ movlw 0 addwfc menu_block+2,W movwf TBLPTRU - VARARGS_GET8 value_type ; Read 10 bytes of item data + 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_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. +; 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 + btfss divemode ; in divemode? + clrf timeout_counter2 ; NO - 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 + rcall menu_draw_lines ; always re-draw whole menu + movlw CCP1CON_VALUE ; see hwos.inc + btfss divemode ; in divemode? + movwf CCP1CON ; NO - power-on backlight menu_vertical_1: - movf selected_item,W ; Get current item data + movf selected_item,W ; get current item data rcall menu_read_item - movf proc_item+0,W ; Check if pro address is NULL ? + 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 ; 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 + bz next_line_menu ; YES - not selectable + btfss divemode ; in divemode? + rcall menu_draw_selected_line ; NO + btfsc in_color_menu ; 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 @@ -286,92 +294,97 @@ dcfsnz lo,F movlw .31 cpfsgt day ; day ok? - bra menu_line_loop_pre1 ; OK! - movlw .1 ; not OK, set to 1st + bra menu_line_loop_pre1 ; YES + movlw .1 ; NO - 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 + 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 + btfss divemode ; in divemode? + call speed_normal ; NO menu_line_loop_pre3: - btfsc divemode ; In divemode? - goto divemode_option0_return ; Yes, return to it + btfsc divemode ; in divemode? + goto divemode_option0_return ; Yes - return to it menu_line_loop: btfsc switch_right - bra do_line_menu ; Type dependent + 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 + bra menu_line_loop1 ; NO - not yet... + btfsc menu_update_sensor_mv ; 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... + btfss onesecupdate ; new second? + bra menu_line_loop2 ; NO - not yet... + + IFDEF _rx_functions + btfsc FLAG_tr_enabled ; TR functions enabled? + call I2C_get_tankdata ; YES - get new tank data + btfsc menu_update_tank_pres ; in tank setup menu? + call TFT_menu_tank_pres ; YES - update tank press + ENDIF + call timeout_surfmode ; timeout on timeout_counter2 - call set_dive_modes ; check, if divemode must be entered + 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 + 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 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 + goto restart ; enter divemode if required + + IFDEF _screendump + btfsc enable_screen_dumps ; screendump enabled? + call TFT_dump_screen_check ; YES - check if requested and do it + ELSE + btfsc disable_comm_mode ; COMM mode disabled (happens during new battery procedure)? + bra menu_line_loop ; YES - loop + ENDIF + 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 + call comm_mode ; YES - start COMM mode + + bra menu_line_loop ; 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 ? + 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. + 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... + btfss divemode ; in divemode? + call speed_fastest ; NO +; 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 + movf selected_item,W ; read selected descriptor rcall menu_read_item - movf value_type,W ; Switch on data type + 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 @@ -379,22 +392,22 @@ 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... + 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... + 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+0,FSR0L ; get option handle movff option_item+1,FSR0H call option_inc ; increment - movff selected_item,PRODL ; Pass selection to callback. + movff selected_item,PRODL ; pass selection to callback. rcall menu_text_call - bra menu_vertical_2 ; redraw all lines... + bra menu_vertical_2 ; redraw all lines ;----------------------------------------------------------------------------- @@ -404,15 +417,15 @@ movlw dm_menu_item1_column movff WREG,win_leftx2 clrf start_item - movff item_max,menupos4 ; Copy item_max for divemode cursor routine + 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 + 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 ? @@ -423,20 +436,20 @@ bra menu_draw_lines_2 menu_draw_long_menu: - movf selected_item,W ; Start at selected-6 + 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. + 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 menu_draw_lines_1: - call TFT_standard_color ; Restore color after disabled lines. + 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 + movf value_type,W ; switch on data type bz menu_draw_line_call dcfsnz WREG bra menu_draw_line_string @@ -447,97 +460,98 @@ bra menu_draw_line_none menu_draw_line_string: - movff text_item+0,TBLPTRL ; Read not-translated string from PROM. + movff text_item+0,TBLPTRL ; read not-translated string from PROM movff text_item+1,TBLPTRH - call strcpy_prom ; Copy in buffer + 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+0,FSR1L ; read string from PROM movff text_item+1,FSR1H - call strcpy_text ; Copy in buffer + 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+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. + 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... + 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. + 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 + 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... + 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 ! + movwf PCL ; ...and jump menu_draw_line_none: - btfsc divemode ; In divemode? - bra menu_draw_line_none_divemode ; Yes + 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) + 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 + 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 + 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) + movf start_item,W ; first line (scrolled) subwf menu_item,W ; current - first - xorlw MENU_LINES_MAX ; Already done 6 lines ? + 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 ? + movf menu_item,W ; done item_max lines? xorwf item_max,W btfss STATUS,Z - bra menu_draw_lines_1 ; No: loop... + 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) + 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! + call aa_wordprocessor ; draw the line banksel common - bcf win_invert ; Reset invert flag + 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 + cpfseq menu_item ; at pos 4? + bra menu_draw_line_none2 ; NO movlw dm_menu_item4_row - movff WREG,win_top ; Reset row + movff WREG,win_top ; reset row movlw dm_menu_item4_column - movff WREG,win_leftx2 ; New column - bra menu_draw_line_none2 ; Done. + 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 + 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) + 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