aboutsummaryrefslogtreecommitdiff
path: root/noao/mtlocal/cyber/rdumpf.x
blob: d9371579f9ba2798ca4e64082a1666c42878b459 (plain) (blame)
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
include	<mach.h>
include	"cyber.h"

# READ_DUMPF -- Read data from an array of cyber words, passing the
# requested number of cyber words to the output buffer.  
# The word array contains control words and "Zero length PRU's" as well
# as data.  The control words are read and used to properly
# interpret the PRU that follows.  Each read by GET_CYBER_WORDS begins
# on a control word boundry.  It is expected that read_dumpf returns an
# integral number of PRU's; if not, the data remaining in the PRU is discarded,
# as the buffer pointer must be positioned to the control word preceeding
# a PRU upon entry to read_dumpf.  The number of cyber words read is 
# returned by read_dumpf.  Pointer ip is in units of cyber words; there
# are two array elements per cyber word.

int procedure read_dumpf (rd, out, max_cyb_words)

int	rd, max_cyb_words
int	out[ARB], pru_buf[NINT_CYBER_WRD * LEN_CYBER_READ]
int	nwords, nwords_read, word_count, ip
int	get_cyber_words(), read_dumpf_init(), bitupk()

begin
	if (mod (max_cyb_words, LEN_PRU) != 0)
	    call error (0, "READ_DUMPF: Non-integral PRU requested")

	for (nwords=0; nwords < max_cyb_words; nwords = nwords + word_count) {
	    # If necessary, read more data into the pru buffer.  This
	    # will be necessary when all data in the pru buffer has
	    # been transferred to the output buffer.

	    if (ip >= nwords_read) {
		# Read another chunk of cyber words; reset buffer position
		nwords_read = get_cyber_words (rd, pru_buf, LEN_CYBER_READ)
		ip = 1

	        if (nwords_read == EOF)
		    break
	    }

	    # Get the number of 12-bit bytes in the next pru from control word.
	    # This number stored in lowest 9 bits of the cyber word.
	    word_count = bitupk (pru_buf[(NINT_CYBER_WRD * ip) - 1], 1, 9) /
		NBYTES_WORD
	    ip = ip + 1

	    if (word_count == 0) {
	       # Zero length PRU to be skipped over
	       ip = ip + LEN_PRU
	       next
	    }

	    if (mod (word_count * 60, NBITS_CHAR) != 0)
		call error (0, "READ_DUMPF: Impossible PRU to CHAR Conversion")
	    
	    call amovi (pru_buf[(NINT_CYBER_WRD * ip) - 1], out[(nwords * 
		NINT_CYBER_WRD) + 1], word_count * NINT_CYBER_WRD)
	    ip = ip + LEN_PRU
	}

	if (nwords == 0)
	    return (EOF)
	else
	    return (nwords)

entry	read_dumpf_init ()

	ip = 1
	nwords_read = 0
end

.help read_cyber
.nf ________________________________________________________________________
GET_CYBER_WORDS -- Read binary chars from a file, ignoring short "noise" 
records and extraneous bits inserted to fill out a byte.  The requested
number of cyber words is returned, one cyber word per two array elements.
Data is read from
the file buffer and placed in the output array by UNPACK_CYBER_WORDS.  The
file buffer is refilled as necessary by calling READ; the output array is
supplied by the calling procedure.  Cyber noise records (48 bits) and bits
used to fill out a byte are not transferred to the output array.  
Variables marking the current position and top of the buffer are initialized
by GET_CYBER_WORDS_INIT; buf pos marks the buffer position in cyber words.
The number of cyber words read is returned as the function value; the number
of output array elements filled is twice the number of cyber words read.
.endhelp ___________________________________________________________________

int procedure get_cyber_words (rd, out, max_cyb_words)

int	rd, max_cyb_words
int	out[ARB]
char	cyber_buf[SZ_TAPE_BUFFER]
int	buf_pos, ncyber_words
int	nwords, word_chunk, nchars_read
int	read(), get_cyber_words_init()

begin
	for (nwords = 0; nwords < max_cyb_words; nwords = nwords + word_chunk) {
	    # See if it is necessary to transfer more data from the binary file
	    # to the file buffer.  This will be necessary when all data from the
	    # file buffer has been transferred to the output array.

	    if (buf_pos >= ncyber_words) {
	        # Read the next non-noise record into cyber_buf; reset buf_pos
    	        repeat {
		    nchars_read = read (rd, cyber_buf, SZ_TAPE_BUFFER)
	        } until (nchars_read >= NCHARS_NOISE || nchars_read == EOF)
		buf_pos = 1
		ncyber_words = (nchars_read * NBITS_CHAR) / NBITS_CYBER_WORD

	        if (nchars_read == EOF)
		    break
	    }

	    # The number of cyber words to output is the smaller of the number 
	    # requested or the number of words left in the buffer. 

   	    word_chunk = min (max_cyb_words - nwords, ncyber_words- buf_pos + 1)
	    call unpack_cyber_words (cyber_buf, buf_pos, out, 
		(NINT_CYBER_WRD * nwords) + 1, word_chunk)
	    buf_pos = buf_pos + word_chunk
	}

	if (nwords == 0)
	    return (EOF)
	else
	    return (nwords)

entry	get_cyber_words_init ()

	buf_pos = 1
	ncyber_words = 0
	return (OK)
end



.help unpack_cyber_words
.nf __________________________________________________________________________
UNPACK_CYBER_WORDS -- Convert a raw data array from a 60-bit Cyber computer into
an SPP array containing one Cyber word in each 64-bit increment.
The least significant Cyber bit is bit 1 in each output word and the most
significant bit is bit 60.  [MACHDEP].

When the Cyber outputs an array of 60 bit Cyber words it moves a stream of
bits into output bytes, filling however many bytes as necessary to output a
given number of Cyber words.  The most significant bits are output first,
i.e., bit 60 of the first word is moved to bit 8 of the first output byte,
bit 59 is moved to bit 7 of the first output byte, and so on.  If effect the
Cyber byte flips each 60-bit word.

To deal with Cyber words as an ordered bit stream we must reorder the bytes
and bits so that the least significant bits are first.  This function is
performed by the primitives CYBOOW and CYBOEW (order odd/even Cyber word)
for individual 60-bit Cyber words.  A portable (and less efficient) version
of order_cyber_bits is available which does not use these primitives.
.endhelp _____________________________________________________________________


procedure unpack_cyber_words (raw_cyber, first_cyber_word, int_array,
			      first_output_element, ncyber_words)

char	raw_cyber[ARB]		# raw Cyber array (e.g. from tape)
int	first_cyber_word	# first 60-bit Cyber word to be unpacked
int	int_array[ARB]		# output unpacked array of Cyber words
int	first_output_element	# first output integer to be filled
int	ncyber_words		# number of Cyber words to unpack

bool	odd_word
int	word, inbit, outbit

begin
	odd_word = (mod (first_cyber_word, 2) == 1)
	inbit = (first_cyber_word - 1) * NBITS_CYBER_WORD + 1
	outbit = (first_output_element - 1) * NBITS_INT + 1

	do word = 1, ncyber_words {
	    # Call odd or even primitive to reorder bits and move 60-bit
	    # ordered Cyber word to the output array.

	    if (odd_word) {
		call cyboow (raw_cyber, inbit, int_array, outbit)
		odd_word = false
	    } else {
		call cyboew (raw_cyber, inbit, int_array, outbit)
		odd_word = true
	    }

	    inbit  = inbit  + NBITS_CYBER_WORD
	    outbit = outbit + NINT_CYBER_WRD * NBITS_INT
	}
end


# The portable version of order_cyber_bits follows.
#.help order_cyber_bits
#.nf __________________________________________________________________________
#ORDER_CYBER_BITS -- Convert a raw data array from a 60-bit Cyber computer into
#an SPP bit-array.  The output SPP bit-array is a bit-packed array of 60-bit
#Cyber words, i.e., bits 1-60 are word 1, bits 61-120 are word 2, and so on.
#The least significant Cyber bit is bit 1 in each output word and the most
#significant bit is bit 60.  [MACHDEP].
#
#The byte stream from the Cyber contains bits 53-60 of the first word in the
#first byte, bits 45-52 in the second byte, and so on (most significant bytes
#first).  In essence we swap the order of the 7 8-bit bytes and the 4-bit half
#byte in each 60 bit word.  The bits in each byte are in the correct order.
#
#Each successive pair of Cyber words fits into 15 bytes.  Byte 8 contains the
#last 4 bits of word 1 in the most signficant half of the byte and the first
#4 bits of word 2 in the first half of the byte.  In each 60 bit word we must
#move bit segments (bytes or half bytes) as follows (for the VAX):
#
#Odd words (from N*60 bit-offset):
#      [from]   [to]  [nbits]
#	 1	53	8
#	 9	45	8
#	17	37	8
#	25	29	8
#	33	21	8
#	41	13	8
#	49	 5	8
#	61	 1	4
#
#Even words (from N*60 bit-offset):
#      [from]   [to]  [nbits]
#	-3	57	4
#	 5	49	8
#	13	41	8
#	21	33	8
#	29	25	8
#	37	17	8
#	45	 9	8
#	53	 1	8
#.endhelp _____________________________________________________________________
#
#define	NBITS_PER_WORD	60
#define	NSEGMENTS	8
#
#
#procedure order_cyber_bits (raw_cyber, first_cyber_word, bit_array,
#			    ncyber_words)
#
#char	raw_cyber[ARB]		# raw Cyber array (e.g. from tape)
#int	first_cyber_word	# first 60-bit Cyber word to be unpacked
#char	bit_array[ARB]		# output bit-array
#int	ncyber_words		# number of Cyber words to unpack
#
#int	word, inword, inbit, outbit, temp, i
#int	o_from[NSEGMENTS], o_to[NSEGMENTS], o_nbits[NSEGMENTS]
#int	e_from[NSEGMENTS], e_to[NSEGMENTS], e_nbits[NSEGMENTS]
#int	bitupk()
#
#data	o_from  / 1, 9,17,25,33,41,49,61/		# odd words
#data	o_to    /53,45,37,29,21,13, 5, 1/
#data	o_nbits / 8, 8, 8, 8, 8, 8, 8, 4/
#data	e_from  /-3, 5,13,21,29,37,45,53/		# even words
#data	e_to    /57,49,41,33,25,17, 9, 1/
#data	e_nbits / 4, 8, 8, 8, 8, 8, 8, 8/
#
#begin
#	do word = 1, ncyber_words {
#	    inword = first_cyber_word + word - 1
#	    inbit  = (inword - 1) * NBITS_PER_WORD
#	    outbit = (  word - 1) * NBITS_PER_WORD
#
#	    # Move bits to the output bit array.  Segment list used depends
#	    # on whether the word is an odd or even word.  This code will work
#	    # even if the caller only wishes to order a single word.
#
#	    if (mod (inword,2) == 1) {
#		do i = 1, NSEGMENTS {
#		    temp = bitupk (raw_cyber, inbit + o_from[i], o_nbits[i])
#		    call bitpak (temp, bit_array, outbit + o_to[i], o_nbits[i])
#		}
#	    } else {
#		do i = 1, NSEGMENTS {
#		    temp = bitupk (raw_cyber, inbit + e_from[i], e_nbits[i])
#		    call bitpak (temp, bit_array, outbit + e_to[i], e_nbits[i])
#		}
#	    }
#	}
#end