1B MicroScript Thorough Primer, No. 5

Toshihisa Muto

Personal Media Corporation


On this occasion and in the next installment, we will carry out parts creation using a script by taking a lighting panel as an example. You will learn how to create a selector to make choices and a volume control to set values.

1B MicroScript [1] is a programming language that runs on top of 1B series BTRON-specification personal computers. In particular, it is suited to the description of visual operations, such as the creation of screens for presentation use, and the control of external devices.

In the four installments up to here, I have finished explaining in general the main functions. Accordingly, over the next two installments, on this occasion and in the next installment, we will attempt parts creation using a script. Parts are pieces for the purpose of setting values in regard to the user. In general terms, we will create the following two parts.

Selector

This is a part for selecting one of several from among multiple choices. On this occasion, we will make it so that one cannot make multiple selections or no selection. It is by all means necessary that only one item is to be selected. When the user clicks a choice, the ON indicator moves there, and that turns into a selected state.

Moreover, a choice can set only one selector, which in particular we call a "switch," with an ON/OFF value. In this case, every time we press the switch, ON and OFF invert.

Volume Control

This is a part mainly for the purpose of setting numerical values. We can control it with the following four methods.

(1)
Dragging: Directly jumping to the value we want to set by dragging a knob

(2)
Pressing: Moving a knob forward in that direction little by little by pressing a part outside of the knob.

(3)
Double Clicking: Moving a knob a great amount in that direction by double clicking

(4)
Clicking: Moving a knob a small amount in that direction by pressing a part outside of the knob.

Creating a Lighting Panel

Let's now try actually making a panel for controlling lighting (Fig. 1). On the left, there is a selector for choosing one from among five types of lighting: "Refreshing Lighting," "Soft Lighting," "Warm Lighting," "Subdued Lighting," or "Clear Lighting." On the right, there is a volume control for setting the "angle" of the lighting, and below that there is a switch for specifying "Automatic Lighting Adjustment." The thing at the bottom of the panel is a volume control for setting the brightness.

Figure 1. Lighting control panel

Because the main point of the programming on this occasion lies in creating parts, we will make it so that control of actual lighting equipment will not be carried out at all. We will only carry out a simple operation in which when you select [Show Current Values] from the [Control] menu, the currently set values of the parts will appear at the bottom of the screen (Fig. 2).

Figure 2. Displaying current values in the message area

Realized as a Library

In the programming on this occasion, I have made it so that the procedures that realize the parts are realized as a library. In other words, I precisely decided the call interfaces of the library at the time of program design. If we call up procedures in accordance with those rules, we can easily create the parts inside the screen. It is not at all necessary to worry about how that library is programmed.

Defining the Lighting Panel Segments

The definitions of the lighting panel segments are as in Fig. 3. Because the segments are rather packed together, I shall explain them one by one. @sel0 to @sel4 are made up from the character segments "Refreshing Lighting" to "Clear Lighting," and @sw the character segment "Automatic Lighting Adjustment." @plate0 and @plate1 are three-dimensional bases (plates) that are placed under the characters. And then, @off0/@on0 and @off1/@on1 serve as ON/OFF indicators that are respectively used in selectors and switches. Up to here are the segments for selectors (switches).

Figure 3. Lighting control panel segment definitions

The remainder are ones concerning volume. @vol0 and @vol1 become the hollow parts, and @knob0 and @knob1 become the handle (knob) segments. @label0 and @label1 are the label segments, such as "Brightness," "Angle," and gradations.

Well then, as usual, a script is described in a real object that begins with "SCRIPT." As in Fig. 3, one can store several script real objects inside one figure real object.

SCRIPT: Common [Upper Left]

This is a common script necessary in utilizing the parts library. The definition of constants, and so on, are carried out here.

SCRIPT: Selector [Upper Right]

This is a script that realizes the selector library. Just by entering this script, it becomes possible to utilize the selector library.

SCRIPT: Volume [Lower Right]

This is a script that realizes the volume control library in the same manner. I will take this up in the next installment.

SCRIPT: Lighting [Lower Left]

This is a script for the Lighting panel. Actually, this alone is fine for user programming. As for the three scripts "SCRIPT: Common," "SCRIPT: Selector," and "SCRIPT: Volume," simply leave them as they are; there is no need to know their contents.

Finally, one important point for caution. In MicroScript, in a case where multiple script real objects exist, MicroScript interprets through them in the order in which their virtual objects were created inside the figure real object. In the case on this occasion, the definitions necessary in order to execute the other scripts are carried out inside "SCRIPT: Common." Accordingly, it is necessary to first create and save the "SCRIPT: Common" virtual object in the "Lighting" real object. Next, we create and save the remaining virtual objects. When you make a mistake with this order, an error message stating that "variable such and such is not defined" will appear at execution time, and you cannot continue with execution.

Creating Selectors by Utilizing a Parts Library

Well then, let's finally try using a parts library. The parts are selectors for selecting one from among five lighting choices and a switch for setting the Automatic Lighting Adjustment ON/OFF. I would like you to look at Program 3 "SCRIPT: Lighting."

I shall follow through the procedures one by one in the order that they are executed. The place where execution begins first is, of course, the part enclosed with PROLOGUE~END in the 59th to 66th lines. In

63 SCENE scene Selector Switch Volume

on the 63th line, we register all the segments that we have created. However, it is not necessary to include the @off @on segments here.

The actual selector preparations are carried out with the procedure "Prepare_Selector."

64 CALL Prepare_Selector

Procedure "Initialize_Selector"

First, it is made up as

30 CALL Initialize_Selector

on the 30th line. It is necessary to call "Initialize_Selector" only once in the beginning when we create the selectors.

Preparing the Lighting Selector (31st to 39th Lines)

Procedure "Register_Selector1"

Next, we register the lighting selector with

33 CALL Register_Selector1 on0 off0 (-17) (5)

The respective arguments have the following meanings.

No. 0 argument [2]: <ON indicator segment>
No. 1 argument: <OFF indicator segment>
No. 2 argument: <indicator relative position: x coordinate>
No. 3 argument: <indicator relative position: y coordinate>

Through the indicator relative position, we display the indicator display position with the relative position of the segment of the choice (Fig. 4).

Figure 4. Fixing of indicator display positions

Well then, almost all the procedures that the parts library on this occasion provides return a return value. However, MicroScript does not possess a mechanism for handling return values. Accordingly, after determining a global variable for the purpose of storing the return value, we will make it so that we use that. Immediately after we have called up a parts library procedure, a return value will enter into a variable with the name "ret." By referencing the variable ret, we come to take out the return value [3].

When we call up the procedure "Register_Selector1," the selector ID is returned as the return value. Afterward, operations concerning this selector ("Lighting Selector"), are carried out using this ID. Actually, an integer value of 0 or higher is used. In the 34th line, we store the selector ID in the variable selid with

34 SET selid ret

In a case where registration has failed, the return value becomes negative. The error check will be omitted here.

Procedure "Register_Selector2"

After the procedure "Register_Selector1," it is necessary to register the lighting selector choices by calling up "Register_Selector2."

38 CALL Register_Selector2 selid 5 sel0 sel1 sel2 sel3 sel4

It comes about that we specify the choice names "Refreshing Lighting," "Soft Lighting," "Warm Lighting," "Subdued Lighting," and "Clear Lighting."

Each argument has the following meaning.

No. 0 argument: <selector ID>
No. 1 argument: <number of the choice>
No. 2 argument: <choice0 segment>
No. 3 argument: <choice1 segment>

Following no. 2 argument, we give choices as arguments one by one up to the number specified in the no. 1 argument. In other words, it comes about that the procedure ""Register_Selector2" takes a variable number of arguments. Here, we have specified character segments, but, of course, it is all right even if we register figures as choices. Furthermore, choices are possible up to a maximum of six [4].

In a case where registration fails, the return value becomes negative, but here also I am omitting the error check.

Procedure "Set_Selector"

We specify the initial value of the lighting selector with the 39th line.

39 CALL Set_Selector selid 3

No. 0 argument: <selector ID>
No. 1 argument: <setting value> 0~of the choice number

What we call the choice number is the number when 0 is made the first choice given in no. 2 argument of "Register_Selector2." Because we have specified "3" here, it comes about that the ON indicator turns on at "Subdued Lighting."

Preparing the Automatic Lighting Adjustment Switch (41st to 46th Lines)

Lighting selector preparation is finished by up to the 39th line. Next, we prepare the switch ("Automatic Lighting Adjustment"). A switch corresponds to a case in which there is no more than one selector choice. Where it differs is only on the point that a switch allows a case in which an ON indicator does not exist. Accordingly, as to switches, we handle them as the same parts as selectors, and as to procedures for registering, we also use the same ones.

42 CALL Register_Selector1 on1 off1 (-17) (5)
43 SET swid ret
44 CALL Register_Selector2  swid 1 sw
45 CALL Set_Selector swid ON

In the case of a switch, we specify ON (=1) or OFF (=0) as the value of the switch in the no. 1 argument of the procedure "Set_Selector."

Furthermore, as for the indicator segments (@on, @off), even in a case where we use ones of the same design among several selectors, it is necessary to respectively prepare them separately. We cannot share among the selectors themselves.

Processing When the Parts Have Been Clicked (4th to 26th Lines)

In the 4th to 26th lines, we have described the processing when each segment is clicked. In making it so that we can use the selector, outside of registering, it is necessary to describe the processing when each segment is clicked in this manner [5].

Among these procedures, of course, no matter what description is carried out is all right. However, when we are using the parts library, in order to set a new value, it is by all means necessary to call up the procedure "Set_Selector" and modify the setting values. In concrete terms, in the case of the selector, we call

39 CALL Set_Selector (Selector ID) TOGGLE

TOGGLE has the meaning of "turning from side to side," and it is set with the value -1.

Inside these procedures, a method of use in which we call up the procedure "Set_Selector" in regard to other parts and make settings is possible. For example, it is all right to set in the manner below an operation in which we always set "Automatic Lighting Adjustment" to OFF only when "Clear Lighting" has been selected.

ACTION Clear_Lighting_Clicked CLICK selid 4
CALL Set_Selector selid 4
CALL Selector swid OFF
END

Displaying the Current Values

The operation for when we have selected [Display Current Values] from the [Control] menu, is described in the 49th to 56th lines [6]. In the 52nd line and 54th line

52 CALL Acquire_Selector selid
54 CALL Acquire_Selector swid

by means of calling up the procedure "Acquire_Selector," we can acquire the current value of the specified selector ID. By means

55 MESG "Current Lighting Values=%d 
         Current Automatic Lighting Adjustment Values=%d" 
        Lighting_Values ret

in the 55th line, we display the current value in the message area at the bottom of the 1B screen.

"SCRIPT: Common" and "SCRIPT: Selector"

As of up to here, the explanation of "SCRIPT: Lighting" is finished. In "SCRIPT: Common" and "SCRIPT: Selector," the selector parts library below used in "SCRIPT: Lighting" is programmed.

Procedure "Initialize_Selector"
Procedure "Register_Selector1"
Procedure "Register_Selector2"
Procedure "Set_Selector"
Procedure "Acquire_Selector"

Because I have relatively thoroughly attached comments to Program 1 and Program 2, I shall forego explaining these in detail in this article.

I would like to explain only the main points below.

"SCRIPT: Common" (Program 1)

In the beginning, we show the number of parts that can be registered.

1 DEFINE MAXVOL 3
2 DEFINE MAXSEL 3
3 DEFINE MAXELM 18

If we make MAXVOL and MAXSEL large, then we can increase the maximum number of volume controls and selectors that can be registered.

In MAXELM, we describe a value in which we have calculated MAXSEL x MAXCHOICE. MAXCHOICE is the maximum number of choices that can be registered in regard to one selector, and this is fixed at "6," which is defined in the 1st line of "SCRIPT: Selector."

"SCRIPT: Selector" (Program 2)

One point about this program is that we draw and move the indicators by means of the MOVE statement, APPEAR statement, and DISAPPEAR statement. Concerning the MOVE statement, I would like you to reference No. 1 in this series (Vol. 22, page 71 of this magazine).

In Closing

In the installment on this occasion, we created selector and switch parts using MicroScript. If we just store "SCRIPT: Common" and "SCRIPT: Selector" inside a figure real object, then selectors and switches can easily be realized merely by calling up the procedures "Initialize_Selector," "Register_Selector1," "Register_Selection2," "Set_Selector," and "Acquire_Selector."

Moreover, in designing the parts as well, the fact that MicroScript can completely separate the design of segments and their operations also becomes a great advantage. In other words, without modifying the script whatsoever, we can afterward freely change such things as the names of choices, the designs of the indicators/switches, and the arrangement of the choices (e.g., vertical line-up or horizontal line-up).

In the next installment, we will make it our business to create the volume controls for "Angle" and "Brightness" inside the lighting panel to make the lighting panel complete.

____________________

Program 1 "SCRIPT: Common"
1 DEFINE MAXVOL 3 # Maximum number of volume controls
2 DEFINE MAXSEL 3 # Maximum number of selectors (switches)
3 DEFINE MAXELM 18 # MAXSEL x MAXCHOICE
4
5 DEFINE pid $ARG[0] # Use the first argument as the PID
6
7 VARIABLE ret # Variable that enters the return value of a procedure

Program 2 "SCRIPT: Selector"
  1 DEFINE MAXCHOICE 6 # Maximum number of choices
  2 DEFINE ON (1)
  3 DEFINE OFF (0)
  4 DEFINE TOGGLE (-1)
  5
  6 # Variables we use in selector parts
  7 # In variables we store segments in, we attach _ at the beginning
  8 VARIABLE _s_I # Counter
  9 VARIABLE _s_nsel # Number of registered selectors
 10 VARIABLE _choice[MAXELM] # Choice segments
 11                          # Utilized as two-dimension array
 12 VARIABLE _s_nchoice[MAXSEL] # Number of choices
 13 VARIABLE _s_selval[MAXSEL]  # Current value of the selector
 14 VARIABLE __s_on[MAXSEL]   # ON indicator segment
 15 VARIABLE __s_off[MAXSEL]  # OFF indicator segment
 16 VARIABLE _s_xofs[MAXSEL] # Indicator relative position: x coordinate
 17 VARIABLE _s_yofs[MAXSEL] # Indicator relative position: y coordinate
 18
 19 #--------------------------------------------------------------------
 20 ACTION Initialize_Selector
 21   SET _s_nsel 0
 22 END
 23
 24 #--------------------------------------------------------------------
 25 # Selector Registration Part 1
 26 #   Selector_Registration1
 27 #     $ARG[0]: (ON  indicator segment)
 28 #     $ARG[1]: (OFF indicator segment)
 29 #     $ARG[2]: (Indicator relative position: x coordinate)
 30 #     $ARG[3]: (Indicator relative position: y coordinate)
 31 #   Return value <0 error
 32 #                >=0 Selector ID (0~)
 33 #
 34 ACTION Selector_Registration1
 35 IF _s_nsel >= MAXSEL
 36   SET ret -1
 37   EXIT
 38 ENDIF
 39 SET __s_on[_s_nsel] $ARG[0]
 40 SET __s_off[_s_nsel] $ARG[1]
 41 SET _s_xofs[_s_nsel] $ARG[2]
 42 SET _s_yofs[_s_nsel] $ARG[3]
 43 SET _s_selval[_s_nsel] 0
 44 SET ret _s_nsel
 45 SET _s_nsel _s_nsel +1
 46ýEND
 47
 48 #--------------------------------------------------------------------
 49 #
 50 # Displaying OFF indicator beside a choice 
 51 #
 52 ACTION _s_showIndicators
 53 SET _s_I 0
 54 APPEAR __s_off[pid]
 55 REPEAT
 56   IF _s_I >= _s_nchoice[pid]
 57     BREAK
 58   ENDIF
 59   # Display OFF indicator in a position shifted only with _s_xofs,
 60   # _s_yofs from upper left corner of the choice segment (_choice)
 61   MOVE __s_off[pid]: _s_xofs[pid]
           _s_yofs[pid]_choice[pid*MAXCHOICE+_s_I] : DUP
 62   SET _s_I _s_I + 1
 63 ENDREPEAT
 64 END
 65 
 66 #--------------------------------------------------------------------
 67 # Selector Registration Part 2
 68 #   Selector_Registration2
 69 #     $ARG[0]: (Selector ID) pid(0~)
 70 #     $ARG[1]: (Number of choices)
 71 #     $ARG[2]: (Choice 0 segment)
 72 #     $ARG[3]: (Choice 1 segment)
 73 #           :   :   :  : 
 74 #   Specify choice segments up to a maximum of 6
 75 #   Return value <0 error
 76 #                =0 Terminate Registration
 77 #
 78 ACTION Selector_Registration2
 79 IF $ARG[1] > MAXCHOICE
 80   # Maximum registration number has been exceeded
 81   SET ret -1
 82   EXIT
 83 END
 84
 85 # Store one each of the choice segments inside _choice
 86 SET _s_I 0
 87 REPEAT
 88   IF _s_I >= $ARG[1]
 89     BREAK
 90   ENDIF
 91   SET _choice[pid*MAXCHOICE+_s_I] $ARG[_s_I+2]
 92   SET _s_I _s_I+1
 93 ENDREPEAT
 94 # Store number of choices inside _s_nchoice
 95 SET _s_nchoice[pid] _s_I
 96 # Display OFF indicator
 97 CALL _s_showIndicators pid
 98 SET ret 0 
 99 END
100
101 #--------------------------------------------------------------------
102 # Set value in the selector
103 #   Set_Selector
104 #     $ARG[0]: (Selector ID) :pid(0~)
105 #     $ARG[1]: (Set value)
106 #         Selector use = 0~ of the choice numbers
107 #         Switch use   = ON(1) / OFF(0)
108 #                      = TOGGLE(-1)
109 #    No return value
110 DEFINE _appear $ARG[7] # Local variable
111 DEFINE _disap  $ARG[6] # Local variable
112 ACTION Set_Selector
113 IF _s_nchoice[pid] == 1
114 # Use switch
115   IF $ARG[1] != TOGGLE
116     # Set another value for the value you would like to set
117     SET _s_selval[pid] ($ARG[1] + 1) % 2
118   ENDIF
119   # Display the current value of the inverted indicator
120   # If current value is OFF, to ON; if ON, to OFF
121   IF _s_selval[pid] == ON # When current value is ON 
122     SET _appear __s_off[pid]; SET _disap __s_on[pid]
123   ELSE # When current value is OFF
124     SET _appear __s_on[pid]; SET _disap __s_off[pid]
125   ENDIF
126   MOVE _disap; MOVE _appear :_s_xofs[pid]
           _s_yofs[pid] _choice[pid*MAXCHOICE];
127   APPEAR _appear
128   # Inverts the current value
129   SET _s_selval[pid] (_s_selval[pid] + 1) % 2
130 ELSE
131 # Use Selector
132   # In clicked choice ($ARG[1])
133   # Move the ON indicator
134   MOVE __s_on[pid] :_s_xofs[pid] _s_yofs[pid]
           _choice[pid*MAXCHOICE+$ARG[1];
135   APPEAR __s_on[pid]
136   # Set the current value
137   SET _s_selval[pid] $ARG[1]
138 ENDIF
139 END
140
141 #--------------------------------------------------------------------
142 # Acquire current value of the selector
143 #   Acquire_Selector
144 #     $ARG[0]: (Selector ID) pid(0~)
145 #   Return value 0~
146 ACTION Acquire_Selector
147 SET ret _s_selvol[pid]
148 END

Program 3 "SCRIPT: Lighting"
 1 VARIABLE selid # Lighting Selector Parts ID
 2 VARIABLE swid  # Automatic Lighting Adjustment Switch Parts ID
 3 ######################################################################
 4 ACTION Refreshing_Lighting_Clicked CLICK sel0
 5 CALL Set_Selector selid 0
 6 END
 7
 8 ACTION Soft_Lighting_Clicked CLICK sel1
 9 CALL Set_Selector selid 1
10 END
11
12 ACTION Warm_Lighting_Clicked CLICK sel2
13 CALL Set_Selector selid 2
14 END
15
16 ACTION Subdued_Lighting_Clicked CLICK sel3
17 CALL Set_Selector selid 3
18 END
19
20 ACTION Clear_Lighting_Clicked CLICK sel4
21 CALL Set_Selector selid 4
22 END
23
24 ACTION Automatic_Lighting_Adjustment_Clicked CLICK sw
25 CALL Set_Selector swid TOGGLE
26 END
27
28 ######################################################################
29 ACTION Prepare_Selector
30 CALL Initialize_Selector
31 # Display ON and OFF indicators in a position 17 dots from the left 
32 # 5 dots down from the upper left hand corner of the choice segment
33 CALL Register_Selector1 on0 off0 (-17) (5)
34 SET selid ret # Parts ID is stored in return value ret
35
36 # Register the lighting choice: "Refreshing," "Soft," "Warm,"  
37 # "Subdued," "Clear"
38 CALL Register_Selector2 selid 5 sel0 sel1 sel2 sel3 sel4
39 CALL Set_Selector selid 3 # Set initial value
40 #---------------------------------------------------------------------
41 # Register the "Automatic Lightning Adjustment" Switch
42 CALL Register_Selector1 on1 off1 (-17) (5)
43 SET swid ret
44 CALL Register_Selector2  swid 1 sw
45 CALL Set_Selector swid ON # Set initial value
46 END
47
48 ######################################################################
49 DEFINE Lightning_Values $ARG[7]
50 # When you select [Display Current Values] menu, it displays current
51 ACTION Display_Current_Values MENU "Display Current Values"
52 CALL Acquire_Selector selid
53 SET Lighting_Values ret
54 CALL Acquire_Selector swid
55 MESG "Current Lighting Values=%d 
         Current Automatic Lighting Adjustment Values=%d" 
        Lighting_Values ret
56 END
57
58 ######################################################################
59 PROLOGUE
60 DEFINE Selector plate0 sel0 sel1 sel2 sel3 sel4
61 DEFINE Switch plate1 sw
62 DEFINE Volume label0 vol0 knob0 label1 vol1 knob1
63 SCENE scene Selector Switch Volume
64 CALL Prepare_Selector
65 # CALL Prepare_Vol_Cntrl # To be explained in the next installment
66 END

____________________

[1] 1B MicroScript: As a result of the March 1994 1B version upgrade (SUS9312, R1.060), MicroScript has become standard equipment in 1B basic software. However, no explanatory materials necessary for programming are attached. Basically, you use it as a player for replaying scripts that other people have created. For example, lots of scripts have been uploaded to personal computer communications provider NIFTY-Serve's Personal Media Forum (FPMC). You can replay these on your 1B at hand by downloading them. Furthermore, the explanatory materials necessary for development and a sample collection are sold separately as "1B MicroScript Development Kit" (standard price 30,000 yen, SUS discount price 10,000 yen; both prices tax not included).

[2] No. 0 Argument: We make it so that we call the first argument the No. 0 Argument. Thereafter, we continue with No. 1 Argument, No. 2 Argument . . .

[3] ret that stores the return value: Pay attention to the fact just one ret variable exists. For example, if we call separate library procedure B after we have called procedure A of one of the libraries, we end up losing the return value of procedure A.

[4] Number of choices, maximum of six: With the current 1B MicroScript, the maximum number of arguments that can be given to an procedure is a maximum of eight. In "Register_Selector2," because we have made it so that we give all the choices in one procedure call, this limit comes to appear. Of course, if we design a separate interface procedure, it is also possible to eliminate this kind of limit.

[5] Processing when a segment has been clicked: Please refer to the first installment (p. 70 in Vol. 22 of this magazine) concerning a description for when an event such as CLICK has occurred on a segment.

[6] Registering the Menu: Please refer to the first installment (p. 70 in Vol. 22 of this magazine) concerning the method for newly creating a menu in MicroScript.


The above article on MicroScript appeared on pages 38-45 in Vol. 27 of TRONWARE . It was translated and loaded onto this Web page with the permission of Personal Media Corporation.

Copyright © 1994 Personal Media Corporation

Copyright © 2008 Sakamura Laboratory, University Museum, University of Tokyo