Reverse engineering of the first Seiko UC-2000 smart watch

Around the end of 1983 - the beginning of 84, the Japanese company Seiko began selling the first-ever computerized watch - Seiko Data-2000 and Seiko UC-2000. Data-2000 had the ability to store 2K notes, they had to be entered using a special compact keyboard that came with it. UC-2000, in fact, are the same Data-2000 with a different color case, but they were already positioned as part of the Wrist Information System, which, among other things, included the UC-2200 terminal, which is a computer with a Z80-compatible processor, the Basic interpreter and thermal printer, but without a screen, which was used as a clock (as it is not strange). Among other things, the terminal made it possible to download applications from special cartridges to the watch. You can read more about the Seiko line of early smart watches, for example, inthis article . In the same post I will tell you how I wrote (possibly) the first, for more than 33 years, program for this watch.

A note on watches in Popular Science magazine, 84 years old, the entire periphery is presented on the lower left photo.
Small introduction
I learned about the UC-2000 a couple of years ago, and about the same time I left such a comment on the GT. Since then, the idea to buy a watch and try to write something for them has not left me. Initially, I was inclined to buy the Epson RC-20, but they are so rare that during this time I saw only one offer on Ebay which I foolishly missed. As a result, I was tired of waiting and I bought a much more affordable UC-2000, without a terminal and keyboard, which were not needed for my purposes. In fact, of course, I would have to buy a docking station in order to remove the ROM dump from the application cartridge and understand the operation of the wireless interface that the clock used to communicate with peripherals. But, to my happiness, one person did this work back in 2002, he had a projectto create his own electronic clock, and he wanted to borrow a screen from Seiko. I don’t know how his work ended, but what was published on his site helped me a lot. This person (unfortunately, I don’t know his name) published applications from a complete cartridge, described the protocol of a wireless inductive interface, and also wrote an application that implements terminal functionality in many respects.
So, having these introductory notes, I wrote out the hours and started searching for information. Here it is necessary to clarify that I am not strong in assembler (all my life before that I wrote on it, maybe one and a half programs) nor, especially, in electronics, but as usual, the lack of knowledge was compensated by a great desire. Because of this, my methods and terminology may seem strange or even be wrong, I hope you correct me in the comments.
Reverse engineering
What was known about the architecture of this watch?
Here, on this advertising poster, perhaps, all the available technical information is displayed:

4bit CPU, 6KB ROM, 1.5KB LCD ROM, 2KB RAM.
And that’s all.
Photos of the insides do not provide any additional useful information - all microchips are expectedly open without any marking: From top to bottom, from left to right: inductance coil used for the wireless interface and battery compartment; a printed circuit board with a processor module on a ceramic substrate - 2 microcircuits, a CPU and RAM; matrix LCD panel - 4 lines of 10 characters, 5x7 pixels each; the reverse side of the board is 4 display controller chips. There is nothing left but to try to manually disassemble the programs from the standard cartridge, there are 5 in total:


- Amida - a game, a Japanese maze;
- Card - a card game;
- Hit - a game, shoot back from enemies;
- Race - tote simulator;
- Scheduler is a daily planner, the only practical application.
Judging by the advertisement, there was also a cartridge with a Japanese-English dictionary, but apparently it was only sold in the Japanese market, so finding it is not easy.
We look at the hex-dump of one of the applications, for example, the HIT game
00000000 CC 0F CC F5 CD 4A C1 09 C0 E0 CC 18 CC 22 CC 7C М.МхНJБ.АаМ.М"М|
00000010 CC CB C2 A9 C3 07 C3 9C C0 9B CD AE B0 00 45 78 МЛВГ.ГњА›Н°.Ex
00000020 45 5E 45 22 3C 10 A8 F2 88 82 3C 18 A8 F2 C2 27 E^E"<.Ёт€‚<.ЁтВ'
00000030 57 48 43 4E D4 21 3C 10 E1 22 45 22 CC 21 AE 89 WHCNФ!<.б"E"М!‰
00000040 AE 55 C2 43 57 48 43 56 D4 28 3C 10 FA 02 AE 49 UВCWHCVФ(<.ъ.I
00000050 C2 83 3C 18 8B 20 8B 0C 36 19 D0 3A 8B 22 8B 00 Вѓ<.‹ ‹.6.Р:‹"‹.
00000060 36 19 D0 3A 8B 14 36 19 D0 3A 8B 24 8B 08 36 19 6.Р:‹.6.Р:‹$‹.6.
00000070 D0 3A CC 4B 8B 20 8B 06 22 19 3E 10 9B 0E 9B 29 Р:МK‹ ‹.".>.›.›)
00000080 E7 21 CC 4A 3A 0E D4 4A 4E 11 EB 21 CC 4A 3B 0C з!МJ:.ФJN.л!МJ;.
00000090 D4 4A 4E 11 CC 4C 4E 11 3E 10 9B 2F 9B 0E 36 19 ФJN.МLN.>.›/›.6.
000000A0 D4 5D 5C 8F AE 55 3C 10 8A 08 AE 1D D8 59 8B 00 Ф]\ЏU<.Љ..ШY‹.
000000B0 CC 5B 8A 02 AE 46 AE 4C CC 28 83 23 83 02 AF F0 М[Љ.FLМ(ѓ#ѓ.Їр
000000C0 80 79 80 58 83 2B 83 0A AF F0 81 79 81 58 83 33 ЂyЂXѓ+ѓ.ЇрЃyЃXѓ3
000000D0 83 12 AF F0 82 79 82 58 83 21 83 00 AF F0 80 39 ѓ.Їр‚y‚Xѓ!ѓ.ЇрЂ9
000000E0 80 18 3C 10 B6 01 CC 5C AE 1D D8 78 8B 00 CC 7A Ђ.<.¶.М\.Шx‹.Мz
000000F0 8A 02 AE 46 AE 4C CC 5C 57 48 43 58 D4 85 3C 10 Љ.FLМ\WHCXФ…<.
00000100 F2 06 F6 0D FA 1C FE 02 AE 49 C2 DF CC BD 3C 00 т.ц.ъ.ю.IВЯМЅ<.
00000110 46 E8 3C 10 8A 02 AE 55 AE 46 AE 4C CC 85 8A 04 Fи<.Љ.UFLМ…Љ.
00000120 79 86 7C 10 3C 18 8C C7 8D C7 8E C7 8F C7 8C 85 y†|.<.ЊЗЌЗЋЗЏЗЊ…
00000130 AE 22 AE 55 A7 FD A7 F2 AE 46 AE 4C CC 85 3C 18 "U§э§тFLМ…<.
00000140 FA 24 8B 20 8B 14 22 19 CC A8 8B 22 8B 1C 2A 19 ъ$‹ ‹.".МЁ‹"‹.*.
00000150 3E 10 9B 35 9B 14 36 19 D0 B1 9B 2F 9B 0E 36 19 >.›5›.6.Р±›/›.6.
00000160 D4 BC 5C 8F AE 55 3C 10 8A 08 AE 1D D8 B9 8B 00 Фј\ЏU<.Љ..Ш№‹.
00000170 CC BB 8A 02 AE 46 AE 4C CC 85 A8 F2 88 82 8A 02 М»Љ.FLМ…Ёт€‚Љ.
00000180 5C 8F 45 22 3C 18 A8 F2 AE 22 3C 08 45 68 AE 55 \ЏE"<.Ёт"<.EhU
00000190 AE 46 AE 4C CC 85 57 48 43 58 D4 D1 3C 10 FA 02 FLМ…WHCXФС<.ъ.
000001A0 AE 49 C3 83 3C 18 80 BF 80 9E 87 D7 86 CF 85 C7 IГѓ<.ЂїЂћ‡Ч†П…З
000001B0 87 11 4F 11 80 F9 80 D8 82 A7 82 86 81 A3 81 82 ‡.O.ЂщЂШ‚§‚†ЃЈЃ‚
000001C0 AF B6 80 6D 80 4C 81 AB 81 8A AF B6 81 6D 81 4C Ї¶ЂmЂLЃ«ЃЉЇ¶ЃmЃL
000001D0 81 B3 81 92 AF B6 82 6D 82 4C 81 A1 81 80 AF B6 ЃіЃ’Ї¶‚m‚LЃЎЃЂЇ¶
000001E0 80 2D 80 0C 80 F5 80 D4 CC D1 3C 00 F5 81 CC FC Ђ-Ђ.ЂхЂФМС<.хЃМь
000001F0 3C 10 FA 09 3A 0A D0 FD C1 90 5C 8F 4F A5 FB A1 <.ъ.:.РэБђ\ЏOҐыЎ
00000200 CD 02 8A 06 CC FC 4C 5C 8F 44 34 5C D5 0F 8A 0A Н.Љ.МьL\ЏD4\Х.Љ.
00000210 8F A5 5C 8F 8E 21 41 32 AE 4C AE 5A CD 48 12 22 ЏҐ\ЏЋ!A2LZНH."
00000220 FA 21 CD 13 5C 8F E9 2B E5 21 CD 48 3C 18 8B 24 ъ!Н.\Џй+е!НH<.‹$
00000230 8B 0E 36 19 D1 1E 3C 10 8A A4 8A 8E CD 48 3E 18 ‹.6.С.<.Љ¤ЉЋНH>.
00000240 9A F1 9A D0 8B E0 8B CE 35 DF D1 2E 8B E2 8B C2 љсљР‹а‹О5ЯС.‹в‹В
00000250 35 DF D1 34 8B D6 35 DF D1 3A CD 40 8B E4 8B CC 5ЯС4‹Ц5ЯС:Н@‹д‹М
00000260 36 DF D1 48 85 DF CD 48 8B E2 8B C4 36 DF D1 48 6ЯСH…ЯНH‹в‹Д6ЯСH
00000270 85 DF CD 48 8B E2 8B D8 36 DF D1 48 85 DF CD 48 …ЯНH‹в‹Ш6ЯСH…ЯНH
00000280 87 CF 88 E0 88 D6 2B C7 36 DF D1 47 29 C7 8C C7 ‡П€а€Ц+З6ЯСG)ЗЊЗ
00000290 AE 46 CC FC 3C 10 FA 0A B6 01 C1 1A 4F 08 D9 53 FМь<.ъ.¶.Б.O.ЩS
000002A0 4C 5C AE 4F CD 54 8A 02 AE 46 CD 4D AE 46 AE 4F L\OНTЉ.FНMFO
000002B0 3C 10 8C C7 10 02 FC 01 CD 60 8C 00 3E 00 9B 0D <.ЊЗ..ь.Н`Њ.>.›.
000002C0 ED 38 45 30 10 22 B4 21 CD 66 8C 21 01 18 11 02 н8E0."ґ!НfЊ!....
000002D0 B9 00 CD 7E CD 81 CD 84 CD 87 CD 8A CD 8D CD 90 №.Н~НЃН„Н‡НЉНЌНђ
000002E0 CD 93 CD 96 CD 99 CD 9C CD 9F CD A2 CD A5 CD A8 Н“Н–ННњНџНўНҐНЁ
000002F0 CD AB 41 2E AE 97 CD 7C AF 13 CD 4D AE E2 AE EE Н«A.—Н|Ї.НMво
00000300 CD 7C AE EE AE CA CD 7C AE EE AE E2 CD 7C AE E2 Н|оКН|овН|в
00000310 AE CA CD 7C AE E2 AE CA CD 7C AE EE AE CA CD 7C КН|вКН|оКН|
00000320 AE E2 AE EE CD 7C AE EE AE CA CD 7C AE E2 AE EE воН|оКН|во
00000330 CD 7C AE E2 AE EE CD 7C AE E2 AE CA CD 7C AE E2 Н|воН|вКН|в
00000340 AE CA CD 7C AE E2 AE EE CD 7C AE EE AE CA CD 7C КН|воН|оКН|
00000350 AE E2 AE EE CD 7C AE E2 AE CA CD 7C 3C 00 F1 81 воН|вКН|<.сЃ
00000360 CD B4 3C 10 AE 89 CD BC 3C 10 BA 00 CD BD CD C4 Нґ<.‰Нј<.є.НЅНД
00000370 CD DA CD F3 CE 08 CD F3 C9 8F 78 23 7D 30 7D 31 НЪНуО.НуЙЏx#}0}1
00000380 7D 54 7C 90 AE 0D CD BC 78 00 AE 18 78 07 AE 73 }T|ђ.Нјx..x.s
00000390 AE 12 78 41 AE 7E AB D7 AB D7 7C 90 7D 52 7D 15 .xA~«Ч«Ч|ђ}R}.
000003A0 7D 11 7D 14 7D 71 7C 90 7C 90 7C F7 79 86 7C 11 }.}.}q|ђ|ђ|чy†|.
000003B0 A7 EF CD BC AE 2D 3C 18 AE 5F AE 52 AE 3A AE 6A §пНј-<._R:j
000003C0 AE 3F 3C 10 78 00 AE 73 8B 22 7F F7 78 22 7F F7 ?<.x.s‹".чx".ч
000003D0 7F F7 7F F7 7F F7 FB 23 8B 24 78 44 CD E7 78 66 .ч.ч.чы#‹$xDНзxf
000003E0 AE 7E 7F F7 CD BC 78 00 AE 0D 78 06 7D 37 7D 56 ~.чНјx..x.}7}V
000003F0 7D 15 7D 52 AB D7 AB D7 7D 71 7D 37 7D 55 7D 52 }.}R«Ч«Ч}q}7}U}R
00000400 7C 90 AE 12 78 84 AE 7E 79 84 AB E3 A7 EF CD BC |ђ.x„~y„«г§пНј
00000410 78 23 AE 18 78 40 AE 73 CD BC 7D 17 7D 11 7D 35 x#.x@sНј}.}.}5
00000420 7D 15 B0 00 7D 50 7D 37 7D 31 7D 36 7D 54 B0 00 }.°.}P}7}1}6}T°.
00000430 7D 54 7D 31 7D 35 7D 15 B0 00 8B 80 8B 62 8B 42 }T}1}5}.°.‹Ђ‹b‹B
00000440 34 5C B0 00 88 62 88 5C 89 62 89 5C 8A 62 8A 5C 4\°.€b€\‰b‰\ЉbЉ\
00000450 88 22 88 1C 8A 20 8A 12 B0 00 78 04 A0 AB A0 AB €"€.Љ Љ.°.x. « «
00000460 78 26 A0 AB A0 AB 78 60 A0 AB A0 AB 78 82 A0 AB x& « «x` « «x‚ «
00000470 A0 AB B0 00 3C 10 60 D7 7C B2 3C 18 B0 00 3C 10 «°.<.`Ч|І<.°.<.
00000480 62 95 7D F3 61 D7 7E 74 3C 18 B0 00 3C 00 46 62 b•}уaЧ~t<.°.<.Fb
00000490 B0 00 3C 00 42 7C B0 00 3C 00 45 F0 B0 00 3C 00 °.<.B|°.<.Eр°.<.
000004A0 46 70 B0 00 62 11 7F F5 B0 00 3C 00 EE A1 CE 59 Fp°.b..х°.<.оЎОY
000004B0 5C 4F B0 00 3C 00 EE A1 CE 5E 5D 0F B0 00 60 D7 \O°.<.оЎО^].°.`Ч
000004C0 7F F2 61 D7 7F F2 62 D7 7F F2 63 D7 7F F2 60 95 .тaЧ.тbЧ.тcЧ.т`•
000004D0 7F F2 B0 00 60 53 7C F6 61 53 7C F6 62 53 7C F6 .т°.`S|цaS|цbS|ц
000004E0 60 11 7C F6 B0 00 F0 81 CE 7A 7C 90 F0 61 CE 7B `.|ц°.рЃОz|ђрaО{
000004F0 7C 90 CE 7C 6C 80 6C 60 6C 40 B0 00 F1 81 CE 85 |ђО|lЂl`l@°.сЃО…
00000500 7C 90 F1 61 CE 86 7C 90 CE 87 6D 80 6D 60 6D 40 |ђсaО†|ђО‡mЂm`m@
00000510 B0 00 8C C7 8D C7 8E 85 5C 8F 41 30 A7 EF AE 46 °.ЊЗЌЗЋ…\ЏA0§пF
00000520 AE 4C 45 E8 3C 08 41 60 41 40 41 20 B0 00 3C 18 LEи<.A`A@A °.<.
00000530 82 A7 82 86 AE B2 80 F5 80 D4 82 AF 82 8E AE B2 ‚§‚†ІЂхЂФ‚Ї‚ЋІ
00000540 81 F5 81 D4 82 B7 82 96 AE B2 82 F5 82 D4 82 BF ЃхЃФ‚·‚–І‚х‚Ф‚ї
00000550 82 9E AE B2 83 F5 83 D4 82 A5 82 84 AE B2 80 B5 ‚ћІѓхѓФ‚Ґ‚„ІЂµ
00000560 80 94 B0 00 8B A0 8B 80 36 9D D2 C8 8B A0 8B 88 Ђ”°.‹ ‹Ђ6ќТИ‹ ‹€
00000570 36 9D D2 C8 8B A0 8B 9C 36 9D D2 C8 8B A2 8B 90 6ќТИ‹ ‹њ6ќТИ‹ў‹ђ
00000580 36 9D D2 C8 8B A4 8B 84 36 9D D2 C8 4E 95 CE C9 6ќТИ‹¤‹„6ќТИN•ОЙ
00000590 8E 85 B0 00 3C 18 3E 10 80 33 80 12 86 4B 85 43 Ћ…°.<.>.Ђ3Ђ.†K…C
000005A0 9B 01 BB 00 CE D6 CE D9 CE DC CE DF 88 60 88 48 ›.».ОЦОЩОЬОЯ€`€H
000005B0 CE E1 88 60 88 5C CE E1 88 62 88 50 CE E1 88 64 Об€`€\Об€b€PОб€d
000005C0 88 44 B0 00 3C 18 81 A3 81 82 AE FA 80 6D 80 4C €D°.<.ЃЈЃ‚ъЂmЂL
000005D0 81 B3 81 92 AE FA 82 6D 82 4C B0 00 3C 18 81 AB ЃіЃ’ъ‚m‚L°.<.Ѓ«
000005E0 81 8A AE FA 81 6D 81 4C 81 A1 81 80 AE FA 80 2D ЃЉъЃmЃLЃЎЃЂъЂ-
000005F0 80 0C B0 00 8B A2 8B 9C 35 9D D3 10 8B A0 8B 92 Ђ.°.‹ў‹њ5ќУ.‹ ‹’
00000600 35 9D D3 10 8B A2 8B 86 35 9D D3 10 8B A2 8B 9A 5ќУ.‹ў‹†5ќУ.‹ў‹љ
00000610 35 9D D3 10 8B A4 8B 8E 35 9D D3 10 4D 85 CF 12 5ќУ.‹¤‹Ћ5ќУ.M…П.
00000620 89 A2 89 9C B0 00 3C 18 81 A3 81 82 82 A7 82 86 ‰ў‰њ°.<.ЃЈЃ‚‚§‚†
00000630 AF B6 80 F5 80 D4 82 AF 82 8E AF B6 81 F5 81 D4 Ї¶ЂхЂФ‚Ї‚ЋЇ¶ЃхЃФ
00000640 82 B7 82 96 AF B6 82 F5 82 D4 82 BF 82 9E AF B6 ‚·‚–Ї¶‚х‚Ф‚ї‚ћЇ¶
00000650 83 F5 83 D4 82 A5 82 84 AF B6 80 B5 80 94 80 6D ѓхѓФ‚Ґ‚„Ї¶ЂµЂ”Ђm
00000660 80 4C 83 23 83 02 AF F0 80 79 80 58 3C 10 B6 02 ЂLѓ#ѓ.ЇрЂyЂX<.¶.
00000670 3C 18 CF 3B CF AF 81 AB 81 8A 82 A7 82 86 AF B6 <.П;ПЇЃ«ЃЉ‚§‚†Ї¶
00000680 80 F5 80 D4 82 AF 82 8E AF B6 81 F5 81 D4 82 B7 ЂхЂФ‚Ї‚ЋЇ¶ЃхЃФ‚·
00000690 82 96 AF B6 82 F5 82 D4 82 BF 82 9E AF B6 83 F5 ‚–Ї¶‚х‚Ф‚ї‚ћЇ¶ѓх
000006A0 83 D4 82 A5 82 84 AF B6 80 B5 80 94 81 6D 81 4C ѓФ‚Ґ‚„Ї¶ЂµЂ”ЃmЃL
000006B0 83 2B 83 0A AF F0 81 79 81 58 3C 10 B6 02 3C 18 ѓ+ѓ.ЇрЃyЃX<.¶.<.
000006C0 CF 62 CF AF 81 B3 81 92 82 A7 82 86 AF B6 80 F5 ПbПЇЃіЃ’‚§‚†Ї¶Ђх
000006D0 80 D4 82 AF 82 8E AF B6 81 F5 81 D4 82 B7 82 96 ЂФ‚Ї‚ЋЇ¶ЃхЃФ‚·‚–
000006E0 AF B6 82 F5 82 D4 82 BF 82 9E AF B6 83 F5 83 D4 Ї¶‚х‚Ф‚ї‚ћЇ¶ѓхѓФ
000006F0 82 A5 82 84 AF B6 80 B5 80 94 82 6D 82 4C 83 33 ‚Ґ‚„Ї¶ЂµЂ”‚m‚Lѓ3
00000700 83 12 AF F0 82 79 82 58 3C 10 B6 02 3C 18 CF 89 ѓ.Їр‚y‚X<.¶.<.П‰
00000710 CF AF 81 A1 81 80 82 A7 82 86 AF B6 80 F5 80 D4 ПЇЃЎЃЂ‚§‚†Ї¶ЂхЂФ
00000720 82 AF 82 8E AF B6 81 F5 81 D4 82 B7 82 96 AF B6 ‚Ї‚ЋЇ¶ЃхЃФ‚·‚–Ї¶
00000730 82 F5 82 D4 82 BF 82 9E AF B6 83 F5 83 D4 82 A5 ‚х‚Ф‚ї‚ћЇ¶ѓхѓФ‚Ґ
00000740 82 84 AF B6 80 B5 80 94 80 2D 80 0C 83 21 83 00 ‚„Ї¶ЂµЂ”Ђ-Ђ.ѓ!ѓ.
00000750 AF F0 80 39 80 18 3C 10 B6 02 3C 18 CF B5 AE 1D ЇрЂ9Ђ.<.¶.<.Пµ.
00000760 DB B3 8B 00 CF B4 8A 02 AE 4C B0 00 35 95 D7 EE Ыі‹.ПґЉ.L°.5•Чо
00000770 3E 10 90 ED 90 CC 89 A2 89 9C 8E 85 3C 00 EE A1 >.ђнђМ‰ў‰њЋ…<.оЎ
00000780 CF C2 5C 4F CF C3 3C 10 4D 4C 8B 80 8B 6A 8B 40 ПВ\OПГ<.ML‹Ђ‹j‹@
00000790 35 5C DB EE D7 D5 8B 66 24 5C 45 24 8E 21 3C 00 5\ЫоЧХ‹f$\E$Ћ!<.
000007A0 EE A1 CF D3 5D 0F CF D4 CF EE 8B 82 8B 60 35 5C оЎПУ].ПФПо‹‚‹`5\
000007B0 D7 EE 8B 80 8B 66 24 5C 45 28 8E 21 3C 00 EE A1 Чо‹Ђ‹f$\E(Ћ!<.оЎ
000007C0 CF E2 5D 0F CF E3 3C 18 8B 24 8B 0C 36 19 3C 10 Пв].Пг<.‹$‹.6.<.
000007D0 D3 EC 89 E4 89 CC CF EE 89 E2 89 D6 3C 18 B0 00 Ум‰д‰МПо‰в‰Ц<.°.
000007E0 36 19 D7 FD 8B 22 8B 1C 3C 00 EE A1 CF F8 5C 4F 6.Чэ‹"‹.<.оЎПш\O
000007F0 CF F9 3C 10 8A 08 5C 8F 8E 21 3C 18 B0 00 03 00 Пщ<.Љ.\ЏЋ!<.°...
If I had previously programmed AVR controllers in assembler, I would immediately have taken the first 14 bytes for the interrupt vector table, but I did not program AVR in assembler, so I thought it was just some kind of set of subroutine calls, i.e. suggested that:
- instructions occupy 2 bytes (this is also obvious because even bytes are often repeated, and odd bytes are much more random);
- the opcode is in the first byte, and the operands are in the second and, most likely, partially in the first;
- instructions of the form 0xC *** is a CALL command with a subroutine address.
After these 28 bytes there is a 0xB000 pair , the same instruction is found throughout the program, including at the very end (not counting the last two bytes, which turned out to be just some kind of program index in ROM), I assumed that this is a return from the subprogram, the command Ret .
This is all that I understood from the binary files after the first attack, even before the arrival of the clock. I tried to find string constants, but, to my surprise, I could not find anything similar to the desired sequence of character codes.
Then I tried to enter from the other side and started to look at the instruction sets of all 4-bit microprocessors and microcontrollers of the 70-80s that Google could reach - nothing like that. I, in my opinion, have never met a single 4-bit processor with double-byte instructions of constant length. There was some hope for modern 4-bit controllers from Epson, I thought that their command system could go back to the beginning of the 80s, but no, and there’s nothing. As a result, it was decided to wait for the clock and act by typing.
The watch arrived, whipped up such a transmitter:

It didn’t work with the coil from the first transformer that turned up, more precisely, it worked only without the back of the watch, and with the second coil that turned up, we managed to get a stable transmission. To download programs I used a slightly modified application published on sigma957.org .
Later, I reeled up the coil and assembled the transmitter on the ATtiny85, which is more suitable for practical use:

Another way to interact with your watch using your phone
When I did the transmitters, I noticed that the clock, in principle, can receive data at half the frequency - 16384 Hz, although the percentage of errors increases sharply. This led to a thought that at first seemed insane: to use the phone's speaker as a coil for transferring data to the watch. My surprise knew no bounds when the idea turned out to be quite workable, here is a video of the resulting program that fully emulates the operation of a compact keyboard:
Of course, the percentage of errors is large, about 10-20%, therefore, without feedback, there is no way to transfer applications. But, for example, you can adjust the contrast in the absence of a normal keyboard (after changing the battery, it is always lifted up so much that it is impossible to use the watch). Well, this does not work on all phones, I tested on the Nexus 5X - excellent, Galaxy S8 - bad, Nexus 5 - very bad, only individual bytes pass.
Of course, the percentage of errors is large, about 10-20%, therefore, without feedback, there is no way to transfer applications. But, for example, you can adjust the contrast in the absence of a normal keyboard (after changing the battery, it is always lifted up so much that it is impossible to use the watch). Well, this does not work on all phones, I tested on the Nexus 5X - excellent, Galaxy S8 - bad, Nexus 5 - very bad, only individual bytes pass.
First I played around with all the standard applications, then I started replacing suspicious instructions with 0x0000 (then I mistakenly assumed that it was NOP) and literally after a couple of replacements I came across a section with text output. I added two instructions to the piggy bank, setting the cursor position:
0111 10ii iii0 0iii, где i - позиция курсора, начиная с верхнего левого угла
and directly outputting the character:
0111 11ii iii1 0iii, где i - код символа
That's because of this interesting arrangement of bits, it turned out that I could not find the lines immediately.
I was in seventh heaven, I immediately wrote “Hello world”, which worked somehow strange due to the fact that I did not understand the purpose of the transition table in the header, but it was already something.
Then I figured out the addressing of the CALL command - it turned out that the routines that call such instructions from the header do not end with RET, as one might assume, but they end with calls to the routines from the ROM. It turns out, I was mistaken, instructions of the form 0xC *** are more like an unconditional jump of JMP A :
0011 AAAA AAAA AAAA, где A - адрес перехода, адресация двухбайтовая
but the call to the CALL A subroutine turned out to be an instruction:
1010 AAAA AAAA AAAA
Then the process stopped again. It was already possible to divide the program into separate blocks, the functions of which were generally clear, for example, it was possible to precisely determine that such and such a set of instructions displayed the score in the HIT game, but I could not figure out what each instruction did.
Having stumbled over hexes for a couple of days, I decided to use the good old method - to throw out from the program everything that does not break it, thus simplifying it as much as possible, and at the same time study what breaks. For preparation, I chose the Scheduler program, it has a minimum size (the code takes only 2/3, the remaining space is used to store the 31st note of 20 characters each) and it looked simpler than the others.
Here is her hex dump
00000000 CC2A CD6F CE6A C109 C0E0 CE83 CE8F CEA4 М*НoОjБ.АаОѓОЏО¤
00000010 CEAC CEB7 C307 CC41 C09B CCD3 CC30 B000 О¬О·Г.МAА›МУМ0°.
00000020 3C10 A8F2 3C18 77FC 6509 3E00 F501 CC20 <.Ёт<.wьe.>.х.М
00000030 8D01 77FC 6501 8AEA 8AD2 8AA0 9C87 AE26 Ќ.wьe.ЉкЉТЉ њ‡&
00000040 AC26 8C43 3C08 9B4C F746 CC31 8257 8236 ¬&ЊC<.›LчFМ1‚W‚6
00000050 8215 B000 CC10 4578 455E 4532 458E C227 ‚.°.М.ExE^E2EЋВ'
00000060 CC10 4570 4548 452A 89F0 89C0 5C03 3C18 М.EpEHE*‰р‰А\.<.
00000070 AC3E AEB4 A7EF 79C5 7C11 CC0F 8822 8808 ¬>ґ§пyЕ|.М.€"€.
00000080 B000 3C00 3990 D045 CC9D 3C18 3E08 9E7C °.<.9ђРEМќ<.>.ћ|
00000090 3A84 D857 3A94 D44E 3A6A D09D 8501 8B22 :„ШW:”ФN:jРќ….‹"
000000A0 8B08 2919 8940 2112 6102 6664 CC7B F692 ‹.).‰@!.a.fdМ{ц’
000000B0 83F3 1BEC D89D 8B22 8B1C 8920 8914 BBE0 ѓу.мШќ‹"‹.‰ ‰.»а
000000C0 CC73 CC9F CC76 CC7B CC81 CC88 CC6F CC8F МsМџМvМ{МЃМ€МoМЏ
000000D0 CC98 CC9B F266 3A78 D49F ACA0 CC9F ACA0 М.М›тf:xФџ¬ Мџ¬
000000E0 C4EC ACA0 C4D7 ACA0 3C00 C532 8B08 3419 Дм¬ ДЧ¬ <.Е2‹.4.
000000F0 D09D 4C11 CC9D 8B24 8B0E 3419 D09D 4C01 РќL.Мќ‹$‹.4.РќL.
00000100 CC9D 3419 DC86 ACA6 AC3E CC9D 2809 CC9D Мќ4.Ь†¬¦¬>Мќ(.Мќ
00000110 3419 D88D ACBB AC3E CC9D 2009 CC9D 3419 4.ШЌ¬»¬>Мќ .Мќ4.
00000120 DC95 8B08 3419 DC95 CC9D 8822 881C CC9D Ь•‹.4.Ь•Мќ€"€.Мќ
00000130 ACA6 AC3E CC9D ACBB AC3E AEB4 45F0 C39C ¬¦¬>Мќ¬»¬>ґEрГњ
00000140 3C08 3E00 8D22 4170 4190 B000 894A 8932 <.>.Ќ"ApAђ°.‰J‰2
00000150 8900 360A D0B1 8B40 8B22 8B08 2A1A ACB6 ‰.6.Р±‹@‹"‹.*.¬¶
00000160 CCB5 8A4E 8A3C 8A10 ACB6 B000 4C5B DCBA МµЉNЉ<Љ.¬¶°.L[Ьє
00000170 8866 8840 B000 894E 893C 8910 360A D0C6 €f€@°.‰N‰<‰.6.РЖ
00000180 8B40 8B22 8B08 221A ACCB CCCA 8A4A 8A32 ‹@‹"‹.".¬ЛМКЉJЉ2
00000190 8A00 ACCB B000 8B66 8B40 345B D4D1 8C43 Љ.¬Л°.‹f‹@4[ФСЊC
000001A0 CCD2 4C4B B000 3C00 F190 F583 3990 D0DB МТLK°.<.сђхѓ9ђРЫ
000001B0 CCE4 ACE9 CCE4 ACE9 8501 8B28 8B00 2119 Мд¬йМд¬й….‹(‹.!.
000001C0 6111 7C11 AEB4 45F0 C98F 3C18 41EE ACA0 a.|.ґEрЙЏ<.Aо¬
000001D0 CCE4 3C18 7800 7CB2 81A3 8182 2585 81C6 Мд<.x.|ІЃЈЃ‚%…ЃЖ
000001E0 77FD 674B 83E6 38D0 DCF6 13E2 E3E1 CD00 wэgKѓж8РЬц.вгбН.
000001F0 F8D3 8BA6 8B82 359D D91A 8B80 2D9D CD19 шУ‹¦‹‚5ќЩ.‹Ђ-ќН.
00000200 8BA6 8B84 359D D91A 8B82 2D9D 8BC2 8B80 ‹¦‹„5ќЩ.‹‚-ќ‹В‹Ђ
00000210 359E D519 4DC6 CD0C 8BA4 8B92 F345 359D 5ћХ.MЖН.‹¤‹’уE5ќ
00000220 D91A 4F9D 2D9D CD19 4F8D 359D D91A 4F9D Щ.Oќ-ќН.OЌ5ќЩ.Oќ
00000230 2D9D 4DC6 8BC4 8BA4 8B92 F346 359E D121 -ќMЖ‹Д‹¤‹’уF5ћС!
00000240 CD24 89C6 89A0 8982 39DA DD2E 1DD4 DD2B Н$‰Ж‰ ‰‚9ЪЭ..ФЭ+
00000250 7C90 6DC0 CD30 7CD1 6DC0 CD30 7C90 7CD1 |ђmАН0|СmАН0|ђ|С
00000260 7CB5 F1A3 6DA0 6D80 CD37 7C90 6D80 7C90 |µсЈm mЂН7|ђmЂ|ђ
00000270 8147 8960 2543 8B62 8B48 355B D941 2D5B ЃG‰`%C‹b‹H5[ЩA-[
00000280 CD3B 8B60 8B4E 355B D946 2D5B B940 CD4E Н;‹`‹N5[ЩF-[№@НN
00000290 CD52 CD56 CD5A CD5E CD62 CD66 7D53 7D55 НRНVНZН^НbНf}S}U
000002A0 7D36 CD69 7D35 7D37 7D36 CD69 7D54 7D55 }6Нi}5}7}6Нi}T}U
000002B0 7D15 CD69 7D57 7D15 7D14 CD69 7D54 7D30 }.Нi}W}.}.Нi}T}0
000002C0 7D55 CD69 7D16 7D52 7D31 CD69 7D53 7D11 }UНi}.}R}1Нi}S}.
000002D0 7D54 ABD7 ABD7 6202 ABC6 ABC6 B000 3C00 }T«Ч«Чb.«Ж«Ж°.<.
000002E0 8F03 8B58 E1E1 CD7A 341B D57A 398E D57F Џ.‹XббНz4.Хz9ЋХ.
000002F0 4782 C190 398E D179 E381 CE54 439C 3C10 G‚Бђ9ЋСyгЃОTCњ<.
00000300 3E00 4118 9C86 77FD 67CF 3C18 E9EF 3C10 >.A.њ†wэgП<.йп<.
00000310 89C6 89A0 8982 348E D597 F3C1 CD97 88C4 ‰Ж‰ ‰‚4ЋХ—уБН—€Д
00000320 88A4 8892 9486 3C18 45E8 CD97 41F6 3C10 €¤€’”†<.EиН—Aц<.
00000330 3E18 98E6 F4C4 38D8 D5A4 F4E5 CDA4 38F8 >..жфД8ШХ¤феН¤8ш
00000340 D5A4 4504 CDA4 4502 AE34 E101 CDAD F3C2 Х¤E.Н¤E.4б.Н.уВ
00000350 F7C3 CDAD 4D96 CDAD 4D86 958E 9C86 AE34 чГН.M–Н.M†•Ћњ†4
00000360 978E 89C2 89AC 899A E102 E50E CDCF 3BC2 —Ћ‰В‰¬‰љб.е.НП;В
00000370 D5BA 4D86 9E9E 228E 9796 4FD6 3BDE D5C1 ХєM†ћћ"Ћ—–OЦ;ЮХБ
00000380 8BC6 77FD 67C7 CDCF 3BC0 D5C7 4D86 9E8E ‹ЖwэgЗНП;АХЗM†ћЋ
00000390 228E 9596 4FC6 3BC8 D5C1 8BC0 CDC1 8F22 "Ћ•–OЖ;ИХБ‹АНБЏ"
000003A0 8B64 9877 9856 9835 3C18 359E D9DF 299E ‹d.w.V.5<.5ћЩЯ)ћ
000003B0 8BC0 8BA2 8B9E 359E 3C10 D9EA CDE7 2B8E ‹А‹ў‹ћ5ћ<.ЩкНз+Ћ
000003C0 89C0 89A2 899E 378E 3C10 D9ED CDE7 8A42 ‰А‰ў‰ћ7Ћ<.ЩнНзЉB
000003D0 8A3E CDF0 9A4D 9A2C CDF0 9A5D 9A3C CE05 Љ>НрљMљ,Нрљ]љ<О.
000003E0 8960 8942 8928 363A D21A 6023 AE2E AE2E ‰`‰B‰(6:Т.`#..
000003F0 AE2E AE2E 4E32 202B 896E 895E 8938 342B ..N2 +‰n‰^‰84+
00000400 D604 886A 8852 8820 CDF0 8960 8942 8928 Ц.€j€R€ Нр‰`‰B‰(
00000410 363A D21A 282B 896A 894E 8938 342B D613 6:Т.(+‰j‰N‰84+Ц.
00000420 886E 885C 8830 6023 AE2E AE2E AE2E AE2E €n€\€0`#....
00000430 4E32 CE05 92E3 92C2 92A1 3C18 3E00 9C87 N2О.’г’В’Ў<.>.њ‡
00000440 AC3E 8C43 AE26 AC26 AEB4 CE54 8FE7 83D7 ¬>ЊC&¬&ґОTЏзѓЧ
00000450 758C 67C7 66A6 64C7 6485 B000 6743 6743 uЊgЗf¦dЗd…°.gCgC
00000460 6743 6743 6743 B000 8D86 8E86 8AA2 18C2 gCgCgC°.Ќ†Ћ†Љў.В
00000470 F0D3 81E6 38D0 DE3D 11E2 E1E1 CE42 F8C4 рУЃж8РЮ=.вббОBшД
00000480 8A9C CE4A 8A9E CE4A 77FD 67CF F3C2 8A98 ЉњОJЉћОJwэgПуВЉ.
00000490 CE4A 8A9A 2196 CE37 8E85 8A94 F0A3 2196 ОJЉљ!–О7Ћ…Љ”рЈ!–
000004A0 18A2 CE4E 2186 B000 F581 CE62 E6E2 E2E6 .ўОN!†°.хЃОbжввж
000004B0 CE62 E2E8 FA29 4E21 FA28 CE62 3A44 DE64 Оbвиъ)N!ъ(Оb:DЮd
000004C0 4E42 FA43 3C18 41FA C190 A7FD 3C18 41FC NBъC<.AъБђ§э<.Aь
000004D0 45E4 CE64 3C00 F581 CE81 E6E2 E2E8 CE81 EдОd<.хЃОЃжввиОЃ
000004E0 E2F0 3C18 E5E1 CE81 E1E9 ACA6 CE7C 3C18 вр<.ебОЃб鬦О|<.
000004F0 E5E1 CE81 E1E3 ACBB 45E2 CE7F 41FC 3C00 ебОЃб㬻EвО.Aь<.
00000500 4670 AEB4 C11A 5748 434E D68E 3C18 EDE2 FpґБ.WHCNЦЋ<.нв
00000510 45F0 CE8E 41EE ACA0 AEB4 A81C C243 5748 EрОЋAо¬ ґЁ.ВCWH
00000520 4356 D69D 3E00 9B4C F342 F748 CE9D 8D22 CVЦќ>.›LуBчHОќЌ"
00000530 AEB4 5C04 A7F2 79C5 7C10 C283 A81C ACA0 ґ\.§тyЕ|.ВѓЁ.¬
00000540 3C18 41EE 3C00 C262 5748 435A D6AB 3C18 <.Aо<.ВbWHCZЦ«<.
00000550 ACA6 AEB4 A81C C2DF 5748 435C D6B3 3C18 ¬¦ґЁ.ВЯWHC\Ці<.
00000560 ACBB AEB4 A81C C383 3C00 4662 B000 3C00 ¬»ґЁ.Гѓ<.Fb°.<.
00000570 F581 CEBE 3C18 E5E1 CEBE 41FA AEB4 426E хЃОѕ<.ебОѕAъґBn
00000580 C2A9 C000 C000 C000 C000 C000 0000 0000 ВА.А.А.А.А.....
00000590 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000600 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000610 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000620 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000630 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000640 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000650 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000660 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000670 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000680 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000690 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000006F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000700 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000710 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000720 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000730 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000740 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000750 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000760 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000770 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000780 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000790 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000007F0 0000 0000 0000 0000 0000 0000 0100 0100 ................
Such tactics immediately began to bear fruit. Having found the button click processing routines, it became clear that the table in the header is the transitions to the addresses of event handlers (not interrupts), I still have not figured out this table to the end, here is what I know at the moment:
Index in title | Description | Standard Handler Address |
---|---|---|
0 | Application launch | 0x227 |
1 | Second timer | 0x190 |
2 | - | 0x11A |
3 | - | 0x109 |
4 | - | 0x0E0 |
5 | Pressing the Mode Button | 0x243 |
6 | Click Transmit | 0x283 |
7 | Right click | 0x2DF |
8 | Left click | 0x383 |
9 | - | 0x2A9 |
10 | - | 0x307 |
eleven | Received byte to reel | 0x39C |
12 | - | 0x09B |
thirteen | I didn’t fully understand, but the handler usually implements a screen redraw | 0x98F |
14 | APL button (application launch) is pressed on the external keyboard | - |
Thanks to the same button handlers by which the user selects the desired note, he identified the addition and subtraction instructions - 0x221A and 0x2A1A , although he has not yet figured out the operands. Then one of the conditional transitions was identified, again without operands.
Scheduler by this time looked something like this
00000000 CC28 B000 B000 B000 B000 B000 CC58 CC38 М(°.°.°.°.°.МXМ8
00000010 CC48 B000 B000 B000 B000 CCD3 B000 B000 МH°.°.°.°.МУ°.°.
00000020 3C18 0000 3E00 9C87 8C43 0000 8AE4 8ADC <...>.њ‡ЊC..ЉдЉЬ
00000030 8AA0 8257 8236 8215 3C08 0000 F74A CC2E Љ ‚W‚6‚.<...чJМ.
00000040 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050 CC10 4578 455E 4532 458E C227 B000 0000 М.ExE^E2EЋВ'°...
00000060 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070 3C18 AC7D C2DF B000 0000 0000 0000 0000 <.¬}ВЯ°.........
00000080 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090 3C18 AC9D C383 B000 0000 0000 0000 0000 <.¬ќГѓ°.........
000000A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000B0 3C18 AC98 C283 B000 0000 0000 0000 0000 <.¬.Вѓ°.........
000000C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000D0 3C18 AC98 3C00 4670 C11A B000 0000 0000 <.¬.<.FpБ.°.....
000000E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000F0 0000 0000 0000 0000 0000 8B40 8B22 8B08 ..........‹@‹"‹.
00000100 2A1A AC88 CC87 8A4E 8A3C 8A10 AC88 B000 *.¬€М‡ЉNЉ<Љ.¬€°.
00000110 4C5B DC8C 8866 8840 B000 0000 0000 0000 L[ЬЊ€f€@°.......
00000120 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000130 0000 0000 0000 0000 0000 8B40 8B22 8B08 ..........‹@‹"‹.
00000140 221A ACA8 CCA7 8A4A 8A32 8A00 ACA8 B000 ".¬ЁМ§ЉJЉ2Љ.¬Ё°.
00000150 8B66 8B40 345B D4AE 8C43 CCAF 4C4B B000 ‹f‹@4[ФЊCМЇLK°.
00000160 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000170 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000180 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000190 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001A0 0000 0000 0000 3C00 F190 F583 3990 D0DB ......<.сђхѓ9ђРЫ
000001B0 CCE4 ACE9 CCE4 ACE9 8501 8B28 8B00 2119 Мд¬йМд¬й….‹(‹.!.
000001C0 6111 7C11 AC01 45F0 C98F 3C18 41EE AC01 a.|.¬.EрЙЏ<.Aо¬.
000001D0 CCE4 3C18 7800 7CB2 81A3 8182 2585 81C6 Мд<.x.|ІЃЈЃ‚%…ЃЖ
000001E0 72FC 674B 83E6 38D0 DCF6 13E2 E3E1 CD00 rьgKѓж8РЬц.вгбН.
000001F0 F8D3 8BA6 8B82 359D D91A 8B80 2D9D CD19 шУ‹¦‹‚5ќЩ.‹Ђ-ќН.
00000200 8BA6 8B84 359D D91A 8B82 2D9D 8BC2 8B80 ‹¦‹„5ќЩ.‹‚-ќ‹В‹Ђ
00000210 359E D519 4DC6 CD0C 8BA4 8B92 F345 359D 5ћХ.MЖН.‹¤‹’уE5ќ
00000220 D91A 4F9D 2D9D CD19 4F8D 359D D91A 4F9D Щ.Oќ-ќН.OЌ5ќЩ.Oќ
00000230 2D9D 4DC6 8BC4 8BA4 8B92 F346 359E D121 -ќMЖ‹Д‹¤‹’уF5ћС!
00000240 CD24 89C6 89A0 8982 39DA DD2E 1DD4 DD2B Н$‰Ж‰ ‰‚9ЪЭ..ФЭ+
00000250 7C90 6DC0 CD30 7CD1 6DC0 CD30 7C90 7CD1 |ђmАН0|СmАН0|ђ|С
00000260 7CB5 F1A3 6DA0 6D80 CD37 7C90 6D80 7C90 |µсЈm mЂН7|ђmЂ|ђ
00000270 8147 8960 2543 8B62 8B48 355B D941 2D5B ЃG‰`%C‹b‹H5[ЩA-[
00000280 CD3B 8B60 8B4E 355B D946 2D5B B940 CD4E Н;‹`‹N5[ЩF-[№@НN
00000290 CD52 CD56 CD5A CD5E CD62 CD66 7D53 7D55 НRНVНZН^НbНf}S}U
000002A0 7D36 CD69 7D35 7D37 7D36 CD69 7D54 7D55 }6Нi}5}7}6Нi}T}U
000002B0 7D15 CD69 7D57 7D15 7D14 CD69 7D54 7D30 }.Нi}W}.}.Нi}T}0
000002C0 7D55 CD69 7D16 7D52 7D31 CD69 7D53 7D11 }UНi}.}R}1Нi}S}.
000002D0 7D54 ABD7 ABD7 6202 ABC6 ABC6 B000 0000 }T«Ч«Чb.«Ж«Ж°...
000002E0 5445 5354 0000 0000 0000 0000 0000 0000 TEST............
000002F0 5400 0000 0000 0000 0000 0054 0000 T..........T..
At the same time, the program almost completely retained the functionality for working with notes. As I later realized, blocks for entering notes from the keyboard, various checks for boundary conditions, and the like “redundant” code were cut. I shuffled the remaining subprograms into a convenient and compact form, since the transition instructions were already known to me. Compactness, by the way, was very relevant, because transmitting 2048 bytes per clock takes about 30 seconds. Imagine the process - we zero out two bytes, send it to the clock, wait 30 seconds, see what happened - if everything breaks badly, then return the instruction, if it does not break then look for the next victim and again 30 seconds. Slow, very slow. Therefore, with Scheduler reduced to 512 bytes, work went much faster.
Further sticking with a stick led to the understanding that the instructions 0x8AE4 0x8ADC 0x8AA0 in the program launch handler set the address of the current note, I interpreted them as loading the direct value into the LDI R register , I
1000 10RR RRRi iii-, где R - регистр назначения, i - загружаемое значение
Now it became clear that we have 32 four-bit registers, besides for instructions everywhere looming everywhere 0x3C00 , 0x3C08 , 0x3C10 , 0x3C18 I took for some signs as the choice of the current bank of registers, which was later confirmed. Total, we have 4 banks of 32 registers. Finding registers was one of the key points, after which I really believed in the ability to disassemble the programs of this watch.
Located nearby0x8257 0x8236 0x8215 turned out to be instructions for copying the registers MOV Rd, Rs
1000 00dd ddds ssss, где d - регистр назначения, s - исходный регистр
After that, I easily sorted out the operands of the previously found operations of addition and subtraction, these turned out to be operations on the groups of registers ADM Rd, Rs and SBM Rd, Rs (M - from Multiple). These instructions, operating with groups of registers, showed that each bank of registers is divided into another 4 pages of 8 registers. Each instruction working with groups of registers can operate with any number of registers within the page, while the indexes of the initial and final register of the group must coincide for both operands. I’m probably not completely explaining it, so I'll try again in the picture:

It turns out that some commands can operate directly with 4-byte values - not bad for a four-bit processor. For ease of use of group commands, I decided to name registers by type RA0, RA1 ... RA7, RB0, RB1, etc. etc.
So, in general, the syntax of the instructions has become more or less understood, it remains a matter of technique to formally describe as many instructions as possible. To do this, firstly, I made a list of all the instructions from the standard programs in binary form and divided it into groups of the first six bits, so you could immediately figure out what data the command is operating on, for example, if the right bit in the group is always 0, then almost certainly the second operand is an immediate value. Secondly, at this point I already knew enough instructions to write a clock program in machine codes that would display the current values of the registers of all banks - click on one button - the values of the registers of the 0th bank are displayed, on the other the 1st etc. . This was my first useful program for the UC-2000!

The contents of the zero register bank
In the process of writing this program, I caught some terrible glitches with the value of zero register of each bank and could not understand what was happening. As it turned out, the reason was that I used 0x0000 as a NOP, but in fact it is a register addition command, i.e. I constantly added the zero register to myself in different places).
With these two tools, in a couple of days I already formally described more than 40 instructions. Instructions with non-standard syntax, such as INC and DEC, took a lot of time.
The instruction with opcode 010101 took even more time ., which always went first in button handlers and was found in some other places. As it turned out, she copied the value to the register of the current bank from a certain group of registers, which I called I / O registers. Empirically established that there are only 16 of these registers, a description of the purpose of those that I managed to understand in the following table:
Register | Description |
---|---|
IO0 | 0th bit - set if the left or right button is pressed; 2nd — the MODE or TRANSMIT button is pressed; 3rd - byte per coil received |
IO1 | Reception data flag |
IO2 | Transfer Error Flag |
IO3 | - |
IO4 | - |
IO5 | Senior nibble taken to the reel |
IO6 | Low nibble taken to the reel |
IO7 | Button interrupt flags, 0th bit - left button, 1st - right. 2nd - MODE, 3rd - TRANSMIT |
IO8 | Flags of the pressed buttons, the same sequence as in IO7 |
IO9 | - |
IO10 | - |
IO11 | - |
IO12 | - |
IO13 | - |
IO14 | 1/16 second counter |
IO15 |
Also, using the program for displaying register values, I found out that the first two banks of registers are used by the internal clock program, therefore, for obvious reasons, it is better to use only 2 and 3 banks as general purpose registers.
Purpose of registers of the 0th bank:
Register | Description |
---|---|
RA0 | Current minutes, low order, BCD |
RA1 | Current minutes, high order, BCD |
RA2 | Current hour in 12 hour format |
RA3 | 12 hour interval, 0 - AM, 1 - PM |
RA4 | Current date, low-order, BCD |
RA5 | Current Date, High Rank, BCD |
RA6 | Current month |
RA7 | The current day of the week. 0 - Sunday and onwards |
RB0 | Minutes of the alarm, low order, BCD |
RB1 | Alarm Minutes, High, BCD |
RB2 | Alarm clock in 12-hour format |
RB3 | 0th bit - AM / PM alarm, 1st - on / off |
RB4 | Current mode, 0 - hours, 1 - downloadable program and further, alarm clock, stopwatch, time setting, data transfer |
RA5 | Current seconds, low-order, BCD |
RA6 | Current seconds, high order, BCD |
RA7 ... RD7 | - |
In the 1st bank, only the RB0 - RB3 registers are of interest, they are used to indicate events that the loaded program will respond to. The rest of the registers of this bank are used differently in different hours of operation, so I did not analyze them (although, of course, there might be something interesting)
The result of all this work was a set of 61 formally described instructions. Unfortunately, I could not restore everything that is visible from the table (which is slightly lower under the spoiler), there is a gap in the interval 5800-5BFF, maybe one or even several instructions were hidden there. There are very specialized teams, such as a piezodynamic speaker, most likely there is something more behind them, I did not even give names to such instructions. Questionable NOP. Many instructions have insignificant bits marked by me as "-", in fact, of course, some can influence something that I missed.
It took a lot of time to select the appropriate mnemonics, some teams are named rather ugly (especially in the middle of the table), I myself constantly forgot them.
Then I came close to the possibility of writing applications, but assembler was very necessary for this, writing something more difficult than viewing register values in machine codes, when the size of the opcodes and operands is not a multiple of a byte, to put it mildly, is not convenient.
Assembler
I naively assumed that there are ready-made implementations of universal assemblers, the once heard phrase “table assembler” was spinning in my head, by which I started to google. It turned out yes, indeed, there is such a class of assemblers called “table driven assembler”, but I could not find anything suitable - these were either long-abandoned products from the 90s such as TDASM, or modern, very limited projects “on the knee”. And that would be all right, but all these table assemblers had a serious flaw - they each had their own notation, which perfectly described the instructions of the processors from the supported list, but didn’t want to describe the set of instructions of the UC-2000: some simply could not work with operands multiple bytes, some could not address both bytes and double-byte commands, etc.
I was already inclined to write my extremely simple assembler, but came across axasm ( article with a description of the author). Briefly, the macro substitution C is used to describe the instructions, due to which greater versatility is obtained, and the entire analysis of the code falls on the preprocessor, we only need to first convert the code of the form “MOV Rd, Rs” to MOV (Rd, Rs), for This author uses AWK, and the entire process is automated with a Bash script. At the same time, of course, this method has disadvantages - it is impossible to hang several instructions on one assembler command, under Windows you will have to use MinGW (although you can certainly rewrite everything, but I was too lazy), and in general, all this is quite cumbersome.
So, I made a description of the commands I know for axasm and things went much better, there was only a disassembler for convenient analysis of regular applications, which I quickly corrected by writing my very simple, but fully functional.
By that time, I had already described most of the instructions, and you could start writing something “serious”.
Programming
As the first program, I again chose Tetris.
Of course, I didn’t have any illusions about the capabilities of the 4-bit processor in the 83-year electronic clock, but I was still unpleasantly surprised by the absence of seemingly elementary commands:
- No bit shift! In no form. It seems to be a basic operation, the absence of which complicates a lot. Let’s say the left shift can be replaced by adding the register to itself, but what is the replacement of the right shift with? (
- There is no logical operation on two registers! AND, OR, and XOR are case-sensitive with an immediate value. But what is there, there is not even a denial.
- You cannot use indirect register addressing in any command, this is probably not very surprising, but very inconvenient.
- The depth of the subprogram call stack is only 3 levels, this is not surprising either, but I, not used to such restrictions, first caught strange program hangs and for a long time I could not understand what was the matter.
Here, for example, how I had to pervert to implement the disjunction of the two registers RA0, RA1:
XORI RA0, 0xF ;вместо отрицания
BTJR RA0, 0, +1 ;тестим 0-й бит
ORI RA1, 1 ;если не установлен то OR'им с единицей
BTJR RA0, 1, +1 ;а если установлен то сразу прыгаем сюда
ORI RA1, 2 ;и дальше в том же духе
BTJR RA0, 2, +1
ORI RA1, 4
BTJR RA0, 3, +1
ORI RA1, 8 ;как хорошо, что у нас всего 4 бита
But each instruction takes 2 bytes out of 2048, a nightmare.
But all arithmetic instructions have analogues with decimal correction. This suggests that the microprocessor was originally developed and used by Seiko-Epson engineers for something like a watch with a calculator function, and only then it was adapted for the UC-2000.
Another unpleasant surprise for me was the lack of access to individual display pixels, although the photos of the clock, which show that the time is displayed with non-standard digits, occupying two familiarities at once, seemed to hint at such an opportunity. However, as soon as I saw the symbol table , there were no illusions left - the halves of the numbers are just separate symbols.
Therefore, for Tetris I had to use pseudo-graphic symbols, since they are enough to use the symbols █, ▀, and "to split the screen into 8x10 пикселей pixels’, the playing field turns out to be something like this:

The "glass" is rotated and occupies the entire screen, but even so, of course, does not reach the classic 10x20 cells.
Despite this limited set of instructions, Tetris fit in 700 bytes, although when I first started it, I was afraid that I could not fit in 2 KB.
Source code with comments
;Даем регистрам более подходящие имена
##define brdAdr RA2
##define brdValTop RA3
##define brdValBtm RA4
##define ind RA5
##define drawLine RA6
##define appState RA7
##define curLine RB0
;9, 10
##define preLine RB3
##define scoresL RB4
;13, 14
##define scoresH RB7
##define piceAngle RC0
##define piceNum RC1
##define piceSelecter RC2
##define piceShift RC3
##define scoresAddL RC4
;21;22
##define scoresAddH RC7
##define curPosL RC4
##define curPosH RC5
##define piceLn0t RD0
##define piceLn0b RD1
##define piceLn1t RD2
##define piceLn1b RD3
##define piceLn2t RD4
##define piceLn2b RD5
##define piceLn3t RD6
##define piceLn3b RD7
;Вычисляем адрес игрового поля
##define brdAdr2b (((board*2)>>8) & 0x0F)
##define brdAdr1b (((board*2)>>4) & 0x0F)
##define brdAdr0b (((board*2) ) & 0x0F)
;Вычисляем адрес фигур
##define picesAdr2b (((pices*2)>>8) & 0x0F)
##define picesAdr1b (((pices*2)>>4) & 0x0F)
##define picesAdr0b (((pices*2) ) & 0x0F)
ORG 0
;Таблица переходов на обработчики событий
JMP start ;Адреса обработчиков нужных событий
JMP timer
JMP 0x11A ;или адреса штатных обработчиков для ненужных событий
JMP 0x109
JMP 0x0E0
JMP btn_mode
JMP btn_transm
JMP btn_right
JMP btn_left
JMP 0x2A9
JMP 0x307
JMP 0x39C
JMP 0x09B
JMP update_screen
RET
;Обработчик запуска приложения
start:
CLRM RB1, RB3%8
LDI RB2, 0xF ;Подписываемся на события нажатия всех 4-х кнопок
LCRB B2
LDI appState, 1
JMP 0x227 ;Все обработчики должны завершаться переходом на определенные адреса
;Обработчик нажатия MODE
btn_mode:
CPJR RB3, 0, btn_mode_startapp ;Если приложение уже запущено, то отписываемся от всех событий
CLRM RB1, RB3%8 ;иначе обработчики так и будут вызываться даже после "выхода" из программы
JMP 0x243
btn_mode_startapp:
LDI RB3, 8 ;А если запуск только произошел то подписываемся на таймер
LDI RB1, 1 ;и перерисовку экрана
JMP 0x243
;Обработчик TRANSMIT
btn_transm:
LARB B3
LCRB B2
ADI piceAngle, 4 ;Поворачиваем фигуру
JMP update_screen
;Обработчик правой кнопки
btn_right:
LARB B3
LCRB B2
CPJR appState, 2, btn_right_c1
CALL prepareNewGame
JMP 0x2DF
btn_right_c1:
INC piceShift, piceShift%8 ;Перемещаем фигуру вправо
JMP 0x2DF
;Обработчик левой кнопки
btn_left:
LARB B3
LCRB B2
DEC piceShift, piceShift%8 ;Перемещаем фигуру влево
JMP 0x383
;Обработчик секундного таймера
timer:
LARB B3
LCRB B2
CPJR appState, 2, timer_draw
CPJR appState, 3, timer_clear_lines_screen
JMP 0x190
timer_clear_lines_screen:
LDI appState, 2 ;Возвращаемся к игре после отображения очков
JMP update_screen
timer_draw:
INC curLine, curLine%8 ;Падение фигуры
JMP update_screen
update_screen:
LARB B3
LCRB B2
CPJR appState, 2, update_screen_draw
PLAI 125 ;Очищаем
STLI 0 ;экран
CPJR appState, 0, update_screen_gover
CPJR appState, 3, update_screen_clear_lines
update_screen_start:
PLAI 12
PSAI STR_TETRIS ;Пишем TETRIS на заставке
CALL OS_PRINT0-6 ;используя функцию внутренней программы часов
JMP 0x98F
update_screen_gover:
PLAI 10 ;GAME OVER
PSAI STR_GAMEOVER
CALL OS_PRINT0-10
JMP update_screen_print_scores
update_screen_clear_lines:
PLAI 10 ;После каждой сброшенной линии
PSAI STR_SCORE ;на секунду показываем заработанные очки
CALL OS_PRINT0-8
STL scoresAddL+1
STL scoresAddL
PSAI STR_TOTAL
update_screen_print_scores:
CALL OS_PRINT0-6 ;Выводим Total
STL scoresH ;и
STL scoresH-1 ;общее
STL scoresH-2 ;количество
STL scoresL ;очков
JMP 0x98F
update_screen_draw:
CALL updatePice ;Обновляем состояние фигуры
CALL draw ;и все перерисовываем
JMP 0x98F
;Инициализация новой игры
prepareNewGame:
CALL OS_CLRCB
LDI appState, 2
LDI brdAdr, brdAdr2b
LDI brdAdr-1, brdAdr1b
LDI brdAdr-2, brdAdr0b
PSAM brdAdr-2, brdAdr%8
CLRM scoresL, scoresH%8
CLRM brdValTop, brdValBtm%8
LDI ind, 10
prepareNewGame_loop:
STSM brdValTop, brdValBtm%8
DEC ind, ind%8
JNC prepareNewGame_loop
;Подготовка новой фигуры
prepareNewPice:
CLRM curLine, preLine%8
LDI piceShift, 2
prepareNewPice_random:
IN piceAngle, 14
ADD piceNum, piceAngle
CPI piceNum, 7
JNC prepareNewPice_random
LDI piceAngle, 0
CMP scoresAddL, scoresAddL+1
JZ updatePice
ADBM scoresL, scoresAddH
LDI appState, 3
JMP update_screen
;обновляем фигуру
updatePice:
LDI brdAdr, picesAdr2b
LDI brdAdr-1, picesAdr1b
LDI brdAdr-2, picesAdr0b
ADM brdAdr-2, piceSelecter
PSAM brdAdr-2, brdAdr%8
LDSM piceLn0t, piceLn0b%8
LDSM piceLn1t, piceLn1b%8
LDSM piceLn2t, piceLn2b%8
LDSM piceLn3t, piceLn3b%8
;двигаем фигуру влево-вправо
shiftPice:
MOV ind, piceShift
shiftPice_loop:
CPJR ind, 0, shiftPice_end
ADM piceLn0t, piceLn3b ;Замена левого сдвига на сложение регистра самого с собой
BTJR piceLn1t, 0, +4 ;По ходу движения проверяем выход фигуры
BTJR piceLn2t, 0, +3 ;за левую границу
BTJR piceLn3t, 0, +2 ;игрового поля
DEC ind, ind%8
JMP shiftPice_loop
JMP processCollision
shiftPice_end:
CPI preLine, 15
JNZ checkCollision
;Объединяем упавшую фигуру с содержимым игрового поля и сохраняем полученное в board
storePice:
LDI brdAdr, brdAdr2b
LDI brdAdr-1, brdAdr1b
LDI brdAdr-2, brdAdr0b
ADM brdAdr-2, curLine+2
CLRM scoresAddL, scoresAddH%8
LDI ind, 3
storePice_loop:
PSAM brdAdr-2, brdAdr%8
LDSM brdValTop, brdValBtm%8
XORI piceLn0t, 0xF ;ужасный OR двух пар регистров
XORI piceLn0b, 0xF
BTJR piceLn0t, 0, +1
ORI brdValTop, 1
BTJR piceLn0t, 1, +1
ORI brdValTop, 2
BTJR piceLn0t, 2, +1
ORI brdValTop, 4
BTJR piceLn0t, 3, +1
ORI brdValTop, 8
BTJR piceLn0b, 0, +1
ORI brdValBtm, 1
BTJR piceLn0b, 1, +1
ORI brdValBtm, 2
BTJR piceLn0b, 2, +1
ORI brdValBtm, 4
BTJR piceLn0b, 3, +1
ORI brdValBtm, 8
PSAM brdAdr-2, brdAdr%8
STSM brdValTop, brdValBtm%8
CMP piceLn0t, piceLn0b ;заодно проверяем нет ли заполненных линий
JZ storePice_loop2_end
CPI brdValTop, 0xF
JNZ storePice_loop2_end
CPI brdValBtm, 0xF
JNZ storePice_loop2_end
MVACM brdAdr-2, brdAdr%8
ADBM scoresAddL, scoresAddH ;и подсчитываем
INCB scoresAddL, scoresAddH%8 ;очки если есть
storePice_loop2:
DEC brdAdr-2, brdAdr%8 ;и удаляем заполненные линии
PSAM brdAdr-2, brdAdr%8
LDSM brdValTop, brdValBtm%8
STSM brdValTop, brdValBtm%8
CPJR brdValBtm, 0, +1
JMP storePice_loop2
CPJR brdValTop, 0, +1
JMP storePice_loop2
MVCAM brdAdr-2, brdAdr%8
storePice_loop2_end:
LSHM piceLn3b, 0
LSHM piceLn3b, 0
INC brdAdr-2, brdAdr%8
DEC ind, ind%8
JNC storePice_loop
JMP prepareNewPice
;проверяем столкновение фигуры с содержимым игрового поля
checkCollision:
LDI brdAdr, brdAdr2b
LDI brdAdr-1, brdAdr1b
LDI brdAdr-2, brdAdr0b
ADM brdAdr-2, curLine+2
PSAM brdAdr-2, brdAdr%8
MVACM piceLn0t, piceLn3b
LDI ind, 4
checkCollision_loop:
LDSM brdValTop, brdValBtm%8
checkCollision_loop2:
CMP piceLn0t, piceLn0b
JZ checkCollision_end2
ADM piceLn0t, piceLn0b
JC checkCollision_compare
ADM brdValTop, brdValBtm
JMP checkCollision_loop2
checkCollision_compare:
ADM brdValTop, brdValBtm
JC processCollision
JMP checkCollision_loop2
checkCollision_end2:
LSHM piceLn3b, 0
LSHM piceLn3b, 0
DEC ind, ind%8
JNZ checkCollision_loop
MVCAM piceLn0t, piceLn3b
MVACM piceAngle, piceShift ;сохраняем валидную
MOV preLine, curLine ;позицию фигуры
RET
;обрабатываем столкновение
processCollision:
CPJR curLine, 0, gameOver
CMP curLine, preLine
JZ processCollision_pre
MOV curLine, preLine ;восстанавливаем валидную позицию фигуры
LDI preLine, 15 ;маркер, что фигура уперлась в пол и нужна новая
processCollision_pre:
MVCAM piceAngle, piceShift ;восстанавливаем валидную позицию фигуры
JMP updatePice
;конец игры
gameOver:
LDI appState, 0
JMP update_screen
;рисуем игровое поле
draw:
LDI brdAdr, brdAdr2b
LDI brdAdr-1, brdAdr1b
LDI brdAdr-2, brdAdr0b
PSAM brdAdr-2, brdAdr%8 ;Указываем на адрес игрового поля
MVAC curLine, curLine ;Копированием в дополнительный банк удобно бэкапить регистры
LDI curPosL, 0xE ;Значение регистров с позицией экранного курсора
LDI curPosH, 0x1 ;на 4 строку первого столбца
LDI ind, 0
draw_loop0: ;проходим поочередно все строки игрового поля сверху вниз [...]
LDSM brdValTop, brdValBtm%8 ;Загружаем регистры brdValTop и brdValBtm первой строкой игрового поля,
;указатель после этого перейдет на следующий байт автоматически
CMP curLine, ind ;если фигура пересекается с текущей отображаемой строкой то рисуем и ее
JNZ draw_ORend
XORI piceLn0b, 0xF ;еще один ужасный OR
XORI piceLn0t, 0xF
BTJR piceLn0b, 0, +1
ORI brdValBtm, 1
BTJR piceLn0b, 1, +1
ORI brdValBtm, 2
BTJR piceLn0b, 2, +1
ORI brdValBtm, 4
BTJR piceLn0b, 3, +1
ORI brdValBtm, 8
BTJR piceLn0t, 0, +1
ORI brdValTop, 1
BTJR piceLn0t, 1, +1
ORI brdValTop, 2
BTJR piceLn0t, 2, +1
ORI brdValTop, 4
BTJR piceLn0t, 3, +1
ORI brdValTop, 8
LSHM piceLn3b, 0 ;Вместо отсутствующей косвенной адресации регистров, сдвигаем регистры с фигурой
LSHM piceLn3b, 0 ;на байт влево на каждом шаге цикла, и получаем нужное значение всегда в piceLn0t-piceLn0b
CMP piceLn0t, piceLn0b
JZ draw_ORend
INC curLine, curLine%8
draw_ORend:
CPJR ind, 0, draw_b1
draw_loop1: ;[...] слева направо
PLAM curPosL, curPosH%8 ;устанавливаем экранный курсор на нужную позицию
BTJR brdValBtm, 2, +5
BTJR brdValBtm, 3, +2
STLI 0x20 ;и
JMP draw_else2
STLI 0xE8 ;рисуем
JMP draw_else2
BTJR brdValBtm, 3, +2
STLI 0xE7 ;подходящий
JMP draw_else2
STLI 0xFF ;символ
draw_else2:
ADM brdValTop, brdValBtm ;Сдвигаем текущую строку игрового поля на 2 бита
ADM brdValTop, brdValBtm ;т.к. каждое знакоместо у нас отображает состояние 2 бит
SBI curPosL, 0xA ;Вот так сложно на
JNC draw_loop1 ;4-битном процессоре
DEC curPosH, curPosH%8 ;вычесть 10
JNC draw_loop1 ;у пары регистров (так переходим к предыдущей строке на экране)
LDI curPosH, 0x1 ;после того, как нарисовали линию
ADI curPosL, 0x9 ;возвращаем курсор опять на 4 строку
JNC draw_b1 ;но уже на
INC curPosH, curPosH%8 ;следующее знакоместо
draw_b1:
INC ind, ind%8 ;переходим к следующей строке игрового поля
CPI ind, 11 ;если еще не все
JNZ draw_loop0
MVCA curLine, curLine ;восстанавливаем curLine
RET
;Область данных
STR_TETRIS:
DS "TETRIS"
STR_GAMEOVER:
DS "GAME OVER!"
STR_SCORE:
DS "Score +"
STR_TOTAL:
DS "Total "
;игровое поле, каждая строка аккуратно умещается в байт
board:
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b00000000
DB 0b11111111
;Фигуры вместе с поворотами
;Конечно, сильно избыточно, но при этому получается очень удобно:
;на адресацию каждой фигуры нужно использовать минимум 3 полубайта (в 3-х регистрах),
;при этом, просто сложив младший полубайт с 4 мы меняем поворот фигуры,
;а инкрементируя средний меняем фигуру.
;Красиво и никаких проверок выхода за границы и прочих усложнений кода.
pices:
DB 0b00000000 ;o 0°
DB 0b00000011
DB 0b00000011
DB 0b00000000
DB 0b00000000 ;o 90°
DB 0b00000011
DB 0b00000011
DB 0b00000000
DB 0b00000000 ;o 180°
DB 0b00000011
DB 0b00000011
DB 0b00000000
DB 0b00000000 ;o 270°
DB 0b00000011
DB 0b00000011
DB 0b00000000
DB 0b00000000 ;I 0°
DB 0b00001111
DB 0b00000000
DB 0b00000000
DB 0b00000001 ;I 90°
DB 0b00000001
DB 0b00000001
DB 0b00000001
DB 0b00000000 ;I 180°
DB 0b00001111
DB 0b00000000
DB 0b00000000
DB 0b00000001 ;I 270°
DB 0b00000001
DB 0b00000001
DB 0b00000001
DB 0b00000000 ;s 0°
DB 0b00000011
DB 0b00000110
DB 0b00000000
DB 0b00000010 ;s 90°
DB 0b00000011
DB 0b00000001
DB 0b00000000
DB 0b00000000 ;s 180°
DB 0b00000011
DB 0b00000110
DB 0b00000000
DB 0b00000010 ;s 270°
DB 0b00000011
DB 0b00000001
DB 0b00000000
DB 0b00000000 ;z 0°
DB 0b00000110
DB 0b00000011
DB 0b00000000
DB 0b00000001 ;z 90°
DB 0b00000011
DB 0b00000010
DB 0b00000000
DB 0b00000000 ;z 180°
DB 0b00000110
DB 0b00000011
DB 0b00000000
DB 0b00000001 ;z 270°
DB 0b00000011
DB 0b00000010
DB 0b00000000
DB 0b00000000 ;L 0°
DB 0b00000111
DB 0b00000100
DB 0b00000000
DB 0b00000010 ;L 90°
DB 0b00000010
DB 0b00000011
DB 0b00000000
DB 0b00000001 ;L 180°
DB 0b00000111
DB 0b00000000
DB 0b00000000
DB 0b00000011 ;L 270°
DB 0b00000001
DB 0b00000001
DB 0b00000000
DB 0b00000000 ;J 0°
DB 0b00000111
DB 0b00000001
DB 0b00000000
DB 0b00000001 ;J 90°
DB 0b00000001
DB 0b00000011
DB 0b00000000
DB 0b00000100 ;J 180°
DB 0b00000111
DB 0b00000000
DB 0b00000000
DB 0b00000011 ;J 270°
DB 0b00000010
DB 0b00000010
DB 0b00000000
DB 0b00000000 ;T 0°
DB 0b00000111
DB 0b00000010
DB 0b00000000
DB 0b00000010 ;T 90°
DB 0b00000011
DB 0b00000010
DB 0b00000000
DB 0b00000010 ;T 180°
DB 0b00000111
DB 0b00000000
DB 0b00000000
DB 0b00000001 ;T 270°
DB 0b00000011
DB 0b00000001
DB 0b00000000
END
Bottom line: three weeks later, after receiving the package with the clock, I was already able to play Tetris at UC-2000:
In the process of writing Tetris, it became clear that event handlers are always called as long as they are indicated in the registers RB0-RB3 of the second bank (I spoke about them above), regardless of whether the program is running or not. Thanks to this, you can completely redo the functionality of the watch, just by drawing what you need on top of the regular modes. To demonstrate this, I wrote a program that adds 6 additional ones to the default dial, switching between which is a combination of the left button + MODE. At the same time, additional dials organically fit into the work of other watch functions:
One of the most sought-after features of modern smartwatches is custom dials, which were potentially available as early as 83, amazing! It is strange that Seiko did not develop this direction in any way. In general, it’s a little disappointing that the potential of this watch has not been fully revealed. Although, of course, there is nothing strange about this, from 2017 everything looks completely different from the 83rd. Moreover, if you recall how many not very successful attempts to invent smart watches were after them. But this, as they say, is another story.
I published everything described on GitHub'e .