04
Mon, Nov
6 New Articles

5250 Data Stream Programming

General
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Getting complete control over your 5250 display

by Craig Pelkie

Suppose you are in your kitchen, cooking dinner. You decide it would be nice to have some canned string beans, so you get a can, run it under the electric can opener, and continue cooking, without giving a second thought to opening the can. Now, suppose you are floating in a life raft in the middle of the ocean. You are by yourself, and have been floating for several days. All you have with you are several cans of water, the kind without flip tops. You have no tools whatsoever to open them with. All you really have is your teeth. After days of trying, you finally bite through the lid of one of the cans...

That pretty well sums up what 5250 data stream programming is like. In the first case, in your kitchen, you have plenty of tools available, and opening the can is but a small part of the overall scheme of things. In the second case, you have no alternatives -- you can get what you want, eventually, but you've got to expect to be bloodied in the process.

What's He Talking About?

Just what is 5250 data stream programming, anyway? And why would you ever consider using it? The short answer is, 5250 data stream programming is a technique that you can use to gain near-total control of a 5250-type display. You can control everything about the appearance of the display, within the limits of the 5250 device. And that is why you'd consider using the technique, since the limits of what you can do are actually quite a bit beyond what the standard ways of controlling the device allow. To be quite specific, one of the primary uses of programming at the low level of data stream programming is to create "pop up" type displays. You've probably seen many examples of this in PC programs, and there are even some companies that now offer products that allow midrange programmers to incorporate "pop up" type displays into their programs. (In fact, after you see what's involved, you may decide that it's easier to license one of those products.)

By now, you probably realize that it is possible to program rudimentary "windows" on the S/36, S/38 and AS/400 by using standard S&D or DDS specs. For example, refer to the July 1989 DataNewtork (now Midrange Computing) article, "Pop-up menus on the AS/400", and the January 1989 DataNetwork article, "Windowing in RPG." In many cases, those techniques provide you with the effect that you want, and are within the realm of high level programming. The drawback of those techniques, though, is that the "window" is hard-coded in the display file; it will always be the same size and appear in the same position. If you want to use a window in another position, you have to define that within the display file, which may or may not be palatable.

This series of articles will teach you how to control the size and location of a window within a program. By sending a series of carefully encoded bytes to a 5250 display, you can exactly specify where a window should appear and how it should appear. Even if you have no interest in using the technique, you may wish to follow the series, since you will learn some of the factors involved in the formatting of a display.

First Things First

If you think that you'll want to program 5250 data streams, you should stop right now, call IBM, and order the 5250 Functions Reference Manual (SA21-9247). This is one of the better manuals I have dealt with; the first section gives an example of "how to do it," and the second section is an encyclopedia of 5250 functions, many of which are irrelevant to our discussion, but nonetheless, carefully explained and cross referenced. For example, there is a great deal of information about the ill-fated 5292 graphics display, which had the misfortune to appear when PCs with graphics capabilities were becoming common, to say nothing of the excessive price. On the other hand, I think the encyclopedia format is commendable, and often wish that other manuals would follow the example of this one.

When you review this manual, you will quickly realize that it says absolutely nothing about the S/36 or AS/400, or RPG, for that matter. This is because the 5250 data stream is treated as a "protocol," or description of how something is done. Dealing with a "protocol" on a specific machine, in a specific language, is an "implementation," which is what we'll be examining in these articles. Sadly, IBM does not seem willing to help us explore issues of implementation; queries to them about specific implementation features have been met with stony silence. Nevertheless, we'll push onward as best we can with the information available, and create some rather dramatic results.

You should also be aware that many of the techniques are already described in other articles. For example, the DataNetwork February 1985 issue contains a "CRT Plotter" program using 5250 commands. News/3X-400, in their December 1987 issue, contains an article describing a technique that can display and read input from a "pop-up" window. Other magazines have occasionally had similar articles, so I am not claiming any originality or invention in these articles. However, unlike earlier articles, we will take time to explore why things are done a certain way, rather than just tell you to do something. For most RPG programmers, learning to program the 5250 data stream will be like learning to program a computer in a foreign language, and I think an understanding of the "whys" will ease the burden somewhat.

1's and 0's

Most RPG programmers have never used the bit-manipulation op-codes, mainly because there are few reasons to do so. So we have formed vague notions of computers as machines that somehow deal with a boring diet of 1's and 0's, and left it at that. The more adventurous may have used bit-level operations to set and control "attribute bytes," that is, bytes that control highlighting, underlining, color and other display attributes. Believe me, when you get done with these articles, you will know how to do that, plus quite a bit more.

The plain fact is that you must become familiar with the BITON and BITOF opcodes, and should work with TESTB as well. In these articles, we'll be using "hexadecimal" notation for bit-value fields, which is higher level than straight binary. However, unlike your first computer science courses, you don't have to learn how to do hex or binary arithmetic; everything we'll be doing is straight conversions. Besides, I have provided you with subroutines that you can include in your programs to convert to and from binary representation. If you are unclear about binary and hexadecimal notation, stop and review the sidebar, Binary and Hex Coding, at this point, and dig up your RPG manuals and review the BITON, BITOF and TESTB operations.

Now, why do you need to know these things? The answer is, when you are programming a 5250 data stream, you compose data stream commands with binary values. For example, to specify a screen location, you express it in terms of X-Y coordinates, with X and Y being binary values. If you stop and think about it, this makes pretty good sense, since a single byte can represent up to 256 values. Binary encoding is also used to represent 5250 commands, although only a handful of commands are used, far less than 256.

Becoming familiar with binary values is one of the major stumbling blocks that RPG programmers have to overcome. You should take as much time as you need to become conversant with binary/hex notation, since it is required for 5250 techniques and is used for many other purposes (particularly when programming PCs).

A Strange Way of Doing Things

Most midrange programmers think of S&D or DDS specs as "the way" to define screens. That is understandable, since the IBM references clearly steer you in that direction. In fact, the only clue that S/36 programmers have to the lower levels is in the Functions Reference Manual (SA21-9436), which most shops have never heard of. Unless your shop is programming S/36 Assembler, you'll probably have no use for this manual, but you may wish to get it just as a matter of interest. S/38 and AS/400 programmers are given enough to whet their appetites, in that the DDS Reference (SC21-9620) documents the "USRDFN" (User Defined) keyword, gratuitously pointing out that "you should have in- depth knowledge of the device before using this keyword," but not breathing a word beyond that. The Data Management Guide (SC21-9658) has four pages concerning data stream programming, which quite carefully dance around the specifics. The most recent version of this manual mentions that "windows can be done using standard DDS or with user-defined data streams," and goes on to mention that examples using standard DDS are in the QUSRTOOL library. Apparently, IBM considers 5250 data stream programming to be strong medicine, and like all medicine-men, they are not about to reveal their secrets.

5250 data stream programming is strange because you format the display within your program. Everything within our experience has led us to believe that the only way to interact with a display is by S&D or DDS specs. But if you think it through, you'll realize that the standard technique is simply a convenience so that we don't have to program at a low-level. In the case of S&D and DDS, we are telling the machine that we're quite willing to put up with the impositions and rules of the specs, so long as they usually provide us with what we want. Indeed, had it not been for PCs, we may have been content to stick with "standard" techniques. At this point, it is an indictment against IBM that more advanced interface techniques are available with the "protocol," but are withheld from us with the "implementation." Let's take back some of the ground they've taken from us.

We'll Go Easy

Oddly, programming some 5250 data stream examples are not overly complicated; they are simply unfamiliar. A key point to remember is that everything about a display is done within your program, not with S&D or DDS specs. The example you will learn in this series will be a text window that you can display and resize at will; that simply cannot be done with "standard" specs. To build and manipulate a text window, we'll start with simply displaying some text on a display. Once we can successfully do that, we can go forward with the technique and create more advanced displays.

At the outset, you must understand that 5250 data stream programming is exacting and merciless (remember how it felt to open the can with your teeth?). That is, because you are more directly controlling your machine, you have to be in complete control of the commands that you give it. Anything less than complete control results in I/O errors that usually can't be corrected short of fixing and recompiling the program. On the other hand, you're not writing Assembler or MI programs, so (as far as I know) it's not like you're going to crash the system. You might be more comfortable if you start with these techniques "after hours." You also might have to explain to your boss that what you're doing won't harm anything, which may or may not fly. Remember, all you're doing is specifying commands to your terminal. Even though it's "lower level" than RPG, it's nowhere near Assembler or MI's potential for damage. Also, for some reason, when you do get 5250 data stream techniques to work, you will feel an almost childish sort of satisfaction. I have to admit, it is a lot of fun to get this stuff working.

From These Humble Beginnings...

There are two program examples provided, one for the S/36 (1), the other for the S/38 and AS/400 (3). Surprisingly, the S/36 program is easier to implement than the AS/400 version. S/38 and AS/400 programmers will have to refer to the sidebar, Special Requirements For AS/400 and S/38, to learn how to create and run the example. By the way, I doubt that the S/36 version will work in the AS/400 S/36 environment, but you're welcome to try. If it doesn't work, use the native version.

There are two program examples provided, one for the S/36 (Figure 1), the other for the S/38 and AS/400 (Figure 3). Surprisingly, the S/36 program is easier to implement than the AS/400 version. S/38 and AS/400 programmers will have to refer to the sidebar, Special Requirements For AS/400 and S/38, to learn how to create and run the example. By the way, I doubt that the S/36 version will work in the AS/400 S/36 environment, but you're welcome to try. If it doesn't work, use the native version.

Both examples accomplish the same thing. They start by displaying five lines of text at the top of the display; when you press ENTER, a reverse image piece of text is displayed on line 4. So what and big deal! Well, whether or not you realize it, the example shows you everything that you'll need to know and do to create dynamic text windows. After all, a window can be as small as one line, as in this example. Bigger windows are just an extension of the technique shown here.

At this point, we're going to go through the programs in detail. We'll start with what's common to both versions, take a slight detour to explain the S/38 and AS/400 specifics, then finish up.

Start With The Display Files

Look at the display file that applies to your machine (Figures 2 and 4). For S/36 programs, the record format of interest is "WTDFM". This is shown as starting on line 1, clearing no lines. A single field, WTD, is defined as 30 characters long, output only, on line 1, position 2. The line and position for this field is really irrelevant, since we will be specifying positioning within the program. The entries are made in the S&D spec so that the format will be created. (Remember, at this point, the machine doesn't know that we're going to take charge of the display. We really just want to tell it to reserve some space for us to put our Write to Display command.)

The S/36 "TEXT" record is of no consequence. It simply contains text lines so that you'll have something to look at when you try the programs. This record can have input/output fields, or whatever you want. If you want, you can substitute in one of your record formats for the test.

For the AS/400 version, the trick is in the "FMWTD" record. This record uses the "USRDFN" (User Defined) record-level keyword; this tells the operating system that our program is going to control things when this format is used. The somewhat shocking thing about this format is that you can't define any fields for it, and you must be certain that any file-level keywords, notably indicators and command keys, do not "propagate" into this format. As the example shows, you can use this type of format in a file with other "normal" formats.

Write to Display

Turning our attention back to the program, the first thing of interest is the data structure used to compose our WTD (Write to Display) command. "Write to Display" is the name of a 5250 data stream command, which is used to write a specific string of formatting characters and text to a display.

All 5250 data stream commands start with an ESCAPE byte, value x'04'. When you format a data stream and do an output operation to a display, the ESCAPE is used to signal that whatever follows is going to be various commands. So the first byte of our WTD string is going to be x'04', represented here as the variable "ESC".

The second byte of our command string is the "Write to Display" command, x'11'. According to the book, this command "...writes characters and attributes into the display regeneration buffer and creates, adds to, and modifies the format table that is associated with the display." Huh? It turns out this is exactly what we want to do: we want to write a string of characters and display attributes, in our case (of a window) adding to and modifying the current format table (which is essentially the current display).

The Write to Display command must be followed by two "control characters." The first control character is used to specify such things as locking the keyboard, clearing and resetting MDT (modified data tag) flags, and filling fields with nulls. Since we won't be using any of those features for our example, we set the first character to x'00'. The second control character is used to set the cursor to blink or stay steady, unlock the keyboard, sound the alarm, and set the Message Waiting indicator on or off. Again, we'll set this byte to x'00' for now. You may want to investigate using these features, in which case you should have the 5250 Functions Reference, and set bits in the control characters according to your needs.

Following the two control characters, you code one or more "Orders," which is where it starts to get interesting. The only order we'll be using is Set Buffer Address, x'11' (note that this uses the same hex code as the Write to Display command; the machine knows the difference from the context.) Other interesting orders are Insert Cursor (x'03', which in our terms is "position cursor"), Repeat to Address (x'02', to repeat a series of bytes), and the most interesting and most complicated, Start of Field (x'1D'), which lets you define input/output fields within the data stream.

For now, we'll devote our attention to the Set Buffer Address command. For an output operation, this command is "used to set the current display address and thereby determine where the data display...begins" (from 5250 Functions Reference). The address is set by the two immediately following bytes, Row and Column. You can see this in the WTD data structure. The Row and Column bytes must be encoded as binary values. For example, to specify a location of row 20, column 40, you would use a row value of x'14' and column value of x'28'. That is why I told you to become familiar with hex and binary coding, and gave you subroutines to convert to and from binary. Now stop and think about this for a while. You've just learned that there is an order, SBA, that is used to tell the display where you want to put stuff. Right after the SBA order, you give it the row and column values that you choose. There is nothing to say that those values have to be "hard coded." So if you want to, you can create a loop that generates a WTD command string, and increment the row or column values, or both, each time through the loop. Do you start to see how you can dynamically position something on the display? All you have to do is tell it, using the SBA order. But we're getting a bit ahead here, so let's pull back and continue with this example.

Before going any further, you should note that invalid settings of the row or column value will cause unrecoverable errors. If you're on a S/38 or AS/400, you're lucky when you get an error, because you can get a formatted dump and track down the illegal value. S/36 programmers have to laboriously examine their code and be certain that the binary values are correct.

Immediately following the "column" setting is where things get turned over to you. In our example of writing text at will to the display, the first byte needed after column is an "attribute" byte. The 5250 Functions Reference has an excellent table showing all valid attribute bytes, for both mono and color displays. Attribute bytes have values from x'20' through x'3F', and control such things as reverse image, high intensity, underscore, blinking and color selections. I know there are other references to the attribute bytes, but I've forgotten where they are since I've been using this manual for so long. Even if you don't plan to do this heavy-duty WTD stuff, it's worth getting the manual for when you want to use the tamer technique of inserting your own display attributes in "normal" displays.

In any event, we have to pick a display attribute to start our text with. In the WTD data structure, this is the ATTRST byte, which we set in the program to reverse image, x'21'. Note that the attribute byte is considered as taking up one of the "display" positions. That is why you have to leave at least one space between fields when you design a display. You can see the attribute bytes on a terminal that has the "Test" or "Extended Display" feature; I recommend that you use this feature when programming your own data streams. You won't see the data stream commands and orders, but you will see where your output data begins and ends. Also, note that an attribute byte precedes a string, and is in fact part of the string. The implication of this is that you can't mix attributes within a string. For example, you can't underline or reverse image a character within a character string, unless you're willing to have the character string "broken" at the point of the new attribute. This is an annoying characteristic of 5250 class displays, since there are occasions where you'd like to create an effect with attributes but can't. If you compare a 5250 display with a PC display, you'll quickly see that the PC display allows specification of attributes for any position on the display. This is because the PC display has a "two dimensional" characteristic, in which every display position has its own attribute byte. Unfortunately, it is improbable that IBM will alter the 5250 protocol at this point to implement such a technique, so no matter how beautiful our screens might become, they'll always be less refined than PC displays.

Right after the attribute byte, you can put anything you want. You can put characters, numbers, or spaces for that matter. You can put anything within the range x'40' through x'FE', or another attribute byte. In our example program, we simply put a little bit of text that was originally in an array. You can get your text from an array, or construct it within the program, or get it from a message or data file. (Hint, hint, do you start to see some of the possibilities?) In any event, the WTD command could care less about the text, it just wants us to adhere to the rules so that it can display it for us.

You'll want to end a text display with an ending attribute, shown in our example as fields "ATTREN." This should be the "normal" display attribute, x'20'. By putting an ending attribute, you ensure that the starting attribute, or any attributes within your string, do not "run on" until the next starting attribute. You should try running the example program with and without the ending attribute to see what I mean.

That's it, as far as building a WTD command string for our simple example.

Setting It Up

Now that we know what we need, we can proceed to program it (first what, then how). The bulk of the executable statements are just bit setting and MOVE instructions, getting things initialized. You should follow through each of the bit operations by hand, and be certain that you understand what is going on. Don't be confused by the BITONs, for example, creating hex value x'04' by saying BITON '5'. Remember that the BITON/BITOF instructions use their own bit numbering system. I invariably draw a picture of a byte and number each of the bits, similar to what is in the chart, and you might want to do that also. The consequences of blowing a bit setting are severe, and also somewhat difficult to track down, so check and double check each setting. Also, I strongly recommend that you put hex fields initially in a "look alike" field, that is, create a value of x'04' in field X04, rather than putting x'04' directly into the field "ESC". This lets you use the same bit field wherever you need, without assigning any significance other than the bit settings. By naming it after its setting, you can easily refer to it in the program. Just be certain that the value is actually correct, that is, don't put a value of x'05' in field X04.

The example program shows the value of coding the "X" type fields; in the short example shown, we use X11 and X00 twice. When you start working with longer WTD commands, you will use the same values many times.

AS/400 and S/38 Note

At this point, the AS/400 and S/38 people have to set three other fields. These fields are the Send Length, Receive Length, and Requested Function. I don't really know why we have to do this, but this is documented in the Data Management Guide under "User-Defined Data Stream Considerations," and there's no way around it. On the other hand, when things blow up, we get better error messages than the S/36, so setting five bytes seems like a pretty good trade-off.

In our example, we are sending a string of length 30, the WTD data structure. Note that the send length includes the initial ESCAPE byte, the WTD command and its control characters, the SBA order and its parameters, and our display attributes and data. If you compose a longer WTD string, you simply set the length equal to the length of the entire string. This is a two byte field and must be set in hex values. In our example, we simply clear the field to x'0000' and move x'1E' (decimal value 30) to the rightmost byte of the field, ending up with x'001E'.

The Receive Length is also a two byte field. In our example, we're not going to receive anything, so we set the whole thing to x'0000'.

The Requested Function is a single byte. Again, I don't know why this has to be set, since the WTD string actually gives the order to send stuff, but we'll just do it. To tell OS/400 or CPF that we want to send (no receive), we encode this byte as x'71'.

These five bytes immediately precede any 5250 data stream command that we issue. Be certain to review the sidebar to understand how to get all of this in order.

Show Off

After the WTD data structure is completely formatted, we simply display it. First we display the TEXT format, just to put stuff on the screen so we can write over it. We then output our WTD format. This writes out the WTD data structure. In the S/36, we can just output the data structure to a field in a record; when the ESCAPE character is seen, the machine realizes that whatever follows is not normal S&D output, so it steps back and lets us take the stage. The AS/400 and S/38 WTD format has already been created with the USRDFN attribute, so the machine has some idea about what to expect... even so, we still have to code the ESCAPE character and everything else, in addition to the preliminary five control bytes.

The S/36 version is simpler, in that the program waits for us to press ENTER after displaying our WTD format. A simple loop refreshes the initial text display, after which you can press ENTER to see the effect again. The AS/400 and S/38 version is a bit more complicated, since the program doesn't wait after we write our WTD format. It does no good to code this as an EXFMT, either, it turns out that the "control" is actually within the data stream. Since we haven't included any input orders within our WTD string, the machine sees no reason to wait, so it goes right back to the top of the loop. To give you a chance to admire the effect, we include the second EXFMT in the AS/400 example, which puts out a message at the bottom of the display.

Try It!

If you are interested in using these techniques, you should create the display file and program required for your machine, and try them. If you don't have the 5250 Functions Reference, you'll be limited in what you can try, but you can do things like set different row and column positions, vary the display attributes, and make the text longer or shorter.

The next article will conclude this brief series, in which we'll take this program as a basis for displaying a "window" of text. What this amounts to is appending additional SBA orders after the first one, for as many orders as we care to make. In preparation for the next article, you should become very familiar with array operations. This is because we will programmatically vary the position and size of the window, and the simplest way to do that is to use a long array of single characters.

Binary and Hex Coding

Most programmers know that computers somehow work with the binary number system, where everything is represented by combinations of 1's and 0's. If you understand binary and hex representation, and are quite familiar with the RPG BITON, BITOF and TESTB opcodes, you can skip this section. Everybody else should work through this until it becomes as familiar as Z-ADD or MOVE.

We practically never have to deal with bit-level data and commands; after all, it is the compiler's job to translate for us. In some cases, such as 5250 data stream programming, you have to encode commands at the bit level. RPG and other high level languages have opcodes that let you work with bit-level data. But to use those commands, you have to know what your intended result is.

 
1 = 256 

You've probably heard that a single byte can represent up to 256 different values, but you might have only a vague idea of how that works. To see this, look in your RPG manual and find the index entry for "collating sequence." If you have an S/36 or S/38 RPG manual, you should use those, since they have a much better chart of the collating sequence than the AS/400 RPG manual. (It appears that the chart itself can be ordered from IBM, form GX21-9096, "Translation Table and Alternate Collating Sequence Coding Sheet".) In any event, the charts show you that, of the 256 possible bit configurations, letters, numbers and symbols take up just over a third of the possibilities. The S/36 and S/38 charts show the actual bit configuration, the value, if any, and the hexadecimal representation.

The part that may be confusing is the equating of binary values (the 1's and 0's) with the hexadecimal value. The hexadecimal value is used as a short-hand representation of the binary values; that is, you can represent the same value in only two characters instead of a string of eight 1's and 0's. It turns out that one hex character can represent up to four binary characters, so using two hex equals eight binaries. The Binary/Hex Chart shows the equivalence of hex characters and binary combinations.

A binary value can be thought of as either "data" or as a numeric value. For example, you use the value as data when you are encoding a display attribute, such as high intensity, reverse image. You use the value as a numeric value when you need to specify location or lengths, such as in the 5250 data stream when you specify a starting row and column.

The numeric value of a binary value can be calculated with simple addition. Starting with the rightmost position, your numeric value is 1 if this position is 1, and 0 if the position is zero. Moving left one position, you add 2 to the numeric value if the position is 1. Each time you move left, you double the additive value and add it to your number if the position is 1 (or "on"). The furthest left position has a value of 128; from left to right the values are 128, 64, 32, 16, 8, 4, 2, 1. If you add all of those together, the numeric value is 255. There are 256 combinations because 0 (all binary positions set to 0, or "off") is a valid configuration.

Each binary position is assigned a number so that we can refer to it in opcodes; also, a specific position is referred to as a "bit". A bit is said to be "on" or "off", depending upon the value of the bit. A bit value of 1 is on, value 0 is off. The leftmost bit position is bit 0, the rightmost is bit 7. This is in terms of RPG, so if you have programmed in other languages or on other machines, you may have to be careful with this, since other implementations might number bits differently.

Setting Bit Values

When you need to set a bit value, you use the RPG opcodes BITON and BITOF. The first step in setting a value is to determine the exact on/off settings that you need. Let's work through a few examples to see how this is done.

In 5250 data stream programming, you have to set the display attributes that you want to use. In the following example we'll create the settings for Reverse Image and Normal. Reverse Image is hex '21', Normal is hex '20'. Many programmers use the convention of specifying those values as x'21' and x'20'; within an RPG program, we'll assign those bit values to fields X21 and X20.

 
BITOF'01234567'     X00       1 
MOVELX00            X20       1 
MOVELX00            X21       1 
BITON'2'            X20 
BITON'27'           X21 

The first thing you have to do when setting a bit field is to "clear" the field. Recall that RPG initializes character fields to blank. Blank is not the same as clearing the field, since blank actually has a bit value of x'40'. (Remember all those times you've seen numeric values of 404040? Those were numeric values initialized to blanks!) To clear a bit field, you set all of the bits off, with the BITOF operation. I prefer to set the value X00, then move that value to the other bit fields that I need, as in the code example shown. After you've initialized the bit fields, you can set on the bits that you need to create the bit configuration. For example, to create the bit configuration for Reverse Image, x'21', you can look at the Bit Values and Positions Chart. The left hex value of 2 equates to bit settings of 0010, the right hex value of 1 equates to bit settings of 0001. This makes sense if you deal with each value by itself. For example, the value 2 is represented by 0010, which is (from right to left), the sum of 0*1, 1*2, 0*4 and 0*8. Each grouping of four bits can represent up to 16 unique values, represented as 0 through F, as shown in the Binary/Hex chart at the end of this sidebar. This is the basis for "packed" numbers, which is a technique of using one byte to represent two numbers: the first four bits represent the first number, the last four represent the second number.

Now that you know the bit settings for each value of x'21', you simply join the values together, so that 0010 and 0001 become a bit string of 00100001. Applying the RPG rule for bit numbering, you find that bits 2 and 7 have to be set on (start at the leftmost position, that is bit 0. The rightmost bit is bit 7.) Now that you have the values that have to be set on, it is a simple matter to use the BITON opcode, as shown in the code example.

Using Bit Values

In these articles, there are two types of bit values that we'll be using, those that are known in advance, and those that aren't. For example, before long you'll learn that the bit value for the Escape character is x'04', the Write to Display command is x'11', and so on. I have found it simplest to initialize all of the known bit values in a "first time" routine in the program. Unknown values come into play when you want to dynamically alter the location of information on the display, which is done by setting new row and column values. Because you don't know in advance what the values will be, you'll need some way to create bit values as needed. The subroutines shown in Figures 6 and 7 will convert to or from binary values. For example, if you need to convert the decimal column number 25 to binary, follow this example:

 
Z-ADD25       W03N0 
EXSR          #CVTTB 
MOVELW01      $COL 

S/38 and AS/400 programmers can take advantage of a short-cut conversion method using data structures. This was explained in the December 1988 issue of DataNetwork in "...A Bit More". On any machine, though, you can include these subroutines as /COPY members and use them as needed.


5250 Data Stream Programming

Figure 3 RPG program WTD

 
       FWTDFM   CF  E                    WORKSTN 
       E                    TEXT    1   1 21 
       I            DS 
       I                                        1 256 WTD 
       I                                        1   1 ESC 
       I                                        2   2 WTDCM 
       I                                        3   3 CC1 
       I                                        4   4 CC2 
       I                                        5   5 SBA 
       I                                        6   6 ROW 
       I                                        7   7 COL 
       I                                        8   8 ATTRST 
       I                                        9  29 WTTEXT 
       I                                       30  30 ATTREN 
       C                     SETON                     LR 
       C* 
       C*    ..initialize bit fields 
       C* 
       C                     BITOF'01234567'X00     1 
       C                     MOVELX00       X04     1 
       C                     MOVELX00       X11     1 
       C                     MOVELX00       X1E     1 
       C                     MOVELX00       X20     1 
       C                     MOVELX00       X21     1 
       C                     MOVELX00       X71     1 
       C                     MOVELX00       ROW     1 
       C                     MOVELX00       COL     1 
       C* 
       C                     BITON'5'       X04 
       C                     BITON'37'      X11 
       C                     BITON'3456'    X1E              *Eq decimal 30 
       C                     BITON'2'       X20 
       C                     BITON'27'      X21 
       C                     BITON'1237'    X71 
       C                     BITON'5'       ROW              *Eq decimal 4 
       C                     BITON'2'       COL              *Eq decimal 32 
       C* 
       C*    ..build Write To Display command string 
       C* 
       C                     MOVELX04       ESC              *Escape 
       C                     MOVELX11       WTDCM            *WriteToDisplay 
       C                     MOVELX00       CC1              *ControlChar1 
       C                     MOVELX00       CC2              *ControlChar2 
       C                     MOVELX11       SBA              *SetBufferAddr 
       C                     MOVELX21       ATTRST           *AttributeStart 
       C                     MOVELX20       ATTREN           *AttributeEnd 
       C* 
       C                     MOVEATEXT,1    WTTEXT 
       C* 
       C*    ..set S/38, AS/400 specific controls  ( see page 4-140 of ) 
       C*       SNDLEN - send data length          ( Data Mgmt Guide   ) 
       C*       RCVLEN - receive data length 
       C*       RQFUNC - requested function 
       C* 
       C                     MOVELX00       SNDLEN  2        *Init left 
       C                     MOVE X00       SNDLEN           *Init right 
       C                     MOVE X1E       SNDLEN           *Set to 30 
       C* 
       C                     MOVELX00       RCVLEN  2        *Init left 
       C                     MOVE X00       RCVLEN           *Init right 
       C* 
       C                     MOVELX71       RQFUNC  1        *Send function 
       C* 
       C*    ..show display, 5250 data stream 
       C* 
       C           *BLANKS   DOWEQ*BLANKS 
       C                     EXFMTFMTEXT 
       C                     WRITEFMWTD 
       C                     EXFMTFMENT 
       C                     END 
  ** 
  Test of WTD command 

5250 Data Stream Programming

Figure 4 Display file WTDFM

 
       A          R FMTEXT 
       A                                      OVERLAY 
       A                                  1  3'Text on line 1... Text on line- 
       A                                       1... Text on line 1... Text o- 
       A                                      n line 1... Text' 
       A                                  2  3'Text on line 2... Text on line- 
       A                                       2... Text on line 2... Text o- 
       A                                      n line 2... Text' 
       A                                  3  3'Text on line 3... Text on line- 
       A                                       3... Text on line 3... Text o- 
       A                                      n line 3... Text' 
       A                                  4  3'Text on line 4... Text on line- 
       A                                       4... Text on line 4... Text o- 
       A                                      n line 4... Text' 
       A                                  5  3'Text on line 5... Text on line- 
       A                                       5... Text on line 5... Text o- 
       A                                      n line 5... Text' 
       A          R FMENT 
       A                                      OVERLAY 
       A                                 22  3'Press ENTER to continue' 
       A          R FMWTD                     USRDFN 

5250 Data Stream Programming

Figure 5 Display file WTDFMX

 
       A          R FMTEXT 
       A                                  1  3'Text on line 1... Text on line- 
       A                                       1... Text on line 1... Text o- 
       A                                      n line 1... Text' 
       A                                  2  3'Text on line 2... Text on line- 
       A                                       2... Text on line 2... Text o- 
       A                                      n line 2... Text' 
       A                                  3  3'Text on line 3... Text on line- 
       A                                       3... Text on line 3... Text o- 
       A                                      n line 3... Text' 
       A                                  4  3'Text on line 4... Text on line- 
       A                                       4... Text on line 4... Text o- 
       A                                      n line 4... Text' 
       A                                  5  3'Text on line 5... Text on line- 
       A                                       5... Text on line 5... Text o- 
       A                                      n line 5... Text' 
       A          R FMENT 
       A                                 22  3'Press ENTER to continue' 
       A          R FMWTD 
       A            SNDLEN         2      1  2TEXT('Send length') 
       A            RCVLEN         2      2  2TEXT('Receive length') 
       A            RQFUNC         1      3  2TEXT('Requested function') 
       A            WTD          256      4  2TEXT('WTD command string') 

5250 Data Stream Programming

Figure 6 Subroutine #CVTTB - convert decimal to binary

 
       C/TITLE  QMACRO,#CVTTB - Convert to binary 
       C**************************************************************** 
       C*  Convert to binary 
       C* 
       C*  Receives - W03N0  N(3,0) 
       C*  Returns  - W01    A(1) 
       C**************************************************************** 
       C* 
       C           #CVTTB    BEGSR 
       C*          *************** 
       C* 
       C                     Z-ADDW03N0     W03N0   30       *Define field 
       C* 
       C                     BITOF'01234567'W01     1        *Clear byte 
       C* 
       C           W03N0     IFGE 128 
       C                     BITON'0'       W01 
       C                     SUB  128       W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 64 
       C                     BITON'1'       W01 
       C                     SUB  64        W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 32 
       C                     BITON'2'       W01 
       C                     SUB  32        W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 16 
       C                     BITON'3'       W01 
       C                     SUB  16        W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 8 
       C                     BITON'4'       W01 
       C                     SUB  8         W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 4 
       C                     BITON'5'       W01 
       C                     SUB  4         W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 2 
       C                     BITON'6'       W01 
       C                     SUB  2         W03N0 
       C                     END 
       C* 
       C           W03N0     IFGE 1 
       C                     BITON'7'       W01 
       C                     END 
       C* 
       C                     ENDSR 

5250 Data Stream Programming

Figure 7 Subroutine #CVTFB - convert from binary to decimal

 
       C/TITLE QMACRO,#CVTFB 
       C***************************************************************** 
       C*  Convert from binary 
       C* 
       C*  Receives - W01    A(1) 
       C*  Returns  - W03N0  N(3,0) 
       C***************************************************************** 
       C* 
       C           #CVTFB    BEGSR 
       C*          *************** 
       C* 
       C                     MOVELW01       W01     1        *Define field 
       C                     Z-ADD0         W03N0   30       *Define field 
       C* 
       C                     TESTB'0'       W01            99*99 - BITON 
       C   99                ADD  128       W03N0 
       C* 
       C                     TESTB'1'       W01            99*99 - BITON 
       C   99                ADD  64        W03N0 
       C* 
       C                     TESTB'2'       W01            99*99 - BITON 
       C   99                ADD  32        W03N0 
       C* 
       C                     TESTB'3'       W01            99*99 - BITON 
       C   99                ADD  16        W03N0 
       C* 
       C                     TESTB'4'       W01            99*99 - BITON 
       C   99                ADD  8         W03N0 
       C* 
       C                     TESTB'5'       W01            99*99 - BITON 
       C   99                ADD  4         W03N0 
       C* 
       C                     TESTB'6'       W01            99*99 - BITON 
       C   99                ADD  2         W03N0 
       C* 
       C                     TESTB'7'       W01            99*99 - BITON 
       C   99                ADD  1         W03N0 
       C* 
       C                     ENDSR 
BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: