;***************************************************************************************** ; Mega 128 Scope Controller Program ; (c) Martin Cibulski ;***************************************************************************************** ;***************************************************************************************** .DSEG ;Word offsets in a menu entry's jump table .EQU MNU_CALL_SHOW1 = 0 .EQU MNU_CALL_SHOW2 = 1 .EQU MNU_CALL_MAX_IND = 2 .EQU MNU_CALL_STARTIND = 3 .EQU MNU_CALL_FASTSTEP = 4 .EQU MNU_CALL_EXEC = 5 ;Byte offsets in a menu entry ; .EQU MNU_TEXT = 0 .EQU MNU_PARENT_PTR = 8 .EQU MNU_ADRESS = 10 .EQU MNU_ENTRY_SIZE = 12 .DSEG men_message: .byte 8 ;***************************************************************************************** mnu_parent: .byte 2 mnu_child: .byte 2 mnu_gpar_index: .byte 2 mnu_par_index: .byte 2 mnu_chi_index: .byte 2 mnu_index_step: .byte 2 mnu_lastgoto_db: .byte 1 mnu_lastgoto_ix: .byte 2 mnu_slowfunc_adr: .byte 2 mnu_slowfunc_r16: .byte 1 mnu_slowfunc_r17: .byte 1 mnu_slowfunc_r18: .byte 1 mnu_slowfunc_r19: .byte 1 ;***************************************************************************************** .CSEG mnu_init: ldi r16 ,low(men_root<<1) sts mnu_parent ,r16 ldi r16 ,high(men_root<<1) sts mnu_parent+1 ,r16 ldi r16 ,low(men_obj<<1) sts mnu_child ,r16 ldi r16 ,high(men_obj<<1) sts mnu_child+1 ,r16 clr r16 sts mnu_gpar_index ,r16 sts mnu_gpar_index+1 ,r16 sts mnu_par_index ,r16 sts mnu_par_index+1 ,r16 sts mnu_chi_index ,r16 sts mnu_chi_index+1 ,r16 ldi r16 ,1 sts mnu_index_step ,r16 clr r16 sts mnu_index_step+1 ,r16 clr r16 sts mnu_lastgoto_db ,r16 sts mnu_lastgoto_ix ,r16 sts mnu_lastgoto_ix+1 ,r16 clr r16 sts mnu_slowfunc_adr ,r16 sts mnu_slowfunc_adr+1,r16 ret ;***************************************************************************************** ;Menu Table ;Entry Name (label) Display Text Parent Entry Function Adress ;----------------------------------------------------------------------------------------- men_root: .db "MENU " .dw 0 ,0 ;----------------------------------------------------------------------------------------- men_obj: .db "OBJECTS " .dw men_root ,0 men_radec: .db "RA/DEC " .dw men_root ,fun_radec men_system: .db "SYSTEM " .dw men_root ,0 ;----------------------------------------------------------------------------------------- men_obj_dir: .db "OBJ_DIR " .dw men_obj ,fun_obj_dir men_obj_db: .db "OBJ_DB " .dw men_obj_dir ,fun_obj_db .db "GOTO " .dw men_obj_db ,fun_obj_goto .db "ADJUST " .dw men_obj_db ,fun_obj_adjust .db "ALIGN 1 " .dw men_obj_db ,fun_obj_align1 .db "ALIGN 2 " .dw men_obj_db ,fun_obj_align2 ;----------------------------------------------------------------------------------------- men_radec_ra: .db "SET RA " .dw men_radec ,fun_radec_ra men_radec_dec: .db "SET DEC " .dw men_radec ,fun_radec_dec men_sys_profiles: .db "PROFILES" .dw men_system ,0 men_sys_reset: .db "RESET " .dw men_system ,fun_reset men_sys_analysis: .db "ANALYSIS" .dw men_system ,0 ;----------------------------------------------------------------------------------------- men_radec_setra: .db "SET RA " .dw men_radec_ra ,fun_radec_setra men_radec_setdec: .db "SET DEC " .dw men_radec_dec ,fun_radec_setdec men_sys_prof_db: .db "********" .dw men_sys_profiles ,fun_profiles .db "ACTIVATE" .dw men_sys_prof_db ,fun_profile_act .db "DEFAULT " .dw men_sys_prof_db ,fun_prof_makedef ;----------------------------------------------------------------------------------------- .db "ON " .dw men_sys_analysis ,fun_sys_ana_on .db "OFF " .dw men_sys_analysis ,fun_sys_ana_off ;----------------------------------------------------------------------------------------- men_end: .db "> STOP <" .dw 0xFFFF ,0x0000 ;***************************************************************************************** ;Menu function RESET fun_reset: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP cli jmp 0x0000 ;MNU_CALL_EXEC ;***************************************************************************************** fun_obj_dir: rjmp fun_obj_dir_show1 ;MNU_CALL_SHOW1 rjmp fun_obj_dir_show2 ;MNU_CALL_SHOW2 rjmp fun_obj_dir_max_index ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_obj_dir_exec ;MNU_CALL_EXEC fun_obj_dir_show1: lds r16 ,mnu_par_index ldi xl ,low(men_message) ldi xh ,high(men_message) call obj_dir_get_longname call lcd_print_x1 set ret fun_obj_dir_show2: lds r16 ,mnu_chi_index ldi xl ,low(men_message) ldi xh ,high(men_message) call obj_dir_get_longname call lcd_print_x2 set ret fun_obj_dir_max_index: lds r16 ,obj_used_slots dec r16 clr r17 clr r18 set ret fun_obj_dir_exec: lds r16 ,mnu_chi_index call obj_db_open clt ret ;***************************************************************************************** fun_obj_db: rjmp fun_obj_db_show1 ;MNU_CALL_SHOW1 rjmp fun_obj_db_show2 ;MNU_CALL_SHOW2 rjmp fun_obj_db_max_index ;MNU_CALL_MAX_IND rjmp fun_obj_db_start_index ;MNU_CALL_STARTIND rjmp fun_obj_db_faststep ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC fun_obj_db_show1: ldi xl ,low(obj_ds_name) ldi xh ,high(obj_ds_name) call lcd_print_x1 set ret fun_obj_db_show2: lds r16 ,mnu_par_index call obj_db_open lds r16 ,mnu_chi_index lds r17 ,mnu_chi_index+1 call obj_db_read_dataset ldi xl ,low(obj_ds_name) ldi xh ,high(obj_ds_name) call lcd_print_x2 set ret fun_obj_db_max_index: lds r16 ,obj_db_datasets ;no of datasets in current db - 1 lds r17 ,obj_db_datasets+1 ;= no of last dataset clr r0 sec sbc r16 ,r0 sbc r17 ,r0 clr r18 ;no wraparound allowed set ret fun_obj_db_start_index: lds r16 ,mnu_lastgoto_db lds r17 ,mnu_par_index cpse r16 ,r17 ret lds r16 ,mnu_lastgoto_ix lds r17 ,mnu_lastgoto_ix+1 set ret fun_obj_db_faststep: lds r16 ,obj_db_datasets lds r17 ,obj_db_datasets+1 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 subi r16 ,low(-1) sbci r17 ,high(-1) set ret ;***************************************************************************************** fun_obj_adjust: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_obj_adjust_exec ;MNU_CALL_EXEC fun_obj_adjust_exec: in r16 ,SREG cli lds r0 ,mot_a_pos lds r1 ,mot_a_pos+1 lds r2 ,mot_a_pos+2 lds r3 ,mot_a_pos+3 lds r4 ,mot_b_pos lds r5 ,mot_b_pos+1 lds r6 ,mot_b_pos+2 lds r7 ,mot_b_pos+3 lds r8 ,clock lds r9 ,clock+1 lds r10 ,clock+2 lds r11 ,clock+3 out SREG ,r16 sts alg_az_steps3 ,r0 sts alg_az_steps3+1 ,r1 sts alg_az_steps3+2 ,r2 sts alg_az_steps3+3 ,r3 sts alg_alt_steps3 ,r4 sts alg_alt_steps3+1 ,r5 sts alg_alt_steps3+2 ,r6 sts alg_alt_steps3+3 ,r7 sts alg_time3 ,r8 sts alg_time3+1 ,r9 sts alg_time3+2 ,r10 sts alg_time3+3 ,r11 lds r1 ,obj_ds_int_ra ;little endian lds r0 ,obj_ds_int_ra+1 lds r3 ,obj_ds_int_dec lds r2 ,obj_ds_int_dec+1 sts alg_rectint3 ,r0 ;big endian sts alg_rectint3+1 ,r1 sts alg_declint3 ,r2 sts alg_declint3+1 ,r3 ldi r16 ,ALG_POS_NEW ;sts alg_newpos3 ,r16 ldi r16 ,0 ldi xh ,high(alg_ana_save) ldi xl ,low(alg_ana_save) rcall mnu_slowfunc_set rcall mnu_out call lcd_modemove rjmp fun_exec_message_ok ;***************************************************************************************** fun_obj_align1: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_obj_align1_exec ;MNU_CALL_EXEC fun_obj_align1_exec: in r16 ,SREG cli lds r0 ,mot_a_pos lds r1 ,mot_a_pos+1 lds r2 ,mot_a_pos+2 lds r3 ,mot_a_pos+3 lds r4 ,mot_b_pos lds r5 ,mot_b_pos+1 lds r6 ,mot_b_pos+2 lds r7 ,mot_b_pos+3 lds r8 ,clock lds r9 ,clock+1 lds r10 ,clock+2 lds r11 ,clock+3 out SREG ,r16 sts alg_az_steps1 ,r0 sts alg_az_steps1+1 ,r1 sts alg_az_steps1+2 ,r2 sts alg_az_steps1+3 ,r3 sts alg_alt_steps1 ,r4 sts alg_alt_steps1+1 ,r5 sts alg_alt_steps1+2 ,r6 sts alg_alt_steps1+3 ,r7 sts alg_time1 ,r8 sts alg_time1+1 ,r9 sts alg_time1+2 ,r10 sts alg_time1+3 ,r11 lds r0 ,obj_ds_int_ra ;little endian lds r1 ,obj_ds_int_ra+1 sts alg_rectint1 ,r1 sts alg_rectint1+1 ,r0 ;big endian lds r0 ,obj_ds_int_dec lds r1 ,obj_ds_int_dec+1 sts alg_declint1 ,r1 sts alg_declint1+1 ,r0 ldi r16 ,ALG_POS_NEW sts alg_newpos1 ,r16 ldi r16 ,TGO_ST_NONE sts tgo_status ,r16 ldi r16 ,1 ldi xh ,high(alg_ana_save) ldi xl ,low(alg_ana_save) rcall mnu_slowfunc_set rcall mnu_out call lcd_modemove rjmp fun_exec_message_ok ;***************************************************************************************** fun_obj_align2: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_obj_align2_exec ;MNU_CALL_EXEC fun_obj_align2_exec: in r16 ,SREG cli lds r0 ,mot_a_pos lds r1 ,mot_a_pos+1 lds r2 ,mot_a_pos+2 lds r3 ,mot_a_pos+3 lds r4 ,mot_b_pos lds r5 ,mot_b_pos+1 lds r6 ,mot_b_pos+2 lds r7 ,mot_b_pos+3 lds r8 ,clock lds r9 ,clock+1 lds r10 ,clock+2 lds r11 ,clock+3 out SREG ,r16 sts alg_az_steps2 ,r0 sts alg_az_steps2+1 ,r1 sts alg_az_steps2+2 ,r2 sts alg_az_steps2+3 ,r3 sts alg_alt_steps2 ,r4 sts alg_alt_steps2+1 ,r5 sts alg_alt_steps2+2 ,r6 sts alg_alt_steps2+3 ,r7 sts alg_time2 ,r8 sts alg_time2+1 ,r9 sts alg_time2+2 ,r10 sts alg_time2+3 ,r11 lds r0 ,obj_ds_int_ra ;little endian lds r1 ,obj_ds_int_ra+1 sts alg_rectint2 ,r1 sts alg_rectint2+1 ,r0 ;big endian lds r0 ,obj_ds_int_dec lds r1 ,obj_ds_int_dec+1 sts alg_declint2 ,r1 sts alg_declint2+1 ,r0 ldi r16 ,ALG_POS_NEW sts alg_newpos2 ,r16 ldi r16 ,TGO_ST_NONE sts tgo_status ,r16 ldi r16 ,2 ldi xh ,high(alg_ana_save) ldi xl ,low(alg_ana_save) rcall mnu_slowfunc_set rcall mnu_out call lcd_modemove rjmp fun_exec_message_ok ;***************************************************************************************** fun_obj_goto: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_obj_goto_exec ;MNU_CALL_EXEC fun_obj_goto_exec: lds r0 ,mnu_gpar_index sts mnu_lastgoto_db ,r0 lds r0 ,mnu_par_index sts mnu_lastgoto_ix ,r0 lds r0 ,mnu_par_index+1 sts mnu_lastgoto_ix+1 ,r0 lds r0 ,obj_ds_int_ra lds r1 ,obj_ds_int_ra+1 lds r2 ,obj_ds_int_dec lds r3 ,obj_ds_int_dec+1 sts tgo_rectint ,r1 sts tgo_rectint+1 ,r0 sts tgo_declint ,r3 sts tgo_declint+1 ,r2 ldi r16 ,TGO_ST_NEW_TARGET sts tgo_status ,r16 rcall mnu_out call lcd_modemove rjmp fun_exec_message_ok ;***************************************************************************************** fun_radec: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_radec_exec ;MNU_CALL_EXEC fun_radec_exec: clt lds r16 ,tgo_status cpi r16 ,TGO_ST_NONE brne fun_radec_enter call mnu_out set ret fun_radec_enter: clt ret ;***************************************************************************************** fun_radec_ra: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC ;***************************************************************************************** fun_radec_dec: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC ;***************************************************************************************** fun_radec_setra: ret ;MNU_CALL_SHOW1 rjmp fun_radec_setra_show2 ;MNU_CALL_SHOW2 rjmp fun_radec_setra_max_index ;MNU_CALL_MAX_IND rjmp fun_radec_setra_start_index ;MNU_CALL_STARTIND rjmp fun_radec_setra_faststep ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC fun_radec_setra_show2: lds AKKU_3 ,mnu_chi_index lds AKKU_2 ,mnu_chi_index+1 call flt_convert_word f_push f_const cor__rect2disp f_div f_store tgo_rect lds r17 ,mnu_chi_index lds r16 ,mnu_chi_index+1 ldi xh ,high(men_message) ldi xl ,low(men_message) call cor_display_ra ldi xh ,high(men_message) ldi xl ,low(men_message) call lcd_print_x2 set ret fun_radec_setra_max_index: ldi r16 ,low(24*60*10) ;tenth minute steps (00h - 24h) ldi r17 ,high(24*60*10) ldi r18 ,0xFF ;wrap around allowed set ret fun_radec_setra_start_index: f_load tgo_rect f_push f_const cor__rect2disp f_mul call flt_double2word mov r16 ,AKKU_3 mov r17 ,AKKU_2 set ret fun_radec_setra_faststep: ldi r16 ,low(40) ;4 minutes = 1° ldi r17 ,high(40) ;per key repeat interval (0.25 sec) set ret ;***************************************************************************************** fun_radec_setdec: ret ;MNU_CALL_SHOW1 rjmp fun_radec_setdec_show2 ;MNU_CALL_SHOW2 rjmp fun_radec_setdec_max_index ;MNU_CALL_MAX_IND rjmp fun_radec_setdec_start_index ;MNU_CALL_STARTIND rjmp fun_radec_setdec_faststep ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC fun_radec_setdec_show2: lds AKKU_3 ,mnu_chi_index lds AKKU_2 ,mnu_chi_index+1 ldi r16 ,low(90*60) sub AKKU_3 ,r16 ldi r16 ,high(90*60) sbc AKKU_2 ,r16 call flt_convert_word f_push f_const cor__decl2disp f_div f_store tgo_decl lds r17 ,mnu_chi_index lds r16 ,mnu_chi_index+1 subi r17 ,low(90*60) sbci r16 ,high(90*60) ldi xh ,high(men_message) ldi xl ,low(men_message) call cor_display_dec ldi xh ,high(men_message) ldi xl ,low(men_message) call lcd_print_x2 set ret fun_radec_setdec_max_index: ldi r16 ,low(180*60) ;arc minutes (-90° - +90°) ldi r17 ,high(180*60) clr r18 ;no wrap around allowed set ret fun_radec_setdec_start_index: f_load tgo_decl f_push f_const cor__decl2disp f_mul call flt_double2word mov r16 ,AKKU_3 mov r17 ,AKKU_2 subi r16 ,low(-90*60) sbci r17 ,high(-90*60) set ret fun_radec_setdec_faststep: ldi r16 ,low(60) ;60 arcmin = 1° ldi r17 ,high(60) ;per key repeat interval (0.25 sec) set ret ;***************************************************************************************** fun_profiles: rjmp fun_profiles_show1 ;MNU_CALL_SHOW1 rjmp fun_profiles_show2 ;MNU_CALL_SHOW2 rjmp fun_profiles_max_index ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP ret ;MNU_CALL_EXEC fun_profiles_show1: ldi zl ,low(msg_mnu_profile<<1) ldi zh ,high(msg_mnu_profile<<1) call lcd_print_z1 lds r17 ,mnu_par_index ldi r16 ,'1' add r16 ,r17 sts lcd_line_1+7 ,r16 set ret fun_profiles_show2: ldi zl ,low(msg_mnu_profile_number_of<<1) ldi zh ,high(msg_mnu_profile_number_of<<1) call lcd_print_z2 lds r17 ,mnu_chi_index ldi r16 ,'1' add r16 ,r17 sts lcd_line_2 ,r16 lds r16 ,mnu_chi_index lds r17 ,eep_cur_profile cp r16 ,r17 brne fun_profiles_show2_noact ldi r16 ,'*' sts lcd_line_2+7 ,r16 fun_profiles_show2_noact: set ret fun_profiles_max_index: ldi r16 ,3 clr r17 set ret ;***************************************************************************************** fun_profile_act: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_profile_act_exec ;MNU_CALL_EXEC fun_profile_act_exec: call lcd_modemove lds r16 ,mnu_par_index sts eep_cur_profile ,r16 cli jmp main_new_profile ;restart with new profile ;***************************************************************************************** fun_prof_makedef: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_prof_makedef_exec ;MNU_CALL_EXEC fun_prof_makedef_exec: lds r16 ,mnu_par_index ldi zh ,high(eep_prof_default) ldi zl ,low(eep_prof_default) call eep_write call mnu_out rjmp fun_exec_message_ok ;***************************************************************************************** fun_sys_ana_on: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_sys_ana_on_exec ;MNU_CALL_EXEC fun_sys_ana_on_exec: ldi r16 ,1 sts alg_eep_open ,r16 rjmp fun_exec_message_ok ;***************************************************************************************** fun_sys_ana_off: ret ;MNU_CALL_SHOW1 ret ;MNU_CALL_SHOW2 ret ;MNU_CALL_MAX_IND ret ;MNU_CALL_STARTIND ret ;MNU_CALL_FASTSTEP rjmp fun_sys_ana_off_exec ;MNU_CALL_EXEC fun_sys_ana_off_exec: ldi r16 ,0 sts alg_eep_open ,r16 rjmp fun_exec_message_ok ;***************************************************************************************** fun_exec_message_ok: ldi zl ,low(msg_mnu_command_ok<<1) ldi zh ,high(msg_mnu_command_ok<<1) call lcd_print_alarm set ret ;***************************************************************************************** ;Basic menu handling routines ; ;***************************************************************************************** ;***************************************************************************************** ;Set call adress and parameters for main program ;xh:xl function adress ;r16 parameter in r16 mnu_slowfunc_set: lds r0 ,mnu_slowfunc_adr lds r1 ,mnu_slowfunc_adr+1 or r0 ,r1 breq mnu_sfs_ok ldi zl ,low(msg_mnu_slowfunc_busy<<1) ldi zh ,high(msg_mnu_slowfunc_busy<<1) call lcd_print_alarm clt ret mnu_sfs_ok: sts mnu_slowfunc_adr ,xh sts mnu_slowfunc_adr+1,xl sts mnu_slowfunc_r16 ,r16 ldi zl ,low(msg_mnu_command_ok<<1) ldi zh ,high(msg_mnu_command_ok<<1) call lcd_print_alarm set ret ;***************************************************************************************** ;Execute call from irq routine in main program mnu_slowfunc_exec: lds zh ,mnu_slowfunc_adr lds zl ,mnu_slowfunc_adr+1 clr r16 cp zh ,r16 cpc zl ,r16 breq mnu_sfx_end lds r16 ,mnu_slowfunc_r16 icall ldi r16 ,255 call util_delay_ms ldi r16 ,255 call util_delay_ms ldi r16 ,255 call util_delay_ms ldi r16 ,255 call util_delay_ms clr r16 sts mnu_slowfunc_adr ,r16 sts mnu_slowfunc_adr+1,r16 mnu_sfx_end: ret ;***************************************************************************************** ;Show parent and child menu entries ; or current RA/DEC position mnu_show: push r16 push r17 push xl push xh push zl push zh clr r16 sts lcd_pause ,r16 lds r16 ,lcd_mode ;show menu or position ? cpi r16 ,LCD_MODE_MOVE breq mnu_show_position lds zl ,mnu_parent ;parent menu entry lds zh ,mnu_parent+1 adiw zh:zl ,MNU_ADRESS lpm r16 ,Z+ lpm r17 ,Z+ tst r16 ;function adress brne mnu_show_dynamic1 tst r17 ;no function adress, breq mnu_show_static1 ;show static text only mnu_show_dynamic1: mov zl ,r16 mov zh ,r17 adiw zh:zl ,MNU_CALL_SHOW1 ;offset in menu item's jump table clt icall ;call into menu item's jump table brts mnu_show_2 ;function didn't print, show static text mnu_show_static1: lds zl ,mnu_parent lds zh ,mnu_parent+1 rcall lcd_print_z1 mnu_show_2: lds zl ,mnu_child ;child menu entry lds zh ,mnu_child+1 adiw zh:zl ,MNU_ADRESS lpm r16 ,Z+ lpm r17 ,Z+ tst r16 brne mnu_show_dynamic2 tst r17 breq mnu_show_static2 mnu_show_dynamic2: mov zl ,r16 mov zh ,r17 adiw zh:zl ,MNU_CALL_SHOW2 ;offset in menu item's jump table clt icall ;call into menu item's jump table brtc mnu_show_static2 rjmp mnu_show_end mnu_show_static2: lds zl ,mnu_child lds zh ,mnu_child+1 rcall lcd_print_z2 rjmp mnu_show_end mnu_show_position: ldi xl ,low(cor_recttext) ldi xh ,high(cor_recttext) rcall lcd_print_x1 ldi xl ,low(cor_decltext) ldi xh ,high(cor_decltext) rcall lcd_print_x2 mnu_show_end: pop xh pop xl pop zh pop zl pop r17 pop r16 ret ;***************************************************************************************** ;Leave a menu subtree (go to parent menu entry) mnu_out: lds zl ,mnu_parent ;pointer to parent node lds zh ,mnu_parent+1 adiw zh:zl ,MNU_PARENT_PTR lpm r16 ,Z+ ;check pointer to parent's parent lpm r17 ,Z+ or r16 ,r17 brne mnu_out_01 ;not null, ok ret mnu_out_01: lds zl ,mnu_parent ;pointer to parent node lds zh ,mnu_parent+1 sts mnu_child ,zl ;set as new child sts mnu_child+1 ,zh adiw zh:zl ,MNU_PARENT_PTR lpm r16 ,Z+ ;parent's parent node lpm r17 ,Z+ lsl r16 ;convert to byte pointer rol r17 sts mnu_parent ,r16 ;set as new parent sts mnu_parent+1 ,r17 lds r16 ,mnu_par_index ;child index = parent index lds r17 ,mnu_par_index+1 sts mnu_chi_index ,r16 sts mnu_chi_index+1 ,r17 lds r16 ,mnu_gpar_index ;parent index = gparent index lds r17 ,mnu_gpar_index+1 sts mnu_par_index ,r16 sts mnu_par_index+1 ,r17 clr r16 ;gparent index = 0 sts mnu_gpar_index ,r16 sts mnu_gpar_index+1 ,r16 rjmp mnu_show ;***************************************************************************************** ;Step into a menu subtree mnu_in: lds zl ,mnu_child ;get function adress of subtree lds zh ,mnu_child+1 ;if function = 0 adiw zh:zl ,MNU_ADRESS ;it is a subtree having child entries lpm r16 ,Z+ lpm r17 ,Z+ mov r0 ,r16 or r0 ,r17 breq mnu_in_into ;function adress = 0, step into subtree mov zl ,r16 ;otherwise call function mov zh ,r17 adiw zh:zl ,MNU_CALL_EXEC ;offset in menu item's jump table clt icall ;call into menu item's jump table brts mnu_in_end ;all done, if not step into subtree anyway mnu_in_into: lds r16 ,mnu_child lds r17 ,mnu_child+1 ldi yl ,low(men_root<<1) ldi yh ,high(men_root<<1) mnu_in_loop: mov zl ,yl mov zh ,yh adiw zh:zl ,MNU_PARENT_PTR lpm r18 ,Z+ lpm r19 ,Z+ cpi r18 ,0xFF brne mnu_in_no_tab_end cpi r19 ,0xFF brne mnu_in_no_tab_end mnu_in_end: ret mnu_in_no_tab_end: lsl r18 rol r19 cp r16 ,r18 brne mnu_in_next cp r17 ,r19 breq mnu_in_found mnu_in_next: adiw yh:yl ,MNU_ENTRY_SIZE rjmp mnu_in_loop mnu_in_found: sts mnu_parent ,r16 sts mnu_parent+1 ,r17 sts mnu_child ,yl sts mnu_child+1 ,yh lds r16 ,mnu_par_index lds r17 ,mnu_par_index+1 sts mnu_gpar_index ,r16 sts mnu_gpar_index+1 ,r17 lds r16 ,mnu_chi_index lds r17 ,mnu_chi_index+1 sts mnu_par_index ,r16 sts mnu_par_index+1 ,r17 movw zh:zl ,yh:yl ;get child items start index adiw zh:zl ,MNU_ADRESS lpm r16 ,Z+ lpm r17 ,Z+ mov r0 ,r16 or r0 ,r17 breq mnu_in_child_index ;no func, take 0 as index movw zh:zl ,r17:r16 adiw zh:zl ,MNU_CALL_STARTIND ;offset in menu item's jump table clt icall ;call into menu item's jump table brts mnu_in_child_index ;index set, if not index=0 clr r16 clr r17 mnu_in_child_index: sts mnu_chi_index ,r16 sts mnu_chi_index+1 ,r17 rjmp mnu_show ;***************************************************************************************** ;Step one entry backwards (in the same tree level) mnu_prev: lds zl ,mnu_child ;if (index < child->max_no) lds zh ,mnu_child+1 adiw zh:zl ,MNU_ADRESS lpm r16 ,Z+ lpm r17 ,Z+ mov r18 ,r16 or r18 ,r17 breq mnu_prev_01 mov zl ,r16 ;otherwise call function mov zh ,r17 adiw zh:zl ,MNU_CALL_MAX_IND ;offset in menu item's jump table clt icall ;call into menu item's jump table brts mnu_prev_01 ;all done, if not set max index to zero clr r16 ;max index 0x0000 clr r17 clr r18 ;no wrap around mnu_prev_01: lds r24 ,mnu_chi_index ;index > 0 ? lds r25 ,mnu_chi_index+1 mov r0 ,r24 or r0 ,r25 brne mnu_prev_step_backwards ;yes, step back tst r18 ;no, wrap around allowed ? brpl mnu_prev_ptr ;no, go to menu item before movw r25:r24 ,r17:r16 ;yes, wrap around to max_index rjmp mnu_prev_index_inrange mnu_prev_step_backwards: lds r0 ,mnu_index_step ;index = index + step lds r1 ,mnu_index_step+1 sub r24 ,r0 sbc r25 ,r1 brcc mnu_prev_index_inrange ;no underflow, save new index clr r24 ;underflow, set index = 0 clr r25 mnu_prev_index_inrange: sts mnu_chi_index ,r24 sts mnu_chi_index+1 ,r25 rjmp mnu_show mnu_prev_ptr: lds zl ,mnu_child ; lds zh ,mnu_child+1 sbiw zh:zl ,MNU_ENTRY_SIZE - MNU_PARENT_PTR lpm r16 ,Z+ lpm r17 ,Z+ lsl r16 rol r17 lds r18 ,mnu_parent lds r19 ,mnu_parent+1 cp r16 ,r18 cpc r17 ,r19 brne mnu_prev_index_inrange lds zl ,mnu_child ; child -- lds zh ,mnu_child+1 sbiw zh:zl ,MNU_ENTRY_SIZE sts mnu_child ,zl sts mnu_child+1 ,zh clr r16 ; index = 0 sts mnu_chi_index ,r16 sts mnu_chi_index+1 ,r16 rjmp mnu_show ;***************************************************************************************** ;Step one entry ahead (in the same tree level) mnu_next: lds zl ,mnu_child ;if (index < child->max_no) lds zh ,mnu_child+1 adiw zh:zl ,MNU_ADRESS lpm r16 ,Z+ lpm r17 ,Z+ mov r18 ,r16 or r18 ,r17 breq mnu_next_01 mov zl ,r16 ;otherwise call function mov zh ,r17 adiw zh:zl ,MNU_CALL_MAX_IND ;offset in menu item's jump table clt icall ;call into menu item's jump table brts mnu_next_01 ;all done, if not set max index to zero clr r16 ;max index 0x0000 clr r17 clr r18 ;no wrap around mnu_next_01: lds r24 ,mnu_chi_index ;index < max_index ? lds r25 ,mnu_chi_index+1 cp r24 ,r16 cpc r25 ,r17 brcs mnu_next_step_forward ;yes, step forward tst r18 ;no, wrap around allowed ? brpl mnu_next_ptr ;no, go to next menu item clr r24 ;yes, wrap around to 0 clr r25 rjmp mnu_next_index_inrange mnu_next_step_forward: lds r0 ,mnu_index_step ;index = index + step lds r1 ,mnu_index_step+1 add r24 ,r0 adc r25 ,r1 cp r16 ,r24 ;out of range ? cpc r17 ,r25 brcc mnu_next_index_inrange ;no mov r24 ,r16 ;set max index mov r25 ,r17 mnu_next_index_inrange: sts mnu_chi_index ,r24 sts mnu_chi_index+1 ,r25 rjmp mnu_show mnu_next_ptr: lds zl ,mnu_child ; lds zh ,mnu_child+1 adiw zh:zl ,MNU_ENTRY_SIZE + MNU_PARENT_PTR lpm r16 ,Z+ lpm r17 ,Z+ lsl r16 rol r17 lds r18 ,mnu_parent lds r19 ,mnu_parent+1 cp r16 ,r18 cpc r17 ,r19 brne mnu_next_index_inrange lds zl ,mnu_child ; child ++ lds zh ,mnu_child+1 adiw zh:zl ,MNU_ENTRY_SIZE sts mnu_child ,zl sts mnu_child+1 ,zh clr r16 ; index = 0 sts mnu_chi_index ,r16 sts mnu_chi_index+1 ,r16 ;} rjmp mnu_show ;*****************************************************************************************