aboutsummaryrefslogtreecommitdiff
path: root/noao/mtlocal/cyber/rpft.x
blob: f21ec44cedca6338eb318a82ac5d304a5b19da27 (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
include	<mach.h>
include "cyber.h"

.help read_cyber
.nf ________________________________________________________________________
READ_CYBER -- Read binary chars from a file, ignoring short "noise" records.
Data is read in chunks from the file buffer into the output buffer.  The
file buffer is refilled as necessary by calling READ; the output buffer is
supplied by the calling procedure.  Cyber noise records (48 bits)
are not transferred to the output buffer and so are ignored.  READ_CYBER_INIT
must be called to initialize variables for CYBER_READ.  Variables marking the
current position and top of the buffer are initialized.
.endhelp ___________________________________________________________________

int procedure read_cyber (rd, out_buffer, maxch)

int	buf_pos, buf_top
int	rd, maxch
char	out_buffer[ARB]
char	block_buf[SZ_TAPE_BUFFER]
int	nchars, chunk_size, nchars_read
int	read(), read_cyber_init()

begin
	for (nchars = 0; nchars < maxch; nchars = nchars + chunk_size) {
	    # 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 moved to the output buffer.

	    if (buf_pos >= buf_top) {
	        # Read the next non-noise record into block_buf; reset buf_pos
    	        repeat {
		    nchars_read = read (rd, block_buf, SZ_TAPE_BUFFER)
	        } until (nchars_read > NCHARS_NOISE || nchars_read == EOF)
		buf_pos = 1
		buf_top = nchars_read
	    }

	    # The number of chars to output is the smaller of the number of
	    # characters requested or the number of characters left in the 
	    # buffer

	    if (nchars_read == EOF)
		break
	    else
	        chunk_size = min (maxch - nchars, buf_top - buf_pos + 1)
    
	    # Move data to output array, increment buffer offset
	    call amovc (block_buf[buf_pos], out_buffer[nchars+1], chunk_size)
	    buf_pos = buf_pos + chunk_size
	}

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

entry	read_cyber_init ()

	buf_pos = 1
	buf_top = 0
	return (OK)
end


.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].

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 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

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 = 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, bit_array, outbit)
		odd_word = false
	    } else {
		call cyboew (raw_cyber, inbit, bit_array, outbit)
		odd_word = true
	    }

	    inbit  = inbit  + NBITS_CYBER_WORD
	    outbit = outbit + NBITS_CYBER_WORD
	}
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