summaryrefslogtreecommitdiff
path: root/tool
diff options
context:
space:
mode:
authorJulian Blake Kongslie2021-04-18 16:00:54 -0700
committerJulian Blake Kongslie2021-04-18 16:12:38 -0700
commit5742e1f66c4e70151865de7092547223898bbf6b (patch)
tree5c4208eb0a32c985e1aa22e230b20fc780234152 /tool
parentMove the core logic out of the top module. (diff)
downloadnoncpu-5742e1f66c4e70151865de7092547223898bbf6b.tar.xz
Support a proper PDP-8 assembler.
Diffstat (limited to 'tool')
-rw-r--r--tool/p8bin2hex.c170
-rwxr-xr-xtool/pll.rb23
2 files changed, 193 insertions, 0 deletions
diff --git a/tool/p8bin2hex.c b/tool/p8bin2hex.c
new file mode 100644
index 0000000..8d28d19
--- /dev/null
+++ b/tool/p8bin2hex.c
@@ -0,0 +1,170 @@
1/*
2 * PDP-8 format converter.
3 *
4 * Usage: p8bin2hex tape.bin > tape.hex
5 *
6 * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM"
7 * formats.
8 *
9 * RIM format:
10 * 10.000.000 leader/trailer (at least an inch of these)
11 * 01.aaa.aaa address hi (bits 5:0 contain address 11:6)
12 * 00.aaa.aaa address lo (bits 5:0 contain address 5:0)
13 * 00.xxx.xxx data hi (bits 5:0 contain data 11:6)
14 * 00.xxx.xxx data lo (bits 5:0 contain data 5:0)
15 * <repeat any number of [address, data] pairs>
16 *
17 * BIN format:
18 * 10.000.000 leader/trailer (at least an inch of these)
19 * 11.011.000 "field" (bits 6:4 specify address 14:12)
20 * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6
21 * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0
22 * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6
23 * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0
24 * <repeat any number of [origin, data+] sequences>
25 * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but
26 * 00.xxx.xxx chucksum lo - excluding field and leader/trailer
27 *
28 * Some tapes may contain assembler error messages. These are are text
29 * delimited by 0377 bytes. The BIN loader ignores bytes from starting
30 * at any 0377 byte, until another 0377 byte is seen.
31 */
32
33#include <inttypes.h>
34#include <stdio.h>
35#include <stdlib.h>
36
37uint16_t mem[32768];
38
39int
40load(FILE *fp)
41{
42 enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start;
43 int c = 0, n, v = 0;
44 uint16_t a = 0, d = 0, t = 0, u = 0;
45 for (n = 0; (c = getc(fp)) != EOF; ++n) {
46 switch (s) {
47 case Addr:
48 u += c;
49 a |= c;
50 fprintf(stderr, " %04o: address %06o\n", c, a & 077777);
51 s = Fetch;
52 break;
53 case Data:
54 u += c;
55 d |= 0x8000 | c;
56 /* fprintf(stderr, " %04o: data %05o\n", c, d & 07777); */
57 fprintf(stderr, " %04o", c);
58 s = Fetch;
59 break;
60 case Fetch:
61 fetch:
62 if (c == 0200) {
63 if ((d & 0x8000) != 0) {
64 if ((d & 07777) != (t & 07777))
65 fprintf(stderr, "\nbad checksum %05o\n", t & 07777);
66 else
67 v = 1, fprintf(stderr, "\nvalid checksum %05o\n", t & 07777);
68 }
69 fprintf(stderr, " %04o", c);
70 goto leadout;
71 }
72 t += u;
73 u = 0;
74 if (d & 0x8000) {
75 fprintf(stderr, ": mem[%06o]=%05o\n", a & 077777, d & 07777);
76 mem[a] = d & 07777;
77 a = (a & ~07777) | ((a + 1) & 07777);
78 d = 0;
79 }
80 fprintf(stderr, " %04o", c);
81 if ((c & 0300) == 0000) {
82 u = c;
83 d = (c & 077) << 6;
84 s = Data;
85 break;
86 }
87 if ((c & 0300) == 0100) {
88 u = c;
89 a = (a & ~07777) | (c & 077) << 6;
90 s = Addr;
91 break;
92 }
93 if ((c & 0307) == 0300) {
94 a = ((c & 0070) << 9) | (a & 07777);
95 fprintf(stderr, ": field %o address %06o\n", (c & 070) >> 3, a & 077777);
96 break;
97 }
98 if (c == 0377) {
99 fprintf(stderr, ": skipping: ");
100 s = Skip;
101 break;
102 }
103 fprintf(stderr, ": unknown byte at %d\n", n);
104 break;
105 case Leader:
106 leader:
107 if (c != 0200) {
108 fprintf(stderr, ": end leader\n");
109 s= Fetch;
110 goto fetch;
111 }
112 fprintf(stderr, " %04o", c);
113 break;
114 case Skip:
115 if (c == 0377) {
116 s = Fetch;
117 putchar('\n');
118 } else {
119 putchar(c);
120 }
121 break;
122 case Start:
123 if (c == 0200) {
124 s = Leader;
125 goto leader;
126 }
127 fprintf(stderr, " %04o", c);
128 break;
129 }
130 }
131 leadout:
132 while ((c = getc(fp)) != EOF)
133 fprintf(stderr, " %04o", c);
134 putchar('\n');
135 return v;
136}
137
138void
139dump()
140{
141 printf("// Generated by p8bin2hex");
142 unsigned int nextaddr = -1;
143 for (uint_fast32_t a = 0; a < 32768; ++a) {
144 if (mem[a] == 0) continue;
145 if (nextaddr != a)
146 printf("\n@%x", (unsigned int)a);
147 nextaddr = a + 1;
148 printf(" %03x", mem[a]);
149 }
150 printf("\n");
151}
152
153int
154main(int argc, char *argv[])
155{
156 if (argc != 2) {
157 fprintf(stderr, "usage: p8 filename.bin\n");
158 exit(EXIT_FAILURE);
159 }
160 FILE *fp = fopen(argv[1], "rb");
161 if (!fp) {
162 perror(argv[1]);
163 exit(EXIT_FAILURE);
164 }
165 if (!load(fp))
166 exit(EXIT_FAILURE);
167 fclose(fp);
168 dump();
169 exit(EXIT_SUCCESS);
170}
diff --git a/tool/pll.rb b/tool/pll.rb
new file mode 100755
index 0000000..49464d4
--- /dev/null
+++ b/tool/pll.rb
@@ -0,0 +1,23 @@
1#!/usr/bin/ruby -w
2
3TARGET_FREQ = ARGV.shift.to_f
4NATIVE_FREQ = 50.0
5
6CLOCK_WIDTH = 5
7
8best = nil
9best_mult = nil
10best_div = nil
111.upto(2**CLOCK_WIDTH) do | mult |
12 1.upto(2**CLOCK_WIDTH) do | div |
13 new = NATIVE_FREQ * mult / div
14 if not best or (new - TARGET_FREQ).abs < (best - TARGET_FREQ).abs or ((new - TARGET_FREQ).abs == (best - TARGET_FREQ).abs and (mult + div) < (best_mult + best_div))
15 best = new
16 best_mult = mult
17 best_div = div
18 end
19 end
20end
21
22error = (best - TARGET_FREQ).abs / TARGET_FREQ
23$stdout.write("Closest I can get is #{best}: *#{best_mult} /#{best_div} (#{(error * 100).round}% error)\n")