![]() |
Электроника МК-161
![]() ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() Программируемый калькулятор с обратной польской нотацией (RPN Logic), Сделан в России! |
Эволюционное развитие советских калькуляторов MK-61/52 :
|
МК-компилятор | Эмулятор | Меню | Расширенное програмирование | Модуль ввода/вывода УСОМК-4 | Диск УЗВМК-1 | Скорость/Точность | Графический интерфейс |
Я разработал MK-компилятор, позволяющий писать программы на ПК используя язык программирования высокого уровня и используя интерфейс RS-232 отсылать их непосрественно в микрокалькулятор или в эмулятор калькулятора.
Программа включает в себя:
|
![]() Основной экран МК-компилятора |
![]()
|
![]() |
![]() |
![]() |
И отправить программу в калькулятор... Пример программы с бинарными данными |
![]() |
Захват основного или графического экрана МК. Захват основного экрана. |
![]() |
Пример: вычисление числа Пи
; требуется только один регистр #REG 0 N DO ; Отображение подсказки в строке комментариев #NUM ask EXEC \CPrintStringB ; ожидание значения INPUT ; сохранено в N STO N ; приготовить строку комментариев для ответа #NUM result EXEC \CPrintStringB ; на старте сумма = 0 CX ; вычисляет сумму 1/n=Пи/6 FOR N @N X^2 1/X + NEXT ; исправления чтобы найти Пи 6 * SQR ; останов дисплея STOP LOOP ; область бинарных данных для текстовых данных #BINARY ; TEXTN добавляет открывающий символ 0A (новая строка) и ; конечный символ nul . ; newline требуется чтобы очистить строку комментариев ask: #TEXTN "сколько циклов?" result: #TEXTN "Усреднение Пи" |
Compiled listing
PROGAM ZONE Step | Code | Keys ------------------------- 0000 | 01 | 1 0001 | 00 | 0 0002 | 00 | 0 0003 | 00 | 0 0004 | F4 | PP M 0005 | 90 | 9 0 0006 | 27 | 2 7 0007 | 50 | R/S 0008 | 40 | M 0 0009 | 01 | 1 0010 | 00 | 0 0011 | 01 | 1 0012 | 07 | 7 0013 | F4 | PP M 0014 | 90 | 9 0 0015 | 27 | 2 7 0016 | 0D | CX 0017 | 60 | RM 0 0018 | 22 | F X^2 0019 | 23 | F 1/X 0020 | 10 | + 0021 | 5D | F L0 0022 | 17 | 1 7 0023 | 06 | 6 0024 | 12 | * 0025 | 21 | F SQRT 0026 | 50 | R/S 0027 | 51 | GOTO 0028 | 00 | 0 0 |
BINARY ZONE Step | Code | Comment ------------------------- 1000 | 0A | newline 1001 | 48 | "H" 1002 | 6F | "o" 1003 | 77 | "w" 1004 | 20 | " " 1005 | 6D | "m" 1006 | 61 | "a" 1007 | 6E | "n" 1008 | 79 | "y" 1009 | 20 | " " 1010 | 6C | "l" 1011 | 6F | "o" 1012 | 6F | "o" 1013 | 70 | "p" 1014 | 73 | "s" 1015 | 3F | "?" 1016 | 00 | nul 1017 | 0A | newline 1018 | 50 | "P" 1019 | 69 | "i" 1020 | 20 | " " 1021 | 61 | "a" 1022 | 70 | "p" 1023 | 70 | "p" 1024 | 72 | "r" 1025 | 6F | "o" 1026 | 78 | "x" 1027 | 69 | "i" 1028 | 6D | "m" 1029 | 61 | "a" 1030 | 74 | "t" 1031 | 69 | "i" 1032 | 6F | "o" 1033 | 6E | "n" 1034 | 00 | nul ------------------------- Addr | Name ------------------------- B 1000 | ASK B 1017 | RESULT ------------------------- Reg | Name ------------------------- 0 | N 9027 | \CPRINTSTRINGB ------------------------- -- END OF FILE -- |
Возврат на адрес 0000 нажатием B/O, затем запуск нажатием С/П. Первый экран: ![]() Попробовал 500 циклов (набрать 500, нажать С/П), соответствующее значение Пи: ![]() Можно снова ввести новое значение и нажать С/П. Например 10000: ![]() |
![]() Эмулятор запустил программу PI Monte Carlo |
Достаточно добавить строку:
#MKFiles 2в исходном коде, и компилятор создаст три файла, которые использует программа:
Запустить эмулятор, нажать правую кнопку мыши. Появится следующее меню: ![]() Выбрать файл для загрузки файла. ![]() ![]() |
С версии 1.04, MK-Compiler может вызвать эмулятор, посылая в него все создаваемые файлы.
![]() |
Кнопки навигации по меню. Кнопки меняют функции в зависимости от контекста. Выход в основное меню по нажатию кнопки ВЫХОД |
![]() |
Доступ к псевдо-регистрам с клавиатуры:
|
доступно множество функций, таких как:
|
коды кнопок :
Примечание : код 26 не возвращается, так как он останавливает программу. Кнопки ВКЛ и Подсветка не возвращают коды. |
Использует #FONT/#DEFCHAR чтобы указать набор символов.![]() |
Использует #FINDFILE/#CREATEFILE/#LOADFILE для управления файлами и директориями.![]() |
Использует прерывания для воспроизведения звуков во время рисования линий.![]() |
Использует #DEFGRAPH для назначения спрайтов a и их отображения (на скрине - пример)![]() |
Программа берёт значения 0, 1 или 2 на входе и затем 20 раз рисует соответствующие образцы на случайных позициях на экране. 0=звезда, 1=квадрат, 2=круг. В конце программа ожидает нажатия кнопки. Можно ввести новое значение и нажать С/П. ; использующиеся регистры #reg 0 Index #reg e ObjectAddress DO ; вычисляет адрес образца ; в БИНАРНОЙ памяти используя таблицу ENTER #NUM Table + PRGM $1000 + STO ObjectAddress ; Очистка экрана 0 EXEC \CLS ; 20 циклов $20 STO Index FOR Index ; Случайные координаты $56 RND * $120 RND * SET \x0y0 ; отрисовка образца @ObjectAddress EXEC \PUTGB NEXT ; Отрисовка графического экрана GRPH ; Ожидание кнопки REPEAT GET \NEXTKEY NOT UNTIL(x<>0) ; Ожидание нового значения INPUT LOOP ; таблица с 3 адресами Table: #DAL star square circle #END |
; смена в БИНАРНОЙ памяти #BINARY star: #DEFGRAPH *..*..* .*.*.*. ..***.. ******* ..***.. .*.*.*. *..*..* #END square: #DEFGRAPH ******* *.....* *.....* *.....* *.....* *.....* *.....* ******* #END circle: #DEFGRAPH ..***.. .*...*. *.....* *.....* *.....* *.....* .*...*. ..***.. #END |
![]() 20 звёзд, значение 0. ![]() 20 квадратов, значение 1. ![]() 20 кружков, значение 2. |
Скомпилированная программа:
ОБЛАСТЬ ПРОГРАММ Step | Code | Keys ------------------------- 0000 | 0E | ENT 0001 | 00 | 0 0002 | 00 | 0 0003 | 04 | 4 0004 | 08 | 8 0005 | 10 | + 0006 | 28 | K PRGM 0007 | 01 | 1 0008 | 00 | 0 0009 | 00 | 0 0010 | 00 | 0 0011 | 10 | + 0012 | 4E | M e 0013 | 00 | 0 0014 | F4 | PP M 0015 | 90 | 9 0 0016 | 10 | 1 0 0017 | 02 | 2 0018 | 00 | 0 0019 | 40 | M 0 0020 | 05 | 5 0021 | 06 | 6 0022 | 3B | K RAN 0023 | 12 | * 0024 | 01 | 1 0025 | 02 | 2 0026 | 00 | 0 0027 | 3B | K RAN 0028 | 12 | * 0029 | F4 | PP M 0030 | 90 | 9 0 0031 | 00 | 0 0 0032 | 6E | RM e 0033 | F4 | PP M 0034 | 90 | 9 0 0035 | 16 | 1 6 0036 | 5D | F L0 0037 | 20 | 2 0 0038 | 56 | K GRPH 0039 | F6 | PP RM 0040 | 90 | 9 0 0041 | 29 | 2 9 0042 | 3A | K NOT 0043 | 57 | F X!=0 0044 | 39 | 3 9 0045 | 50 | R/S 0046 | 51 | GOTO 0047 | 00 | 0 0 0048 | 00 | AL(0) 0049 | 09 | AL(9) 0050 | 12 | AL(18) |
ОБЛАСТЬ ДВОИЧНЫХ ДАННЫХ Step | Code | Comment ------------------------- 1000 | 07 | Width 1001 | 07 | Height 1002 | 49 | byte 1003 | 2A | byte 1004 | 1C | byte 1005 | 7F | byte 1006 | 1C | byte 1007 | 2A | byte 1008 | 49 | byte 1009 | 07 | Width 1010 | 08 | Height 1011 | FF | byte 1012 | 81 | byte 1013 | 81 | byte 1014 | 81 | byte 1015 | 81 | byte 1016 | 81 | byte 1017 | FF | byte 1018 | 07 | Width 1019 | 08 | Height 1020 | 3C | byte 1021 | 42 | byte 1022 | 81 | byte 1023 | 81 | byte 1024 | 81 | byte 1025 | 42 | byte 1026 | 3C | byte ------------------------- Addr | Name ------------------------- 0048 | TABLE B 1000 | STAR B 1009 | SQUARE B 1018 | CIRCLE ------------------------- Reg | Name ------------------------- 0 | INDEX e | OBJECTADDRESS 9000 | \X0Y0 9010 | \CLS 9016 | \PUTGB 9029 | \NEXTKEY ------------------------- -- END OF FILE -- |
У модуля есть два выхода на 2 реле, и один вход.
| ![]() |
Возможные значения:
|
![]() Представим, что на двери установлен датчик открытия двери, подключённый к каналу С. Нам необходимо включать сигнализацию при открытии двкри и отключать сигнализацию когда дверь закрыта. ; Параллельный порт 1 SET \IOmode DO ; ожидать открытия в канале C REPEAT GET \IOModule 8 AND UNTIL(x<>0) ; Если Открыто - включить сигнализацию ; на канале A 5 SET \IOModule ; Ожидать закрытия в канале C REPEAT GET \IOModule 8 AND UNTIL(x=0) ; при закрытии Выключить сигнализацию ; в канале A 7 SET \IOModule LOOP |
Скомпилированная программа:
Область программы Step | Code | Keys ------------------------- 0000 | 01 | 1 0001 | F4 | PP M 0002 | 90 | 9 0 0003 | 90 | 9 0 0004 | F6 | PP RM 0005 | 90 | 9 0 0006 | 92 | 9 2 0007 | 08 | 8 0008 | 37 | K AND 0009 | 57 | F X!=0 0010 | 04 | 0 4 0011 | 05 | 5 0012 | F4 | PP M 0013 | 90 | 9 0 0014 | 92 | 9 2 0015 | F6 | PP RM 0016 | 90 | 9 0 0017 | 92 | 9 2 0018 | 08 | 8 0019 | 37 | K AND 0020 | 5E | F X=0 0021 | 15 | 1 5 0022 | 07 | 7 0023 | F4 | PP M 0024 | 90 | 9 0 0025 | 92 | 9 2 0026 | 51 | GOTO 0027 | 04 | 0 4 ------------------------- Reg | Name ------------------------- 9090 | \IOMODE 9092 | \IOMODULE ------------------------- -- END OF FILE -- |
![]() |
Организация диска - 2048 блоков по 264 байт. Я предполагаю, что 8 байт в каждом блоке зарезервировано для целей управления, и всего 256 байт используются для данных. Таким образом 256×2048=512×1024=512 kB. |
![]() |
Тесты точности | Тесты скорости | |||||
Forensic Тест научных функций, индикация в градусах. Набрать: arcsin(arccos(arctan(tan(cos(sin(9)))))) Результат: 8,9999999772404. Теоретическое значение 9 ! |
(прим. переводчика - в эмуляторе = 8,9999986; в калькуляторе = 9
Hebdogiciel20 =0 =1 2 FOR 0 SQR NEXT FOR 1 X^2 NEXT STOPРезультат: 1,9999999837026 Tеоретическое значение = 2 ! |
Простое суммирование:
0000 + 0001 GOTO 00Начинается 1 1 1 0 в стеке, и суммируется 60 секунд, сумма = 95756. Это примерно в 800 раз быстрее MK-61... |
Вычисление числа PI
Результаты использования программы выше на странице:
|
Use "RadioButtons", multiple menus, SELECT/ENDSELECT![]() |
Use checked lines.![]() |
Use the progress bar, multiple menus, FOR/NEXT, time calculation, sound.![]() |
Use a graphical menu with blocks inside an icon.![]() |
#MKFiles 2 ;-------------------- ; Register definitons ;-------------------- #reg a GrainNum ; количество песчинок за цикл #reg b PiValue ; результирующее приближение Пи (на экран) #reg c Total ; подсчёт песчинок во всех циклах #reg d InsideCircle ; подсчёт песчинок в четверти круга #reg e Duration ; продолжительность цикла в ЧЧ.ММСС (на экран) #reg 7 Address ; адрес подпрограммы отвечеющей за активный элемент #reg 0 Hundred ; для повтора циклов #reg 1 Iter ; idem #reg 6 progress ; значение от 9 до 116 для отрисовки строки прогрессии #reg 5 done ; флаг второго меню #reg 4 limit ; количество итераций |
Если вы бросаете песчинки на некий квадрат,, ![]() вероятность того, что он упадёт на четверть круга, вписанную в квадрат составляет: ![]() Таким образом, возможно симулировать этот процесс и получить аппроксимацию числа Пи! |
;-------------------- ; Main Menu description ;-------------------- #MENU ; меню 0 #STRING 1 "PI MonteCarlo" ; Титул большим шрифтом #HLINE ; разделитель #VINPUTD "Hundreds grains :" 92 GrainNum verif ; строка "input" устанавливает переменную GrainNum #ACTION "Run !" Calculation ; строка "действия" (переходит к вычислению) #OUTPUTD 0 "PI =" 32 PiValue ; строка "вывода" показывает регистр PiValue #OUTPUTF 0 "Time :" 50 Duration 2 4 ; строка "вывода" показывает время #HLINE ; разделитель #ACTION "Exit !" ProgramEnd ; строка "действия" (переходит к ProgramEnd) #ENDMENU |
Выглядит примерно так: ![]() Click on
|
;-------------------- ; Sub Menu description ;-------------------- #MENU ; меню 1 #STRING 1 "Calculating..." ; титул большими символами #BLANK 10 ; пропуск #STARTRECT ; начало отрисовки прямоугольника... #PROGRESSBAR progress ; ... прогресс основан на регистре "progress" #ENDRECT ; закончить прямоугольник #BLANK 10 ; пропуск #?LINK "Progress..." 0 Done "Done !" ; conditional link, отображает надпись "Progress" во время вычисления ; отображает надпись "Done !" в конце (при значении регистра done=1) ; ссылка на меню 0. #ENDMENU |
отисовывается прогресс расчёта: ![]() |
![]() выбрать и нажать "Done !" для возврата в главное меню. |
![]() Увидите значение числа Пи и время вычисления. |
Собственно программа расчёта. Она начинается сразу за определением переменных. Ядро системы целиком включено в "#MENUMAINLOOP", где содержится всё что требуется программе для управления меню. Всё что вам надо - подготовить различные подпрограммы для взаимодействия с экраном. |
;-------------------- ; My initializations ;-------------------- CX =PiValue =Total =InsideCircle =Duration =done 1 SET GrainNum ; по умолчанию = 1 hundred (сотня) = 100 песчинок за цикл 9 SET progress ; 9 = 0% в линейке прогресса $1000 SET limit ; не более 1000 сотен ;-------------------- ; The main loop here ;-------------------- #MENUMAINLOOP Address |
ProgramEnd: ; если нажат Exit!- просто останов. STOP |
также простая: она проверяет что не превышен лимит и что значение больше нуля. |
verif: @GrainNum ; введённое значение /-/ IF(X>=0)THEN 1 =GrainNum ; если отрицптельное или нуль, возврат к 1 ELSE @limit + IF(x<0)THEN ; если лимит<значение @limit =GrainNum ; тогда возврат к лимиту ENDIF ENDIF RTN |
;-------------------- ; My subprograms ;-------------------- Note: ; подпрограмма звука ENT $20 EXEC \Sound ; ВВОД частоты, продолжительность 20/100 sec REPEAT GET \SOUND ; звук прерван? UNTIL(x=0) ; if не равно нулю, включить RTN Calculation: 0 =done ; для условной ссылки #GOTOMENU 1 0 ; переключится на меню 1, активный элемент 0 GET \TIME HMS> =Duration ; сохранение времени старта @GrainNum =Hundred ; для цикла SUM Total ; обновить накопитель новыми песчинками FOR Hundred ; для каждой сотни песчинок 1 ENTER @Hundred @GrainNum / - ; вычислить положение индикатора (9-116) $107 * 9 + =progress ; согласно значению цикла #REDRAW ; показать новый индикатор $100 =Iter ; запустить на одну сотню песчинок FOR Iter RAN X^2 RAN X^2 + 1 - ; сравнить 1 со случайным x^2+y^2 IF(x<0)THEN ; если <1 тогда 1 SUM InsideCircle ; 1 в накопитель ENDIF NEXT NEXT $116 =progress ; индикатор на 100% 1 =done ; сменить условную ссылку #REDRAW ; показать интерфейс @InsideCircle @Total / $25 / =PiValue ; (inside/total) / 100 * 4 = PI GET \TIME HMS> @Duration - >HMS =Duration ; новое_время-время_старта = продолжительность $523 Gosub Note ; прелестная музыка сообщает об окончании $880 Gosub Note $699 Gosub Note RTN |
она начинается заданием в меню "Calculation" стартовых условий, (флагов, времени старта, отображения второго меню с индикатором). Затем основное меню обновляет позицию индикатора и сбрасывает песчинки кучками по 100. Когда вычисление окончено, Пи вычислено, подсчитано общее время, флаги изменяются и программа воспроизвдит 3 ноты, сигнализируя об окончании задачи. Также цикл программы в конце вычислений нарисует кнопку "Done !". По её нажатии произойдёт переход в меню 0. |