├── БЕРЁСТА ├── BIN │ ├── meander.bin │ ├── shift.bin │ ├── ADD_0_to_7.bin │ └── SUB_6_to_1.bin ├── берёста4.lay6 ├── programmator.png ├── beresta_schematic.png ├── описание БерЁста.docx ├── beresta_simulation.DSN └── КАнютаASM │ ├── img │ └── logo.ico │ ├── примеры │ ├── add.asm │ ├── sub.asm │ ├── тест.asm │ ├── меандр.asm │ └── сдвиг_старшим_битом_вперед.asm │ └── КАнютаASM.py ├── README.md └── LICENSE /БЕРЁСТА/BIN/meander.bin: -------------------------------------------------------------------------------- 1 | ! -------------------------------------------------------------------------------- /БЕРЁСТА/BIN/shift.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/BIN/shift.bin -------------------------------------------------------------------------------- /БЕРЁСТА/берёста4.lay6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/берёста4.lay6 -------------------------------------------------------------------------------- /БЕРЁСТА/programmator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/programmator.png -------------------------------------------------------------------------------- /БЕРЁСТА/BIN/ADD_0_to_7.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/BIN/ADD_0_to_7.bin -------------------------------------------------------------------------------- /БЕРЁСТА/BIN/SUB_6_to_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/BIN/SUB_6_to_1.bin -------------------------------------------------------------------------------- /БЕРЁСТА/beresta_schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/beresta_schematic.png -------------------------------------------------------------------------------- /БЕРЁСТА/описание БерЁста.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/описание БерЁста.docx -------------------------------------------------------------------------------- /БЕРЁСТА/beresta_simulation.DSN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/beresta_simulation.DSN -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/img/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/img/logo.ico -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/примеры/add.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/примеры/add.asm -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/примеры/sub.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/примеры/sub.asm -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/примеры/тест.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/примеры/тест.asm -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/примеры/меандр.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/примеры/меандр.asm -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/примеры/сдвиг_старшим_битом_вперед.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kelas1945/BERESTA-4/HEAD/БЕРЁСТА/КАнютаASM/примеры/сдвиг_старшим_битом_вперед.asm -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BERESTA-4 2 | Проект одноплатного четырехбитного компьютера на 155 серии времен СССР. 3 | 4 | Подробнее о проекте: [Статья](https://habr.com/ru/articles/813719/). 5 | [Видео](https://www.youtube.com/watch?v=BHI0DK1IGjk). 6 | 7 | Содержание архива: 8 | папка КАнютаASM - компилятор (исходник на Python, примеры) 9 | 10 | папка BIN - содержит коды прошивок для ПЗУ 11 | 12 | beresta_simulation.DSN -симулятор Proteus 13 | Симулятор немного отличается от оригинальной схемы, что никак не влияет на функционал. 14 | Выходы ОЗУ 155РУ2 (7489) дважды инвертируются и вместо РЕ3 или РТ4 используется ПЗУ 2764. 15 | И главное, чтобы симуляция запустилась не забываем в свойствах микросхемы ПЗУ 2764 16 | выбрать файл прошивки. Примеры прошивок лежат в папке BIN. 17 | 18 | beresta_schematic.PNG - принципиальная схема Берёста-4 19 | 20 | programmator.PNG - принципиальная схема программатора 21 | 22 | берёста4.LAY6 - печатная плата (Sprint Layout) 23 | 24 | описание БерЁста.DOCX - описание инструкций Берёста-4 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /БЕРЁСТА/КАнютаASM/КАнютаASM.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter.ttk import Combobox 3 | from tkinter import messagebox 4 | 5 | from PIL import ImageChops 6 | from PIL import Image 7 | 8 | from PIL import ImageTk 9 | from tkinter.ttk import Progressbar 10 | from tkinter import filedialog 11 | from tkinter import filedialog as fd 12 | 13 | import serial #установка pip install pyserial 14 | import time 15 | import binascii 16 | from time import sleep 17 | 18 | import tkinter as tk 19 | import tkinter.messagebox as mb 20 | from tkinter.messagebox import showinfo, askyesno 21 | from tkinter.messagebox import askyesnocancel 22 | from tkinter import ttk 23 | 24 | import matplotlib.pyplot as plt 25 | 26 | 27 | def insertText(): #открыть программы для микрохи 28 | file_name = fd.askopenfilename(filetypes=(("ассемблер", "*.asm"),("All files", "*.*"))) 29 | lb29.configure (text=file_name) 30 | 31 | if file_name!="": 32 | text.delete(0.0, END) 33 | text.tag_config('lable', background="yellow", foreground="red") 34 | text.tag_config('reg', foreground="blue") 35 | text.tag_config('kom', foreground="green") 36 | with open(file_name, encoding="cp1251") as f: 37 | s = f.readline() 38 | while s: 39 | 40 | s1=s.strip() 41 | result=s1.partition(':') 42 | if (result[1]!=''): 43 | text.insert(END, s1, 'lable') 44 | text.insert(END, "\n") 45 | else: 46 | sep2='//' 47 | result2=s.partition(sep2) 48 | 49 | if result2[1]==sep2: 50 | text.insert(END, result2[0]) 51 | text.insert(END, result2[1], 'kom') 52 | text.insert(END, result2[2], 'kom') 53 | else: 54 | text.insert(END, s) 55 | 56 | 57 | s = f.readline() 58 | f.close() 59 | 60 | 61 | def extractText(): #сохранить программу 62 | global new_project 63 | global modified 64 | modified=0 65 | 66 | file_name = fd.asksaveasfilename(filetypes=(("ассемблер", "*.asm"),("All files", "*.*") )) 67 | if file_name!="": 68 | lb29.configure (text=file_name) 69 | result3=file_name.partition('.asm') 70 | if (result3[1]!='.asm'): 71 | file_name=file_name+".asm" 72 | 73 | f = open(file_name, 'w') 74 | s = text.get(1.0, END) 75 | f.write(s) 76 | f.close() 77 | 78 | new_project=1 79 | else : new_project=0 80 | 81 | 82 | def clicked4(): #компиляция 83 | global realport 84 | global portActiv 85 | global stroki 86 | global step_step 87 | global step_step2 88 | global labelsRAM 89 | global wavform 90 | global wavform2 91 | global wavform3 92 | global wavform4 93 | global wavform_st 94 | 95 | 96 | ## ************ статические инструкции **** 97 | 98 | instruction = { 99 | 'mov a buf': 0x05, 100 | 'mov a p2': 0x25, 101 | 'mov a r1': 0x35, 102 | 'mov a ram': 0x45, 103 | 'mov a r2': 0x55, 104 | 105 | 'mov adr buf': 0x06, 106 | 'mov adr p2': 0x26, 107 | 'mov adr r1': 0x36, 108 | 'mov adr r2': 0x56, 109 | 'mov ram buf': 0x07, 110 | 'mov ram p2': 0x27, 111 | 'mov ram r1': 0x37, 112 | 'mov ram r2': 0x57, 113 | 'mov p1 buf': 0x08, 114 | 'mov p1 p2': 0x28, 115 | 'mov p1 r1': 0x38, 116 | 'mov p1 ram': 0x48, 117 | 'mov p1 r2': 0x58, 118 | 'mov r1 p2': 0x29, 119 | 'mov r1 buf': 0x09, 120 | 'mov r1 ram': 0x49, 121 | 'mov r1 r2': 0x59, 122 | 123 | 124 | 'mov r2 buf': 0x00, 125 | 'mov r2 p2': 0x20, 126 | 'mov r2 r1': 0x30, 127 | 'mov r2 ram': 0x40, 128 | 129 | 130 | 'add adr': 0x16, 131 | #'add ram': 0x17, 132 | 'add p1': 0x18, 133 | 'add a': 0x15, 134 | 'add r1': 0x19, 135 | 'add r2': 0x10, 136 | 137 | 'sub adr': 0x96, 138 | #'sub ram': 0x97, 139 | 'sub p1': 0x98, 140 | 'sub a': 0x95, 141 | 'sub r1': 0x99, 142 | 'sub r2': 0x90, 143 | 144 | 145 | 'jmp': 0x03, 146 | 'je': 0x13, 147 | 'jc': 0x23, 148 | 'jbz0': 0x43, 149 | 'jbz1': 0x53, 150 | 'jbz2': 0x63, 151 | 'jbz3': 0x73, 152 | 153 | } 154 | 155 | k155ru2() 156 | 157 | metka="" 158 | error="" 159 | adres=0 160 | intege="" 161 | lab="" 162 | 163 | step_step=0 164 | step_step2=0 165 | 166 | error_next=0 167 | 168 | lb4.configure (text="") 169 | kod.delete(0.0, END) 170 | 171 | mas = [] 172 | lable = [] 173 | lable_sp=[] 174 | lable_oper=[] 175 | 176 | integ =[] 177 | binarik=[] 178 | st_l=0 179 | f=0 180 | 181 | prg=[] 182 | 183 | del wavform[:] #очистить данные для диаграммы 184 | del wavform2[:] #очистить данные для диаграммы 185 | del wavform3[:] #очистить данные для диаграммы 186 | del wavform4[:] #очистить данные для диаграммы 187 | wavform_st=0 188 | 189 | 190 | #сбрасываем все регисты 191 | BUF.configure (text=str(hex(0))) 192 | A.configure (text=str(hex(0))) 193 | R1.configure (text=str(hex(0))) 194 | R2.configure (text=str(hex(0))) 195 | P1.configure (text=str(hex(0))) 196 | ADR.configure (text=str(hex(0))) 197 | ROMA1.configure (text=str(hex(0))) 198 | ROMA2.configure (text=str(hex(0))) 199 | 200 | 201 | for i in range(16): 202 | if i<8: labelsRAM[i].configure (text=str(hex(15))) 203 | else: labelsRAM[i].configure (text=str(hex(0))) 204 | 205 | 206 | s = text.get(1.0, END).splitlines() 207 | for line in s: 208 | stroka=line.lower() 209 | stroka=stroka.strip() #убрать пробелы в начале и конце 210 | #убрать пустые строки 211 | if stroka!="": 212 | #убрать коментарии 213 | result=stroka.partition('//') 214 | if (result[1]!=''): 215 | stroka=result[0] 216 | 217 | if stroka!="": 218 | #убрать коментарии 219 | prg.append([]) 220 | prg[adres]=stroka 221 | adres=adres+1 222 | 223 | #собрать названия всех меток 224 | result=stroka.partition(':') 225 | if (result[1]!=''): 226 | metka=result[0] 227 | metka=metka.strip() #убрать пробелы в начале и конце 228 | metka=" ".join(metka.split()) #убрать повторяющиеся пробелы 229 | for i in range(len(lable_sp)): 230 | if lable_sp[i]==metka: messagebox.showerror('Ошибка', 'дубликат метки <'+metka+'>') 231 | 232 | lable_sp.append([]) 233 | lable_sp[st_l]=metka 234 | st_l=st_l+1 235 | if (result[2]!=''): messagebox.showerror('Ошибка', 'отделите метку <'+stroka+'> от команды') 236 | 237 | 238 | adres=0 239 | metka="" 240 | 241 | ## for i in range(len(prg)): 242 | ## 243 | ## print (prg[i]) 244 | 245 | 246 | for ii in range(len(prg)): 247 | stroka=prg[ii].lower() 248 | stroka=stroka.strip() #убрать пробелы в начале и конце 249 | 250 | result=stroka.partition(':') 251 | if (result[1]!=''): 252 | 253 | metka=result[0] 254 | metka=metka.replace(","," ") #заменить запятую на пробел 255 | metka=metka.strip() #убрать пробелы в начале и конце 256 | metka=" ".join(metka.split()) #убрать повторяющиеся пробелы 257 | 258 | 259 | else: 260 | if stroka!="": 261 | 262 | stroka=stroka.strip() #убрать пробелы в начале и конце 263 | stroka=" ".join(stroka.split()) #убрать повторяющиеся пробелы 264 | result=stroka.partition(',') 265 | intege="" 266 | res2=result[2].strip() #убрать пробелы в начале и конце 267 | res0=result[0].strip() #убрать пробелы в начале и конце 268 | if (res2.isdigit()): 269 | stroka=res0 270 | intege=res2 271 | else: 272 | for i in range(len(lable_sp)): 273 | #print (lable_sp[i]) 274 | if lable_sp[i]==res2: 275 | stroka=res0 276 | lab=res2 277 | f=1 278 | if f==0: 279 | stroka=res0+" "+res2 280 | lab="" 281 | f=0 282 | intege=""; 283 | 284 | mas.append([]) 285 | lable.append([]) 286 | integ.append([]) 287 | lable_oper.append([]) 288 | stroka=stroka.strip() #убрать пробелы в начале и конце 289 | mas[adres]=stroka 290 | lable[adres]=metka 291 | integ[adres]=intege 292 | lable_oper[adres]=lab 293 | adres=adres+1 294 | metka="" 295 | 296 | 297 | print ("*** обработка ***") 298 | 299 | 300 | adres=0 301 | for i in range(len(mas)): 302 | unit=mas[i] 303 | if unit in instruction: 304 | data = instruction[unit] 305 | binarik.append([]) 306 | binarik[adres]=data 307 | adres=adres+1 308 | else: 309 | #обработка отсутствия значения в словаре 310 | if unit=='mov buf': 311 | data=int(integ[i]) 312 | data=data<<4 313 | data=data+4 314 | binarik.append([]) 315 | binarik[adres]=data 316 | adres=adres+1 317 | else: 318 | error=1 319 | if unit== 'mov roma1': 320 | for j in range(len(lable)): 321 | if lable[j]==lable_oper[i]: 322 | data=j&0x0F 323 | data=data<<4 324 | data=data+1 325 | binarik.append([]) 326 | binarik[adres]=data 327 | adres=adres+1 328 | error=0 329 | 330 | 331 | else: 332 | if unit== 'mov roma2': 333 | for j in range(len(lable)): 334 | if lable[j]==lable_oper[i]: 335 | data=j&0xF0 336 | data=data+2 337 | binarik.append([]) 338 | binarik[adres]=data 339 | adres=adres+1 340 | error=0 341 | if error==1: 342 | 343 | if error_next==0: messagebox.showerror('Информация', 'ошибка в <'+unit+','+integ[i]+lable_oper[i]+'> строке ') 344 | error_next+=1 345 | lb4.configure (text="ошибок = "+str(error_next)+" шт.") 346 | 347 | 348 | for i in range(len(binarik)): 349 | result=hex(binarik[i]) 350 | kod.insert(END,result+'\n') 351 | print ("*** готово ***") 352 | lbx.configure (text=str(len(binarik))) 353 | 354 | 355 | 356 | 357 | ######################################################## 358 | f = open('CodeForFlash\com.bin', 'wb') 359 | 360 | s = kod.get(1.0, END).splitlines() 361 | lbx.configure (text=str(len(s)-1)) 362 | for line in s: 363 | if line!='': 364 | i=int(line,16) 365 | f.write(bytes(chr(i), 'iso8859-1')) 366 | f.close() 367 | 368 | 369 | def clickk(): 370 | global new_project 371 | result = askyesnocancel(title="", message="СОХРАНИТЬСЯ?") 372 | if result==None: new_project=0 373 | elif result: 374 | extractText() 375 | else : new_project=1 376 | 377 | def newText(): 378 | global new_project 379 | global modified 380 | new_project=0 381 | if modified==0: 382 | lb29.configure (text="") 383 | text.delete(0.0, END) 384 | kod.delete(0.0, END) 385 | else: 386 | clickk() 387 | if new_project==1: 388 | lb29.configure (text="") 389 | text.delete(0.0, END) 390 | kod.delete(0.0, END) 391 | modified=0 392 | 393 | def info(): 394 | messagebox.showinfo('Информация', 'Компилятор для ЭВМ Берёста (и только для её!!!).\n cpurus@yandex.ru\n Попов Н.П.\n 2024 ') 395 | 396 | def read_reg(): 397 | global pb1 398 | global pb2 399 | global Flag 400 | global Aa 401 | global ADRus 402 | global ramsik 403 | global Aaa 404 | global AaaSUB 405 | 406 | adstrok=ADR.cget("text") 407 | ADRus=int(adstrok.partition('x')[2],16) 408 | 409 | ramsik = labelsRAM[ADRus].cget("text") 410 | ramsik= ramsik.partition('x')[2] 411 | 412 | Aa=A.cget("text") 413 | Aa= Aa.partition('x')[2] 414 | Aaa=int(ramsik,16)+int(Aa,16) 415 | AaaSUB=int(Aa,16)+int(ramsik,16) 416 | 417 | Flag=Aaa&0x10 418 | Flag=Flag>>4 419 | 420 | Aaa=Aaa&0x0F 421 | AaaSUB=AaaSUB+1 422 | AaaSUB=AaaSUB&0x0F 423 | 424 | 425 | def steps(): 426 | global step_step 427 | global step_step2 428 | global labelsRAM 429 | global labelsADR 430 | 431 | global pb1 432 | global pb2 433 | global Flag 434 | global Aa 435 | global ADRus 436 | global ramsik 437 | global Aaa 438 | global AaaSUB 439 | 440 | global wavform 441 | global wavform2 442 | global wavform3 443 | global wavform4 444 | global wavform_st 445 | 446 | 447 | #берем содержимое входного порта 448 | P2_in=0 449 | P2_in=enabled3.get()<<1 450 | P2_in=P2_in+enabled2.get()<<1 451 | P2_in=P2_in+enabled1.get()<<1 452 | P2_in=P2_in+enabled0.get() #P2_in = полубайт порта 453 | 454 | 455 | kod.tag_config('lable', background="yellow", foreground="red") 456 | s = kod.get(1.0, END).splitlines() 457 | #print (len(s)) 458 | if step_step>4 470 | 471 | 472 | read_reg() 473 | 474 | labelsADR[ADRus].configure (text=labelsADR[ADRus].cget("text"),background="white") 475 | 476 | #регистры=P2 477 | if (pb2==2)&(pb1==5): A.configure (text=str(hex(P2_in))) 478 | if (pb2==2)&(pb1==6): ADR.configure (text=str(hex(P2_in))) 479 | if (pb2==2)&(pb1==8): P1.configure (text=str(hex(P2_in))) 480 | if (pb2==2)&(pb1==9): R1.configure (text=str(hex(P2_in))) 481 | if (pb2==2)&(pb1==0): R2.configure (text=str(hex(P2_in))) 482 | 483 | if (pb2==2)&(pb1==7): 484 | if ADRus>7: 485 | labelsRAM[ADRus].configure (text=str(hex(P2_in))) 486 | else: 487 | 488 | strokus3=P2_in 489 | strokus3=~strokus3 490 | strokus3=strokus3&0x0f 491 | labelsRAM[ADRus].configure (text=str(hex(strokus3))) 492 | 493 | 494 | 495 | #BUF=число 496 | if pb1==4: BUF.configure (text=str(hex(pb2))) 497 | if pb1==1: ROMA1.configure (text=str(hex(pb2))) 498 | if pb1==2: ROMA2.configure (text=str(hex(pb2))) 499 | 500 | 501 | 502 | #регистры=BUF 503 | if (pb2==0)&(pb1==5): A.configure (text=BUF.cget("text")) 504 | if (pb2==0)&(pb1==9): R1.configure (text=BUF.cget("text")) 505 | if (pb2==0)&(pb1==8): P1.configure (text=BUF.cget("text")) 506 | if (pb2==0)&(pb1==0): R2.configure (text=BUF.cget("text")) 507 | if (pb2==0)&(pb1==6): ADR.configure (text=BUF.cget("text")) 508 | if (pb2==0)&(pb1==7): 509 | if ADRus>7: 510 | labelsRAM[ADRus].configure (text=BUF.cget("text")) 511 | else: 512 | strokus2=BUF.cget("text").partition('x')[2] 513 | strokus3=int(strokus2,16) 514 | strokus3=~strokus3 515 | strokus3=strokus3&0x0f 516 | labelsRAM[ADRus].configure (text=str(hex(strokus3))) 517 | 518 | #регистры=R1 519 | if (pb2==3)&(pb1==5): A.configure (text=R1.cget("text")) 520 | if (pb2==3)&(pb1==6): ADR.configure (text=R1.cget("text")) 521 | if (pb2==3)&(pb1==8): P1.configure (text=R1.cget("text")) 522 | if (pb2==3)&(pb1==0): R2.configure (text=R1.cget("text")) 523 | if (pb2==3)&(pb1==7): 524 | if ADRus>7: 525 | labelsRAM[ADRus].configure (text=R1.cget("text")) 526 | else: 527 | strokus2=R1.cget("text").partition('x')[2] 528 | strokus3=int(strokus2,16) 529 | strokus3=~strokus3 530 | strokus3=strokus3&0x0f 531 | labelsRAM[ADRus].configure (text=str(hex(strokus3))) 532 | 533 | 534 | 535 | #регистры=R2 536 | if (pb2==5)&(pb1==5): A.configure (text=R2.cget("text")) 537 | if (pb2==5)&(pb1==6): ADR.configure (text=R2.cget("text")) 538 | if (pb2==5)&(pb1==8): P1.configure (text=R2.cget("text")) 539 | if (pb2==5)&(pb1==9): R1.configure (text=R2.cget("text")) 540 | if (pb2==5)&(pb1==7): 541 | if ADRus>7: 542 | labelsRAM[ADRus].configure (text=R2.cget("text")) 543 | else: 544 | strokus2=R2.cget("text").partition('x')[2] 545 | strokus3=int(strokus2,16) 546 | strokus3=~strokus3 547 | strokus3=strokus3&0x0f 548 | labelsRAM[ADRus].configure (text=str(hex(strokus3))) 549 | 550 | 551 | 552 | #регистры=ОЗУ 553 | if (pb2==4)&(pb1==5): A.configure (text=str(hex(int(ramsik,16)))) 554 | if (pb2==4)&(pb1==8): P1.configure (text=str(hex(int(ramsik,16)))) 555 | if (pb2==4)&(pb1==9): R1.configure (text=str(hex(int(ramsik,16)))) 556 | if (pb2==4)&(pb1==0): R2.configure (text=str(hex(int(ramsik,16)))) 557 | 558 | #регистры=АЛУ+ 559 | if (pb2==1)&(pb1==5): A.configure (text=str(hex(Aaa))) 560 | if (pb2==1)&(pb1==6): ADR.configure (text=str(hex(Aaa))) 561 | if (pb2==1)&(pb1==8): P1.configure (text=str(hex(Aaa))) 562 | if (pb2==1)&(pb1==9): R1.configure (text=str(hex(Aaa))) 563 | if (pb2==1)&(pb1==0): R2.configure (text=str(hex(Aaa))) 564 | 565 | #регистры=АЛУ- 566 | if (pb2==9)&(pb1==5): A.configure (text=str(hex(AaaSUB))) 567 | if (pb2==9)&(pb1==6): ADR.configure (text=str(hex(AaaSUB))) 568 | if (pb2==9)&(pb1==8): P1.configure (text=str(hex(AaaSUB))) 569 | if (pb2==9)&(pb1==9): R1.configure (text=str(hex(AaaSUB))) 570 | if (pb2==9)&(pb1==0): R2.configure (text=str(hex(AaaSUB))) 571 | 572 | 573 | 574 | ST.configure (text=str(step_step)) 575 | 576 | read_reg() 577 | 578 | if Flag: FlagL.configure (text="True", fg='#0aff0a') 579 | else: FlagL.configure (text="False", fg='#ff0a0a') 580 | 581 | if int(ramsik,16)==int(Aa,16): FlagLZ.configure (text="True", fg='#0aff0a') 582 | else: FlagLZ.configure (text="False", fg='#ff0a0a') 583 | 584 | labelsADR[ADRus].configure (text=labelsADR[ADRus].cget("text"),background="yellow") 585 | 586 | step_step=step_step+1 587 | 588 | ROMad2=ROMA2.cget("text") 589 | ROMadd2=ROMad2.partition('x')[2] 590 | ROMtmp=int(ROMadd2,16) 591 | ROMtmp=ROMtmp<<4 592 | ROMad1=ROMA1.cget("text") 593 | ROMadd1=ROMad1.partition('x')[2] 594 | ROMtmp=ROMtmp+int(ROMadd1,16) 595 | 596 | #jmp 597 | if (pb2==0)&(pb1==3): 598 | step_step=ROMtmp 599 | 600 | #je 601 | if (pb2==1)&(pb1==3): 602 | if FlagLZ.cget("text")=="True": 603 | step_step=ROMtmp 604 | 605 | #'jc': 0x23, 606 | if (pb2==2)&(pb1==3): 607 | if FlagL.cget("text")=="True": 608 | step_step=ROMtmp 609 | 610 | ## 'jbz0': 0x43, 611 | ## 'jbz1': 0x53, 612 | ## 'jbz2': 0x63, 613 | ## 'jbz3': 0x73, 614 | bitA=A.cget("text") 615 | bitA=bitA.partition('x')[2] 616 | 617 | if (pb2==4)&(pb1==3)&(int(bitA,16)==1): step_step=ROMtmp 618 | if (pb2==5)&(pb1==3)&(int(bitA,16)==2): step_step=ROMtmp 619 | if (pb2==6)&(pb1==3)&(int(bitA,16)==4): step_step=ROMtmp 620 | if (pb2==7)&(pb1==3)&(int(bitA,16)==8): step_step=ROMtmp 621 | 622 | 623 | 624 | P1_wav_t=P1.cget("text") 625 | P1_wav=P1_wav_t.partition('x')[2] 626 | P1_wav_int=int(P1_wav,16)& 1 627 | P1_wav_int2=int(P1_wav,16)& 2 628 | if P1_wav_int2==2: P1_wav_int2=3 629 | else: P1_wav_int2=2 630 | P1_wav_int3=int(P1_wav,16)& 4 631 | if P1_wav_int3==4: P1_wav_int3=5 632 | else: P1_wav_int3=4 633 | P1_wav_int4=int(P1_wav,16)& 8 634 | if P1_wav_int4==8: P1_wav_int4=7 635 | else: P1_wav_int4=6 636 | 637 | wavform.append([])#данные для графика 638 | wavform[wavform_st]=P1_wav_int 639 | 640 | wavform2.append([])#данные для графика 641 | wavform2[wavform_st]=P1_wav_int2 642 | 643 | wavform3.append([])#данные для графика 644 | wavform3[wavform_st]=P1_wav_int3 645 | 646 | wavform4.append([])#данные для графика 647 | wavform4[wavform_st]=P1_wav_int4 648 | 649 | wavform_st=wavform_st+1 650 | 651 | 652 | 653 | def on_closing(): 654 | global modified 655 | if modified==1: 656 | if messagebox.askyesno("выход", "сохраниться?"): 657 | extractText() 658 | root.destroy() 659 | 660 | def on_modified(event): 661 | global modified 662 | modified=1 663 | 664 | def plot_port(): 665 | global wavform 666 | global wavform2 667 | global wavform3 668 | global wavform4 669 | plot, axes = plt.subplots(num="диаграмма порта P1") 670 | plt.plot(wavform) 671 | plt.plot(wavform2) 672 | plt.plot(wavform3) 673 | plt.plot(wavform4) 674 | plt.text(0, 6, "3", fontsize=15) 675 | plt.text(0, 4, "2", fontsize=15) 676 | plt.text(0, 2, "1", fontsize=15) 677 | plt.text(0, 0, "0", fontsize=15) 678 | plt.show() 679 | 680 | 681 | def starts(): 682 | a=0 683 | 684 | if entry.get().isdigit(): 685 | step = int(entry.get()) 686 | while a < step: 687 | a = a+1 688 | steps() 689 | else: messagebox.showerror('Информация', 'неверное количество итераций <'+entry.get()+'>') 690 | 691 | def k155ru2 (): 692 | global labelsRAM 693 | global labelsADR 694 | 695 | string='ADR' 696 | nums=['0','1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] 697 | labelsADR =[] 698 | labelsRAM =[] 699 | 700 | for x in nums: 701 | jk=string+x 702 | if int(x)<8: adr=tk.Label(frame4,text=jk, font=("Arial Bold", 15), fg='#0aafaf',background="white") 703 | else: adr=tk.Label(frame4,text=jk, font=("Arial Bold", 15), fg='#0a0aff',background="white") 704 | adr.grid(column=0, row=int(x)) 705 | labelsADR.append(adr) 706 | 707 | if int(x)<8: ram=tk.Label(frame4,text=str(hex(15)), font=("Arial Bold", 15)) 708 | else: ram=tk.Label(frame4,text=str(hex(0)), font=("Arial Bold", 15)) 709 | ram.grid(column=1, row=int(x)) 710 | labelsRAM.append(ram) 711 | 712 | #################################################################### 713 | global ff 714 | global ee4 715 | global modified 716 | global step_step 717 | global step_step2 718 | global labelsRAM 719 | 720 | global wavform 721 | global wavform2 722 | global wavform3 723 | global wavform4 724 | global wavform_st 725 | 726 | global labelsRAM 727 | 728 | 729 | wavform_st=0 730 | 731 | wavform=[] 732 | wavform2=[] 733 | wavform3=[] 734 | wavform4=[] 735 | 736 | step_step=0 737 | step_step2=0 738 | 739 | 740 | modified=0 741 | 742 | 743 | ff=0 744 | 745 | 746 | root = Tk() 747 | root.iconbitmap(r'img\logo.ico') 748 | root.title("КАнюта 1.0") 749 | root.geometry('1100x650+100+0') 750 | root.resizable(False, False) 751 | 752 | 753 | #root.overrideredirect(1) #полноэкранный режим 754 | #root.state('zoomed') 755 | 756 | frame1=Frame(root, bd=1, relief=RAISED) 757 | frame1.pack(side=TOP, fill=X) 758 | 759 | frame7=Frame(root, bd=1, relief=RAISED) 760 | frame7.pack(side=TOP, fill=X) 761 | 762 | 763 | frame9=Frame(root, bd=1, relief=RAISED) 764 | frame9.pack(side=BOTTOM, fill=Y) 765 | 766 | frame2=Frame(root, bd=1, relief=RAISED) 767 | frame2.pack(side=LEFT, fill=Y) 768 | 769 | frame6=Frame(root, bd=1, relief=RAISED) 770 | frame6.pack(side=RIGHT,fill=Y) 771 | 772 | frame3=Frame(root, bd=1, relief=RAISED) 773 | frame3.pack(side=RIGHT,fill=Y) 774 | 775 | frame4=Frame(root, bd=1, relief=RAISED) 776 | frame4.pack(side=RIGHT,fill=Y) 777 | 778 | frame5=Frame(root, bd=1, relief=RAISED) 779 | frame5.pack(side=RIGHT,fill=Y) 780 | 781 | 782 | 783 | mainmenu = Menu(frame1) 784 | root.config(menu=mainmenu) 785 | 786 | filemenu = Menu(mainmenu, tearoff=0) 787 | filemenu.add_command(label="Новый",command=newText) 788 | filemenu.add_command(label="Открыть",command=insertText) 789 | filemenu.add_command(label="Сохранить",command=extractText) 790 | filemenu.add_command(label="Выход",command=on_closing) 791 | 792 | helpmenu = Menu(mainmenu, tearoff=0) 793 | helpmenu.add_command(label="О программе", command=info) 794 | 795 | mainmenu.add_cascade(label="Файл", menu=filemenu) 796 | mainmenu.add_cascade(label="Справка", menu=helpmenu) 797 | 798 | 799 | 800 | lb29 = Label(frame7, text="", font=("Arial Bold", 10)) #название открытого файла 801 | lb29.pack(side=LEFT, fill=X) 802 | 803 | btn3 = Button(frame1, text="Компилировать", command=clicked4) 804 | btn3.grid(column=5, row=0, padx=5) 805 | 806 | message = StringVar() 807 | message.set("100") 808 | entry = tk.Entry(frame1, fg="black", bg="white", width=5, textvariable=message) 809 | entry.grid(column=6, row=0, padx=5) 810 | 811 | start = Button(frame1, text="старт", command=starts) 812 | start.grid(column=7, row=0, padx=5) 813 | 814 | step = Button(frame1, text="1 шаг", command=steps) 815 | step.grid(column=8, row=0, padx=5) 816 | 817 | 818 | plott = Button(frame1, text="диаграммы P1", command=plot_port) 819 | plott.grid(column=10, row=0, padx=5) 820 | 821 | 822 | 823 | lbx = Label(frame7, text="0", font=("Arial Bold", 15), fg='#0aff0a') 824 | lbx.pack(side=RIGHT, fill=X) 825 | lb3 = Label(frame7, text="размер бинарника", font=("Arial Bold", 15)) 826 | lb3.pack(side=RIGHT, fill=X) 827 | 828 | #метка для ошибок 829 | lb4 = Label(frame7, text="", font=("Arial Bold", 15), fg='#ff0a0a') 830 | lb4.pack(side=LEFT, fill=X) 831 | 832 | 833 | #текст программы 834 | text = Text(frame2, width=71, height=33, wrap=WORD) 835 | text.pack(side=LEFT, fill=Y) 836 | scroll = Scrollbar(frame2,command=text.yview) 837 | scroll.pack(side=LEFT, fill=Y) 838 | text.config(yscrollcommand=scroll.set) 839 | text.bind("", on_modified) 840 | 841 | #код программы 842 | kod = Text(frame2, width=4, height=33, wrap=WORD) 843 | kod.pack(side=LEFT, fill=Y) 844 | scroll1 = Scrollbar(frame2,command=kod.yview) 845 | scroll1.pack(side=LEFT, fill=Y) 846 | kod.config(yscrollcommand=scroll1.set) 847 | 848 | k155ru2() 849 | 850 | ROMA1a=Label(frame4,text="ROMa1", font=("Arial Bold", 15), fg='#0afa0f') 851 | ROMA1a.grid(column=0, row=17) 852 | ROMA1=Label(frame4,text=str(hex(0)), font=("Arial Bold", 15)) 853 | ROMA1.grid(column=1, row=17) 854 | 855 | ROMA2a=Label(frame4,text="ROMa2", font=("Arial Bold", 15), fg='#0afa0f') 856 | ROMA2a.grid(column=0, row=18) 857 | ROMA2=Label(frame4,text=str(hex(0)), font=("Arial Bold", 15)) 858 | ROMA2.grid(column=1, row=18) 859 | 860 | 861 | BUFa = Label(frame3, text="BUF", font=("Arial Bold", 15), fg='#0aff0a') 862 | BUFa.grid(column=1, row=0) 863 | BUF = tk.Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 864 | BUF.grid(column=2, row=0) 865 | 866 | Aa = Label(frame3, text="A", font=("Arial Bold", 15), fg='#ff0aff') 867 | Aa.grid(column=1, row=1) 868 | A = tk.Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 869 | A.grid(column=2, row=1) 870 | 871 | R1a = Label(frame3, text="R1", font=("Arial Bold", 15), fg='#0a0aff') 872 | R1a.grid(column=1, row=2) 873 | R1 = tk.Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 874 | R1.grid(column=2, row=2) 875 | 876 | R2a = Label(frame3, text="R2", font=("Arial Bold", 15), fg='#0a0aff') 877 | R2a.grid(column=1, row=3) 878 | R2 = tk.Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 879 | R2.grid(column=2, row=3) 880 | 881 | P1a = Label(frame3, text="P1", font=("Arial Bold", 15), fg='#0abfbf') 882 | P1a.grid(column=1, row=4) 883 | P1 = Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 884 | P1.grid(column=2, row=4) 885 | 886 | ADa = Label(frame3, text="ADR", font=("Arial Bold", 15), fg='#0abfbf') 887 | ADa.grid(column=1, row=9, pady=20) 888 | ADR = tk.Label(frame3, text=str(hex(0)), font=("Arial Bold", 15)) 889 | ADR.grid(column=2, row=9, pady=20) 890 | 891 | Flaga = Label(frame3, text="CF", font=("Arial Bold", 15), fg='#aabbbf') 892 | Flaga.grid(column=1, row=10) 893 | FlagL = tk.Label(frame3, text='False', font=("Arial Bold", 15), fg='#ff0a0a') 894 | FlagL.grid(column=2, row=10) 895 | 896 | Flagb = Label(frame3, text="ZF", font=("Arial Bold", 15), fg='#aabbbf') 897 | Flagb.grid(column=1, row=11) 898 | FlagLZ = tk.Label(frame3, text='False', font=("Arial Bold", 15), fg='#ff0a0a') 899 | FlagLZ.grid(column=2, row=11) 900 | 901 | 902 | 903 | STa=Label(frame5,text="ST", font=("Arial Bold", 15), fg='#0afa0f') 904 | STa.grid(column=0, row=0) 905 | ST=Label(frame5,text="0", font=("Arial Bold", 15)) 906 | ST.grid(column=0, row=1) 907 | 908 | 909 | STa=Label(frame6,text="P2", font=("Arial Bold", 15), fg='#0afa0f') 910 | STa.grid(column=0, row=0) 911 | 912 | enabled3 = IntVar() 913 | enabled_checkbutton3 = ttk.Checkbutton(frame6, variable=enabled3) 914 | enabled_checkbutton3.grid(column=1, row=1) 915 | enabled2 = IntVar() 916 | enabled_checkbutton2 = ttk.Checkbutton(frame6, variable=enabled2) 917 | enabled_checkbutton2.grid(column=2, row=1) 918 | enabled1 = IntVar() 919 | enabled_checkbutton1 = ttk.Checkbutton(frame6, variable=enabled1) 920 | enabled_checkbutton1.grid(column=3, row=1) 921 | enabled0 = IntVar() 922 | enabled_checkbutton0 = ttk.Checkbutton(frame6, variable=enabled0) 923 | enabled_checkbutton0.grid(column=4, row=1) 924 | 925 | STa=Label(frame6,text="3") 926 | STa.grid(column=1, row=2) 927 | STa=Label(frame6,text="2") 928 | STa.grid(column=2, row=2) 929 | STa=Label(frame6,text="1") 930 | STa.grid(column=3, row=2) 931 | STa=Label(frame6,text="0") 932 | STa.grid(column=4, row=2) 933 | 934 | 935 | root.protocol("WM_DELETE_WINDOW", on_closing) 936 | 937 | root.mainloop() 938 | --------------------------------------------------------------------------------