Форум проекта "Минилаб-Мастер"
Клуб по интересам - отдыхаем от фотобизнеса => Art Of Electronics => Тема начата: Andy от 06 Июля 2009, 16:18:50
-
Неужели это Искусство утеряно после DOS? Кстати не сильно искал :)
Короче, мне надо стрелками лазить по меню в контроллере и все должно отображатся на LCD дисплее. Меню имеет деревовидную структуру. Подскажите самый эффектный алгоритм, господа программеры, буду благодарен.
-
И еще бы алгоритм ввода строки и редактирования ее BackSpace-oм, ессесно эхоповтором на дисплее... :-[
-
Это про меню http://expsys.narod.ru/glava3.htm
Про контроллеры не подскажу, слишком обща у тебя задача, но алгоритмы везде одинаковые.
-
Мдя... Вот вам, юзайте на здоровие. Код громоздок, но я не программер. Вложенные меню делаются так же точ-в точь... Код расчитан на 32мегу, клаву от PC и жк wh1601a-yyh-ctk.
$regfile = "m32def.dat" \' используем ATmega32 (MRC40 с универсальным модулем)
$crystal = 10000000
$hwstack = 100 \' default use 32 for the hardware stack
$swstack = 100 \' default use 10 for the SW stack
$framesize = 100 \' default use 40 for the frame space
Config Keyboard = Pind.2 , Data = Pind.6 , Keydata = Keydata
$lib "lcd4.lbx" \'используем 4-х битное подключение дисплея с помощью альтернативной библиотеки
Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.2 , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7
Config Lcd = 16 * 2
$baud = 9600
Dim S As String * 12
Dim B As Byte
Dim Menu As Byte
Dim Keymenu As Byte
Dim Longstr As String * 16
Dim Str1 As String * 8
Dim Str2 As String * 8
\'$serialinput = Kbdinput
Cls
Keymenu = 1
Longstr = "Ўpaa»Д v1.0"
Gosub Printlsd
Wait 1
Cls
Longstr = "Pa·paІoїєa Andy"
Gosub Printlsd
Wait 1
Cls
Mainmenu:
Do
If Keymenu = 1 Then
Gosub Menu1
End If
\'Gosub Kbdinput
If B = 50 Then
If Keymenu < 5 Then
Incr Keymenu
End If
End If
If B = 56 Then
If Keymenu > 1 Then
Decr Keymenu
End If
End If
Select Case Keymenu
Case 1 : Gosub Menu1
Case 2 : Gosub Menu2
Case 3 : Gosub Menu3
Case 4 : Gosub Menu4
Case 5 : Gosub Menu5
End Select
Loop
Return
Menu1:
Cls
Longstr = "BГІop KaccГ"
Gosub Printlsd
Gosub Kbdinput
If B = 13 Then
Gosub Progr1
End If
Return
Menu2:
Cls
Longstr = "¤aґpy·єa EPROM"
Gosub Printlsd
Gosub Kbdinput
If B = 13 Then
Gosub Progr2
End If
Return
Menu3:
Cls
Longstr = "BГґpy·єa EPROM"
Gosub Printlsd
Gosub Kbdinput
If B = 13 Then
Gosub Progr3
End If
Return
Menu4:
Cls
Lcd "Menu4"
Gosub Kbdinput
If B = 13 Then
Gosub Progr4
End If
Return
Menu5:
Cls
Lcd "Menu5"
Gosub Kbdinput
If B = 13 Then
Gosub Progr5
End If
Return
Progr1:
Cls
Lcd "Progr1"
Wait 1
Return
Progr2:
Cls
Lcd "Progr2"
Wait 1
Return
Progr3:
Cls
Lcd "Progr3"
Wait 1
Return
Progr4:
Cls
Lcd "Progr4"
Wait 1
Return
Progr5:
Cls
Lcd "Progr5"
Wait 1
Return
Kbdinput:
Do
B = Getatkbd()
Loop Until B <> 0
\'Lcd B
\'Wait 1
Return
End
Keydata:
\'normal keys lower case
Data 0 , 0 , 0 , 0 , 0 , 200 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , &H5E , 0
Data 0 , 0 , 0 , 0 , 0 , 113 , 49 , 0 , 0 , 0 , 122 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 0 , 0 , 32 , 118 , 102 , 116 , 114 , 53 , 0
Data 0 , 110 , 98 , 104 , 103 , 121 , 54 , 7 , 8 , 44 , 109 , 106 , 117 , 55 , 56 , 0
Data 0 , 44 , 107 , 105 , 111 , 48 , 57 , 0 , 0 , 46 , 45 , 108 , 48 , 112 , 43 , 0
Data 0 , 0 , 0 , 0 , 0 , 92 , 0 , 0 , 0 , 0 , 13 , 0 , 0 , 92 , 0 , 0
Data 0 , 60 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0
\'shifted keys UPPER case
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 81 , 33 , 0 , 0 , 0 , 90 , 83 , 65 , 87 , 34 , 0
Data 0 , 67 , 88 , 68 , 69 , 0 , 35 , 0 , 0 , 32 , 86 , 70 , 84 , 82 , 37 , 0
Data 0 , 78 , 66 , 72 , 71 , 89 , 38 , 0 , 0 , 76 , 77 , 74 , 85 , 47 , 40 , 0
Data 0 , 59 , 75 , 73 , 79 , 61 , 41 , 0 , 0 , 58 , 95 , 76 , 48 , 80 , 63 , 0
Data 0 , 0 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 0 , 13 , 94 , 0 , 42 , 0 , 0
Data 0 , 62 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 , 0
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0
Printlsd:
Str1 = Mid(longstr , 1 , 8)
Str2 = Mid(longstr , 9 , 8)
Cls
Lcd Str1
Lowerline
Lcd Str2
Return
-
Вот окончательный вариант меню, очень легко добавлять новые меню и подменю любой степени вложенности.
Mainmenu:
Gosub Beep
Cls
Longstr = W27 \'Выбор Кассы
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr1 \'Нажат ENTER - Программа выбора кассы
Case 50 : Goto Menu2 \'Нажата Стрелка Вниз
\'Case 56 : Goto Menu3 \'Нажата Стрелка Вверх
End Select
Loop
Menu2:
\'Меню Работа с кассой
Cls
Longstr = W28 \'Работа с кассой
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Menu21 \'Нажат ENTER - Программа выбора кассы
Case 56 : Goto Mainmenu \'Нажата Стрелка Вверх
Case 50 : Goto Menu3 \'Нажата Стрелка Вниз
End Select
Loop
Menu3:
\'Меню Загрузка EPROM
Cls
Longstr = W14 \'Загрузка EPROM
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr3 \'Нажат ENTER -
Case 56 : Goto Menu2 \'Нажата Стрелка Вверх
Case 50 : Goto Menu4 \'Нажата Стрелка Вниз
End Select
Loop
Menu4:
\'Меню Загрузка блока
Cls
Longstr = W13 \'Загрузка блока
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr4 \'Нажат ENTER -
Case 56 : Goto Menu3 \'Нажата Стрелка Вверх
Case 50 : Goto Menu5 \'Нажата Стрелка Вниз
End Select
Loop
Menu5:
\'Меню Выгрузка EPROM
Cls
Longstr = W15 \'Выгрузка EPROM
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr5 \'Нажат ENTER -
Case 56 : Goto Menu4 \'Нажата Стрелка Вверх
Case 50 : Goto Menu6 \'Нажата Стрелка Вниз
End Select
Loop
Menu6:
\'Тест
Cls
Longstr = W34 \'Тест
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr6 \'Нажат ENTER -
Case 56 : Goto Menu5 \'Нажата Стрелка Вверх
\'Case 50 : Goto Menu6 \'Нажата Стрелка Вниз
End Select
Loop
Menu21:
\'Меню отчета с фискалки по датам
Cls
Longstr = W16 \'С фиск. по датам
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Fisk \'Нажат ENTER -
\'Case 56 : Goto Menu5 \'Нажата Стрелка Вверх
Case 50 : Goto Menu22 \'Нажата Стрелка Вниз
Case 100 : Goto Menu2 \'Нажат ESC
End Select
Loop
Menu22:
\'Меню отчета с фискалки по сменам
Cls
Longstr = W17 \'С фиск. по сменам
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Fisksmena \'Нажат ENTER -
Case 56 : Goto Menu21 \'Нажата Стрелка Вверх
Case 50 : Goto Menu23 \'Нажата Стрелка Вниз
Case 100 : Goto Menu2 \'Нажат ESC
End Select
Loop
\'Программа пустая
Menu23:
Cls
Longstr = "Ёycїo 1"
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Progr4 \'Нажат ENTER -
Case 56 : Goto Menu22 \'Нажата Стрелка Вверх
\'Case 50 : Goto Menu23 \'Нажата Стрелка Вниз
Case 100 : Goto Menu2 \'Нажат ESC
End Select
Loop
Menu31:
\'По годам кварталам и месяцам
Cls
Longstr = W18 \'Год.Кварт.Месяц
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
\'Case 13 : Goto Fisksmena \'Нажат ENTER -
\'Case 56 : Goto Menu21 \'Нажата Стрелка Вверх
Case 50 : Goto Menu32 \'Нажата Стрелка Вниз
Case 100 : Goto Menu21 \'Нажат ESC
End Select
If B = 13 Then
1val = 1
2val = 3
Goto Fiskini
End If
Loop
и так далее....
-
А вот вопрос такой есть. Можно ли в бейсике каким либо обраозом передать подпрограмму или метку как параметр? что-то вроде указателя?
Например меню мое сотоит из однотипных блоков
Menumain:
\'Меню Работа с кассой
Cls
Longstr = W28 \'Работа с кассой
Gosub Printlsd
Do
Gosub Kbdinput
Select Case B
Case 13 : Goto Menu21 \'Нажат ENTER - Программа выбора кассы
Case 56 : Goto Mainmenu \'Нажата Стрелка Вверх
Case 50 : Goto Menu3 \'Нажата Стрелка Вниз
End Select
Loop
хотелось бы сделать одну функцию, а туда передавать как параметр например подпрограмму Menu3 и вызывать ее. Очень меня давно этот вопрос интересует, постоянно на него натыкаюсь. Код можно очень сильно сократить...
типа так:
ukaz=Menu3
gosub Menumain
Menumain:
бла бла
Case 50 : Goto ukaz
return
Условие переходит на Menu3.... Profit...
Можно так сделать?
-
Посмотри в сторону Adr и Adr2. Вот в документации Bascom-а топик: http://avrhelp.mcselec.com/index.html?adr___adr2.htm
Там как раз в качестве примера реализация меню рассматривается. Глянул только мельком - вроде оно.
И еще бы алгоритм ввода строки и редактирования ее BackSpace-oм, ессесно эхоповтором на дисплее...
А это, кстати, нужно еще?
-
Посмотри в сторону Adr и Adr2. Вот в документации Bascom-а топик: http://avrhelp.mcselec.com/index.html?adr___adr2.htm
Там как раз в качестве примера реализация меню рассматривается. Глянул только мельком - вроде оно.
И еще бы алгоритм ввода строки и редактирования ее BackSpace-oм, ессесно эхоповтором на дисплее...
А это, кстати, нужно еще?
Посмотрел, как баран, так и не понял как это работает. Какие-то умножения на два и все такое, чувствую, штука нужная, а как это работает - не пойму....
-
Написал ближе к твоим требованиям. Структура меню - в данных, а код - отдельно, один для всех. Код обильно прокомментировал.
Единственное - ввод-вывод. Так как не знаю, как прикрутить LCD и AT keyboard в эмуляторе, сделал ввод через Waitkey(), а вывод через Print. И вместо клавиш влево (<-), вправо (->) и Enter использовал, соответственно, "1", "3" и "2". Но это, думаю, не важно. Ввод-вывод свои поставишь.
Для добавления пунктов код трогать не надо. Надо только добавлять пункты с связями в секцию $data, и писать подпрограммы для действий.
$regfile = "M644def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 64
$framesize = 64
$lib "adr2.lib"
Dim Menupointer As Word
Dim B As Byte
Dim Type As Byte
Dim Dummy As Byte
Dim Message As String * 32
\' Типы меню
Const Id_submenu = &HAA
Const Id_command = &H55
Main_menu:
\' Ставим указатель Data на первый пункт главного меню
Restore Menu1
\' Сохраняем в MenuPointer текущий указатель Data,
\' который лежит в регистрах R8 и R9 (ассемблерный код).
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Display_new_menu:
\' Извлекаем из MenuPointer указатель в регистры R8 и R9,
\' то есть передвигаем указатель Data в позицию MenuPointer.
lds R8, {MenuPointer}
lds R9, {MenuPointer + 1}
\' Читаем тип меню (подменю или команда), название и печатаем название
Read Type
Read Message
Print Message
\' Ждем клавишу, пока она не 1 (<-) или 2 (Enter) или 3 (->).
Wait_key:
B = Waitkey()
If B < 49 Then
Goto Wait_key
End If
If B > 51 Then
Goto Wait_key
End If
\' Проверяем, нажата ли 2 (Enter)
If B = 50 Then
\' Если тип у нас - подменю, то:
If Type = Id_submenu Then
\' Читаем адрес дочернего меню (идет в Data сразу за названием)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
\' Иначе (если тип - команда), то:
Else
\' Читаем адрес метки команды (идет в Data сразу за названием)
Read Dataptr
\' Вызываем подпрограмму по этому адресу.
movw R30,R8
icall
\' И после ее отработки идем в самое начало. Здесь можно и выйти
\' из меню вообще или остаться в этом пункте меню или еще что-нибудь.
Goto Main_menu
End If
End If
\' Если нажата не 2 (Enter), то пропускаем 2 байта с адресом
\' команды или подменю - они нам не нужны.
Read Dummy
Read Dummy
\' Проверяем, нажата ли 1 (<-)
If B = 49 Then
\' Читаем адрес предыдущего меню на этом уровне (сосед слева)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
\' Если нажата и не 1 (<-), то снова пропускаем 2 байта с адресом
\' соседа слева - они нам тоже не нужны.
Read Dummy
Read Dummy
\' Проверяем, нажата ли 3 (->)
If B = 51 Then
\' Читаем адрес следующего меню на этом уровне (сосед справа)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
End
\' ---------
\' Подпрограммы для команд
Runmenu11:
\' Здесь делаем полезные дела
Print "Running command from menu 1 -> 1"
Return
Runmenu12:
\' Полезные дела
Print "Command of menu 1 -> 2"
Return
Runmenu2:
\' Полезные дела
Print "Command of menu 2"
Return
Runmenu3:
\' Полезные дела
Print "Command of menu 3"
Return
\' ---------
\' Блок данных. Здесь и находится структура меню. Порядок пунктов меню не важен,
\' главное правильно указать связи-адреса на дочерний элемент (подменю или
\' команду) и соседей слева и справа. Структура такая:
\'
\' Метка_своя:
\' Data Тип_Меню
\' Data "Название_меню"
\' Data Метка_дочернего
\' Data Метка_соседа_слева
\' Data Метка_соседа_справа
\'
$data
Menu1:
Data Id_submenu
Data "Menu 1 v"
Adr2 Menu10
Adr2 Menu3
Adr2 Menu2
Menu10:
Data Id_submenu
Data "Menu up^"
Adr2 Menu1
Adr2 Menu12
Adr2 Menu11
Menu11:
Data Id_command
Data "Menu 11!"
Adr Runmenu11
Adr2 Menu10
Adr2 Menu12
Menu12:
Data Id_command
Data "Menu 12!"
Adr Runmenu12
Adr2 Menu11
Adr2 Menu10
Menu2:
Data Id_command
Data "Menu 2 !"
Adr Runmenu2
Adr2 Menu1
Adr2 Menu3
Menu3:
Data Id_command
Data "Menu 3 !"
Adr Runmenu3
Adr2 Menu2
Adr2 Menu1
-
Отлично! В коий раз снимаю шляпу...
Все почти сразу заработало, Единственно поправил этот кусочег:
Else
\' Читаем адрес метки команды (идет в Data сразу за названием)
Read Dataptr
\' Вызываем подпрограмму по этому адресу.
movw R30,R8
icall
\' И после ее отработки идем в самое начало. Здесь можно и выйти
\' из меню вообще или остаться в этом пункте меню или еще что-нибудь.
lds R8, {MenuPointer}
lds R9, {MenuPointer + 1}
Goto Main_menu
End If
Так как первую строку Restore Menu1 я вывел за пределы функции, чтобы попадать из любого места программы в нужное мне меню.
А подпрограммы портят регистры и меню вылетает неизвестно куда. Пихать в стек их не помогает, надежнне восстановить из переменной. Появился отличный эффект обратного попадания в родительское меню, откуда подпрограмма вызывалась.
-
А так получилось очень быстрое и маленькое меню. Очень удобно добавлять новые подменю Код занимает всего 600 байт!
-
И добавление нового пункта меню добавит всего 7 байт (без учета строки с названием, естественно).
PS: Алгоритм ввода строки и редактирования ее BackSpace-oм еще нужен? Или уже сделал давно?
-
Пока сделал кривенько, попозже код напишу. Пока под микроскопом изучаю твой код, учусь, типа.
-
И добавление нового пункта меню добавит всего 7 байт (без учета строки с названием, естественно).
И самое смешное, что алгоритм можно оптимизировать, например этот блок:
\' Если нажата не 2 (Enter), то пропускаем 2 байта с адресом
\' команды или подменю - они нам не нужны.
Read Dummy
Read Dummy
\' Проверяем, нажата ли 1 (<-)
If B = 49 Then
\' Читаем адрес предыдущего меню на этом уровне (сосед слева)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
повторяется 2 раза практически без изменений, по одному на каждую кнопку. Но пока вывести его в отдельную функцию не удалась, всему виной фраза Goto Display_new_menu. Из-за нее стек срывается, нельзя выходить из функции без return. Но это не суть важно...
-
Ага, можно оптимизировать. И в функцию даже не нужно. Просто этот кусок кода, где два раза повторяется:
\' Если нажата не 2 (Enter), то пропускаем 2 байта с адресом
\' команды или подменю - они нам не нужны.
Read Dummy
Read Dummy
\' Проверяем, нажата ли 1 (<-)
If B = 49 Then
\' Читаем адрес предыдущего меню на этом уровне (сосед слева)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
\' Если нажата и не 1 (<-), то снова пропускаем 2 байта с адресом
\' соседа слева - они нам тоже не нужны.
Read Dummy
Read Dummy
\' Проверяем, нажата ли 3 (->)
If B = 51 Then
\' Читаем адрес следующего меню на этом уровне (сосед справа)
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
оптимизировать таким макаром:
\' Если нажата не 2 (Enter), то пропускаем 2 байта с адресом
\' команды или подменю - они нам не нужны.
Read Dummy
Read Dummy
\' Если нажато 1 (<-) - мы на месте
\' Если нажато 2 (->) - то смещаемся еще на 2 байта
If B = 51 Then
Read Dummy
Read Dummy
End If
If B = 49 Or B = 51 Then
\' Читаем адрес пункта меню (<- или ->), на который пришли
Read Dataptr
\' Записываем его в MenuPointer и идем читать и рисовать это новое меню
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
End If
Можно еще Dummy объявить как Word и вызывать Read Dummy не дуплетом, а одинарно.
---------
Исправил чуть.
-
Что-то как-то... Условий менше не стало, Неочевидно стало добавлять новые условия (я добавил еще одну кнопку для возврата в предыдущее меню). Короче, я вывел
Read Dummy
Read Dummy
и
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
в отдельные функции и успокоился. Итак все очень неплохо.
-
Неочевидно стало добавлять новые условия (я добавил еще одну кнопку для возврата в предыдущее меню).
Добавил к каждому пункту меню в секции data еще одну связь на родительский элемент или просто адреса родителей запоминаешь по ходу работы? Интересно просто.
Основная мысль предыдущего моего сообщения была в том, чтобы в зависимости от нажатой кнопки, при помощи Read Dummy переместиться на нужную связь. Если сосед слева - 2 байта, сосед справа - 4 байта, родитель (если возврат в предыдущее добавить) - 6 байт. А потом уже один раз выполнить (он для всех кнопок ведь одинаков) блок
Read Dataptr
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu
Но можно и по-твоему. Вариантов реализации много. :)
-
Ну я просто добавил еще один одинаковый блок как на те две кнопки, и прицепил третью кнопку. А в описание меню добавил еще одно поле. Потом вывел одинаковые блоки в подпрограммы - получилось компактно и красиво. Вот и все.
-
Ну я просто добавил еще один одинаковый блок как на те две кнопки, и прицепил третью кнопку. А в описание меню добавил еще одно поле.
Точно. Тоже думаю, что это оптимальное решение. Меню в секции $data такого вида:
Метка_своя:
Data Тип_Меню
Data "Название_меню"
Adr2 Метка_дочернего /или/ Adr Метка_подпрограммы
Adr2 Метка_соседа_слева
Adr2 Метка_соседа_справа
Adr2 Метка_родителя
Вот еще вариант обработки клавиш, который мене в голову пришел: \' Если тип меню - команда и был нажат "Enter" (2), то:
If B = 50 Then
If Type = Id_command Then
Read Dataptr
movw R30,R8
icall
Goto Display_new_menu
End If
End If
Offset = 0 \' Нажат "Enter" (2) но не команда, а подменю
If B = 49 Then Offset = 2 \' Нажата "<-" (1) - смещение 2 байта
If B = 51 Then Offset = 4 \' Нажата "->" (3) - смещение 4 байта
If B = 52 Then Offset = 6 \' Нажата "Esc" (4) - смещение 6 байт
While Offset > 0
Read Dummy \' смещаемся к нужному меню
Offset = Offset - 1
Wend
Read Dataptr
sts {MenuPointer}, R8
sts {MenuPointer + 1}, R9
Goto Display_new_menu