-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathkenbakuino.txt
309 lines (264 loc) · 13.1 KB
/
kenbakuino.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
Kenbak-uino
an Arduino-based emulation of the "KENBAK-1"
by Mark Wilson
(kiwimew at gmail dot com)
1 Introduction
--------------
Not long after discovering the Arduino it seemed to me it could be a fun
project to re-create an early computer, one with just LEDs and switches.
I looked at things like the Altair 8800 (1975) but it has 30+ LEDs and 20+
switches and seemed like too much work.
Then I stumbled on the KENBAK-1 (1971). Perfect! Only a dozen LEDs and 17
switches. As a bonus it was the 30th anniversary of it's introduction.
I found a reasonable amount of information online, starting at the Wikipedia
article, http://en.wikipedia.org/wiki/Kenbak-1.
This is a software emulation of the KENBAK-1's CPU, and method of operation,
together with a basic recreation of the hardware.
2 Operation
-----------
The basic operation is to enter values with the 8 bit switches on the left.
CLR clears them all. The bits toggle by default. Pressing (ADDR) SET sets
the address register to the displayed value. Pressing STOR writes the
displayed value into the memory at the address, and increments the address.
In this way programs can be entered. The KENBAK as only 256 bytes of memory
and no registers as such (location 0 is A, location 4 is the program counter
etc). DISP displays the current address. READ reads the memory at the
address. STRT starts the program running, STOP halts it.
STOP+RUN single-steps. For more details refer to the online information, for
example the scans of the original manuals.
3 The Build
-----------
I went with an over-all scale in keeping with small LEDs and small buttons. I
dispensed with the power and lock toggle switches. I found a suitable
enclosure in keeping with the over-all scale. I prototyped the circuits for
driving the LEDs with 74HC595's and the switches with 74HC165's. I also
prototyped the "daughter" board that would hold the LEDs and switches at right
angles to the main board. To keep the proportions right, the LEDs and
switches needed to be quite close together so in the end I used two parallel
boards to squeeze the components together and as an aid to keeping everything,
particularly the LEDs, "square". I aimed to keep the design fairly "modular",
the main board and LED/Switch boards are separate and connect via a header
strip. At this early stage I did very little coding, other than the emulation
of the CPU. Once I was convinced I had the hardware right, I wired it all
together (a lot of work, 500+ solder joints), then squeezed it into the
enclosure and tested all the buttons and LEDs, amazingly, everything worked
first time. Then I spend a lot of time on the software, particularly the MCP
which controls the CPU and implements the extensions, like sample programs,
listed below. The samples were very challenging too, it's been a long time
since I worked in assembly language!
An ASCII schematic of the circuit can be found in PINS.H of the sketch.
4 Extensions
------------
I've added a few extensions to the basic KENBAK-1 behaviour.
Extension #1 SysInfo Instruction ---------------------------------------------
The KENBAK-1 instruction set includes 3 NOOP (no-operation) op-codes: 02Q0,
03Q0 and 031R+[Second Byte] (Q=0..7, R=3..7). I've chosen a particular value
of the latter, 0360, to implement an "operating system" SysInfo extension
rather than no-operation. (I use 0300 when a real NOOP is required.) The
execution of any of the NOOPs is handled by the virtual method
virtual bool OnNOOPExtension(byte Op);
on the CPU class. On the base class it does nothing (just returns true to
indicate execution can continue). On the Sketch's derived ExtendedCPU class
it traps the 0360 NOOP and execute the SysInfo function as follows:
The value in the A register sets the operation: if the high bit is set, the
operation is a "write" otherwise it is a "read". The remaining 7 bits provide
the Index of the item. The argument for a write comes from the B register.
The result of a read is placed in the B register.
Note that some writes actually perform an *action* and the corresponding
reads do nothing. Operation 027 (EEPROM Page) read requires a value in B!
Executing the SysInfo instruction resets the CPU speed.
The SysInfo instruction is often referred to as SYSX (system extension op-code)
The first 8 values for the Index read/write the DS1307 RTC registers
(see http://datasheets.maxim-ic.com/en/ds/DS1307.pdf). Numbers are BCD.
000: Seconds (00..59)
001: Minutes (00..59)
002: Hours (00..23) (always 24-hr, no matter how the RTC is configured)
003: Day (01..07)
004: Date (01..31)
005: Month (01..12)
006: Year (00..99)
007: Control
No validation is performed.
The next 8 values read/write bytes to the subsequent 8 bytes of "user" RAM in
the DS1307 (or a different RTC, or EEPROM, see the constants in Clock.h):
010: Flags controlling the Kenbak-uino.
Currently only 1, if b0 is set, pressing one of the Data switches *toggles*
the bit, otherwise it only sets it (as per the KENBAK-1).
011: EEPROM Page Map
See Extension #5 EEPROM. The value of this byte defines how the 1k of EEPROM
is partitioned into 8 pages starting with #0 of 256 bytes. Bits in the Map
indicate if subsequent pages should be half the size, a 1 means halve, a 0
leaves the size as-is. The least significant bit applies to page #1 -- if it
should be half the size of #0 (i.e. 128 bytes).
Thus for example, a Map of 012 creates the following page sizes:
256, 256, 128, 128, 64, 64, 64
000 creates 4 full-size pages (higher pages are ignored): 256, 256, 256, 256
012: User #1
013: User #2
014: User #3
015: User #4
016: User #5
These 5 bytes are available for reading and writing non-volatile values.
The final 7 Index values act as follows:
017: Auto-run (New)
This byte configures auto-running a program at startup (See Extension #9).
It's binary form is 0b00XX0NNN where
XX: 00 = off, 01 = built-in, 10 = EEPROM
NNN: built-in program number or EEPROM slot
020: Control LEDs
Reading does nothing. Writing sets the control LEDs as follows:
b0:INP
b1:ADDR
b2:MEM
b3:RUN
The upper 4 bits control the intensity of the RUN LED, 0000 = max brightness
(PWM=255), 1111 = min (PWM=16).
021: Random
A read returns are random byte, 0..255 in B. Writing a 0 seeds the random
number generator using the time etc. Writing a non-0 value uses that as the
seed.
022: Program delay milliseconds
Reading does nothing. Writing delays execution for the given duration.
This is separate from the "CPU Speed" (Extension #7 below.)
023: Serial
Reads or writes a byte from the Serial port (@38400baud)
024: EEPROM Offset
025: RAM Offset
026: EEPROM Size
028: EEPROM Overlay
030: EEPROM Page
These five commands control copying bytes between program RAM and EEPROM.
You can, for example, use it to overlay code. See memcopy.txt
0177: Reading this special value simply returns 0 in Register A, indicating
that extensions are enabled. Writing does nothing.
The remaining extensions use multiple button-presses to perform special
actions when a program is not running.
Note that STOP+RUN single-steps, as per the KENBAK-1.
Extension #2 Blank -----------------------------------------------------------
Pressing STOP+CLR (i.e. Press STOP and without releasing it press CLR) turns
off all LEDs.
Extension #3 Erase -----------------------------------------------------------
Pressing CLR+STOR sets all memory to 0 *except* 03 (P register) which is set
to 04. The address register is set to 04, ready to enter a program.
The CPU speed (BitN-STOP, Extension #7 below) is set to 0.
Extension #4 Library ---------------------------------------------------------
Pressing STOP+BitN loads one of eight pre-defined programs:
N Description
-- -----------
0: Simple counter
1: Pattern
2: Counting Clock
3: BCD Clock
4: Binary Clock
5: Das Blinken Lights (random pattern)
6: Sieve of Eratosthenes
7: Set RTC
See 5 Programs below.
Extension #5 EEPROM ----------------------------------------------------------
Pressing BitN+STOR writes program memory to EEPROM at "page N". Pressing
BitN+READ reads program memory from EEPROM at page N. The ATmega328 has 1k
of EEPROM, by default this is divided into 8 "pages" of various sizes:
N Size
-- ----
0: 256
1: 256
2: 128
3: 128
4: 64
5: 64
6: 64
7: 64
Program memory is always read from or written to starting at address 000.
Thus Bit7+STOR writes the *first* 64 bytes (addresses 000 through to 077) of
program memory to EEPROM address 960. Bit0+READ reads all 256 bytes of program
space (addresses 000 through to 0377) from EEPROM address 0.
Note that EEPROM memory which has not been written to will be read as 0377
(Unconditional JUMP AND MARK INDIRECT).
The page sizes can be adjusted using SysInfo Index 011 EEPROM Page Map.
Extension #6 SystemInfo ------------------------------------------------------
Pressing STOP+READ executes a SysInfo read. The Index is taken from the
Address register, the result is placed in the Output register (0200).
Pressing STOP+STOR executes a SysInfo write. The Index is taken from the
Address register (there is no need to set b7), the argument is taken from the
Input register (0377).
All SysInfo calls are available programatically and from the front panel but
some make more sense that others (for example Delay from the front panel).
Extension #7 CPU Speed -------------------------------------------------------
Pressing BitN+STOP sets the "CPU speed". It sets the delay in milliseconds
added after each CPU cycle, equal to 2^N ms. Thus b0+STOP sets the
delay to 1ms. b7+STOP sets it to 128ms. The delay is set to 0 at power on
and on CLR+STOR (Extension #3 Erase above) or if a program executes the
SysInfo instruction, 0360.
Extension #8 Send/Receive Memory ---------------------------------------------
Pressing BitN+DISP writes program memory as 16 lines of 16 bytes of octal data
to the serial port.
Pressing BitN+SET read program memory from the serial port. BitN sets the baud.
0/1/2/3=4800/9600/19k2/38k4.
Refer to serial.txt.
Extension #9 Auto-Run Program/Reset Configuration ----------------------------
Holding buttons down while turning the device on configure automatically
running a program at power-on:
Stop and BitN : auto-run built-in program N
Read and BitN : auto-run from EEPROM slot N
Stop : turn auto-run off
In addition, holding
Stop and Clear
will reset configuration to defaults.
Not done ---------------------------------------------------------------------
It would be really useful to move the Input and Flag bytes (0200-0203)
up alongside the Output byte (0377) to provide a larger contiguous block of
memory. See for example the Sieve program which has to work around this.
Deprecations:
I don't do the "dim" display of entry values while running
No need to Start/Stop at power on.
Memory is zero'd at power on.
5 Programs
----------
"Classic programs", these don't use any extensions:
---Count:
Simply increments the OUTPUT register. Will be a blur unless slowed-down
with BitN+STOP.
---Pattern:
Cylon-style single LED moving left-right-left etc. Will be a blur unless
slowed-down with BitN+STOP.
---Sieve:
Builds a table of the odd numbers up to 255 and applies the Sieve of
Eratosthenes to them. Then display the primes, HALTing after each one (hit
START to proceed to the next one).
"Clocks", these use System extensions to try to do something useful with the
Kenbak-uino. Note that they all display the time in 12-hour format with no
AM-PM indicator:
---Count Clock:
Alternates between showing the hours and the minutes. The Control LEDs are
turned off. The hours are displayed thus
P_ HHH HHH
The number of H's is the hour, plus 6 if P is lit. Thus (where '*' denotes
a lit LED & '_' unlit)
-- --* *** is 4 O'Clock
*- --- *** is 9 O'Clock etc
The minutes are displayed thus
B_ MMM MMM
The number of M's is the minutes times 10. If the leftmost lit M is blinking,
it means +5 minutes. B is always blinking. Thus (where '!' denotes a
blinking LED)
!- --* *** is 40 minutes after the hour
!- --- !** is 25 minutes after the hour
This is the easiest clock to actually read the time.
---BCD Clock
Scrolls back and forth between showing the hours and the minutes in BCD. The
minutes display has the leftmost (b7) LED blinking. The Control LEDs are
turned off. Thus
-- --- *-- is 4 O'Clock
-- -*- -*- is 12 O'Clock
!- *-- --* is 21 minutes after the hour
!* -*- *-* is 55 minutes after the hour
---Binary Clock
Shows the time in binary. The minutes are shown on the Data LEDs with the
leftmost (b7) LED blinking. The hours are shown on the Conrol LEDs. Thus
!- -*- *-* * - - * is 9:21
!- **- *** * * - - is 12:55
---Set Clock
This sets the time: the hours (BCD, 24-hour format) are in A, the minutes
(BCD) are in B.
--Das Blinken Lights
Just blinks all the LEDs, old-school.