The MIRTOS System Command Processor was designed to be used interactively, which is actually the meaning of the "I" in the MIRTOS acronym. But to actually use a microcontroller for control, there should be some way of executing a series of commands. Unique device initialization is needed with a startup configuration file. Furthermore, it would be convenient to be able to change those commands easily, store them in a readable format, and be able to invoke them on command.
All of the interactive commands can also be stored in either EEPROM or FLASH memory and sequentially executed as "batch" of commands. These human-readable "scripts" can either be invoked from the serial command console using the Script system command or programmatically from a subroutine, setting the script pointer WORD variable, ScriptNextOp and then either setting or clearing the bit BIT_SYS_SCRIPT_FLASH in the bFlags_System BYTE variable, as the script location determines. The three variables mentioned in the last sentence are defined in the SystemSRAM.Def file.
Not every form of every System Command, however, can be placed in a script. The text character limit for a script line is 50 bytes. Since the serial Parsing Buffer is larger than that, a script line will always be able to fit in the Parsing Buffer. It is not difficult to limit script text lines to 50 bytes, however. Note also that an nRF command limit is even less than 50 bytes.
The Script Processor is enabled after a system reboot only after the first full second has passed. It always verifies that the serial Parsing Buffer is empty before it inserts a new script command into that buffer. Entering even one character into the Parsing Buffer will prevent any script from executing. One way to stop a script from initializing a device is to hit the spacebar during the first second and enter " E 1 = 0", for example. Any leading space is (or spaces are) removed from the Parsing Buffer before the command is handed to the System Command Processor.
There are some commands which are ONLY a part of the scripting language command set. For example, there is no need for an interactive command to delay processing, for example. When executing a command sequence, however, it is sometimes necessary to delay execution until some task has completed. The scripting language therefore contains timed delay commands. The script timers will mark time but will not timeout while there is any command being processed by the System Command Processor. This is because script commands will not interrupt a system command or entry of a system command.
.STRING "; OFF script: " ; Note the start and purpose .STRING "N 0x60" ; Change the nRF24L01 from PRX to PTX mode .STRING "N> 'SNPW:Node_Name'" ; Log into the remote device .STRING "N> 'ES 0x282 = 0'" ; Set the BYTE at uVars.B[2] to 0 .STRING "N> 'Logoff'" ; Log out of the remote device .STRING "ES 0x284 = 50 M" ; Setup a BYTE mSec timer at uVars.B[4] .STRING "TM1 V4" ; Start the 50 millisecond BYTE timer .STRING "N*" ; Reload the default nRF configuration .STRING "S = -1 E" ; Park the script pointer .BYTE 0xFF ; Terminate the script
In the example above, the "N>" commands transmit the string which follows to be sent to the nRF24L01, as "immediately" as possible. If the default configuration were then to be reloaded immediately, the transmission may be interrupted and message not be received. For that reason, the "ES ..." and "TM1 ..." script lines configure and implement a 50 mSec delay. This is to be certain that the radio has enough time to send the message before the default PRX configuration is reloaded with "N*".
The syntax of the Script Timer Command is:T[M1|M2|M4|S1|S2] [V#|Address] where "M" or "S" select either a mSec or Seconds timer "1", "2", or "4" select the number of bytes (BYTE, WORD, ULONG) "V#" or "Address" specifies the timer's starting SRAM addressNotes:
Time | Desired | Start at | Command to initialize | uVars.B[##] Uses | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Range | Type of timer | Delay | uVars.B[##] | the uVars.B[##] | the Timer | Delay | Start | |||
1 to 250 mSec |
1-byte (BYTE) mSec |
4 mSec | 0 | ES 640 = 4 M | TM1 V0 | 0 | 1 | |||
10 mSec | 1 | ES 0x281 = 10 M | TM1 V0 | 1 | 2 | |||||
100 mSec | 5 | ES 645 = 100 M | TM1 0x281 | 5 | 6 | |||||
250 mSec | 18 | ES 658 = 250 M | TM1 658 | 18 | 19 | |||||
1 to 65,530 mSec |
2-byte (WORD) mSec |
250 mSec | 0 | ESW 0x280 = 250 M | TM2 V0 | 0 & 1 | 2 & 3 | |||
750 mSec | 8 | ESW 648 = 750 M | TM2 V8 | 8 & 9 | 10 & 11 | |||||
1 Second | 8 | EWS 0x288 = 1000 M | TM2 0x288 | 8 & 9 | 10 & 11 | |||||
2.496 Seconds | 24 | EWS 664 = 2496 M | TM2 V24 | 24 & 25 | 26 & 27 | |||||
60 Seconds | 28 | EWS 668 = 60000 M | TM2 668 | 28 & 29 | 30 & 31 | |||||
1 to 4,294,967,290 mSec |
2-byte (WORD) mSec |
4 mSec | 0 | ESL 640 = 4 M | TM4 V0 | 0, 1, 2 & 3 | 4, 5, 6 & 7 | |||
60 Seconds | 24 | ESL 664 = 60000 M | TM4 664 | 24, 25, 26 & 27 | 28, 29, 30 & 31 | |||||
6 Minutes | 24 | ESL 0x298 = 360000 M | TM4 V24 | 24, 25, 26 & 27 | 28, 29, 30 & 31 | |||||
1 Hour | 9 | ELS 649 = 3600000 M | TM4 0x289 | 9, 10, 11 & 12 | 13, 14, 15 & 16 | |||||
1 to 256 Seconds |
1-byte (BYTE) Seconds |
4 Seconds | 2 | ES 642 = 4 S | TS1 V2 | 2 | 3 | |||
60 Seconds | 24 | ES 664 = 60 S | TS1 0x298 | 24 | 25 | |||||
240 Seconds | 30 | ES 670 = 240 S | TS1 V30 | 30 | 31 | |||||
1 to 65,536 Seconds |
2-byte (WORD) Seconds |
4 Seconds | 2 | ESW 642 = 4 S | TS2 V2 | 2 & 3 | 4 & 5 | |||
60 Seconds | 24 | ESW 664 = 60 S | TS2 0x298 | 24 & 25 | 26 & 27 | |||||
600 Seconds | 6 | EWS 646 = 600 S | TS2 V6 | 6 & 7 | 8 & 9 | |||||
900 Seconds | - | ESW 0x500 = 900 S | TS2 0x500 | none; above uVars.B[##] range |
All Foreground and Background processes (command processing, serial output, nRF radio, WS2812, etc.) continue to operate while a script timer is timing. The seconds heartbeat LED, for example, can be used to demonstrate this aspect. Recall from the "S" command description, that when an "S" or "S =" command is executed, it will display the script operation pointer.
Example of entering a script, starting at EEPROM address 0x130:> S = -1 E ; Park the script pointer at an invalid EEPROM address Next operation pointer: 0xFFFF >DE+ 0x130 48 ; Verify that portion of EEPROM is unused EEPROM contents: 0130: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0140: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 0150: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ >E 0x130 = "ESW 0x500 = 4 S" >E 0x140 = "TS2 0x500" >E 0x14A = "ESW 0x510 = 1 S" ; Saved after the timer expires >DE+ 0x130 48 EEPROM contents: 0130: 45 53 57 20 30 78 35 30-30 20 3D 20 34 20 53 00 ESW 0x500 = 4 S. 0140: 54 53 32 20 30 78 35 30-30 00 45 53 57 20 30 78 TS2 0x500.ESW 0x 0150: 35 31 30 20 3D 20 31 20-53 00 FF FF FF FF FF FF 510 = 1 S....... >DS+ 0x500 20 SRAM contents: 0500: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 0510: 00 00 00 00 .... >S = 0x130 ; Start the script at EEEPROM address 0x130 Next operation pointer: 0x0130 ESW 0x500 = 4 S >>>
Notice that when the script started, it immediately output two (2) prompt (">") characters, as shown above. It then began timing and after 4 seconds, the third prompt character was printed, after the timer timed out. If the seconds heartbeat LED was enabled, the LED changed states while the timer was timing. Many timers can be timing simultaneously, but only a single script can be running at any time.
Shown below is the output beginning at the time that the script was started, so some is repeated. After the timer fired, the last script line which saved the time value was executed. Let's check that first.
Next operation pointer: 0x0130 ESW 0x500 = 4 S >>> DS+ 0x500 20 ; Display the section of SRAM used SRAM contents: 0500: 04 00 73 1C 00 00 00 00-00 00 00 00 00 00 00 00 ..s............. 0510: 01 00 77 1C ..w. >
There was no output while the timer was timing. Script debugging can be enabled so you can actually see that it is doing something, and even what portion of the script is executing. Type the ']' character at the start of a new line. If it is displayed, it was not the first character on the line. That toggle key can generate significantly more output. Before executing the next command, it will probably be very good to note that it can even be toggled (off or on) while a script is running (especially if the Stack Dump option with the Registers display, using '}', is enabled.)
If your terminal program cannot display lines with 100 characters, the output may look different that that shown above. Be sure that script debugging is toggled off and copy "E 4 ^= 32" into your cut-and-paste buffer (Ctrl-C in Windows) and enter these 3 commands, which are shown entered into the captured screen below:> S = 304 ; = 0x130 10 32 54 76 98 1110 1312 1514 1716 1918 2120 2322 2524 2726 2928 3130 SP RetAdd SREG ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ------ -------- 0000 054D 090E FF28-0004 0000 0000 6000-0021 007F 5312 3D20-940F 0230 0280 1B00 08F1 3604 ItHsvnZc Next operation pointer: 0x0130 ESW 0x500 = 4 S > <==> Next operation pointer: 0x0130 ESW 0x500 = 4 S <==> Next operation pointer: 0x0140 TS2 0x500 0000 054E 090E FF28-0004 0000 0000 6000-0021 207F 450F 5753-940F 0230 0280 1B00 08F1 3604 ItHsvnZc > <==> Next operation pointer: 0x0140 TS2 0x500 <==> Next operation pointer: 0x0140 TS2 0x500 <==> Next operation pointer: 0x0140 TS2 0x500 (omitted the same line above, repeatedly output over 430 times during the 4 second delay) <==> Next operation pointer: 0x0140 TS2 0x500 <==> Next operation pointer: 0x014A ESW 0x510 = 1 S <==> Next operation pointer: 0x015A 10 32 54 76 98 1110 1312 1514 1716 1918 2120 2322 2524 2726 2928 3130 SP RetAdd SREG ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ------ -------- 0000 0002 0912 FF28-0004 0000 0000 6000-0021 007F 450F 5753-940F 0230 0280 1B00 08F1 3604 ItHsvnZc > ... (toggled debugging back off using ']' and '}') >
> S = -1 Next operation pointer: 0xFFFF >E 4 ^= 32 ; Display the script logic Hz line each second >Script logic Hz: 1 Script logic Hz: 1 >S = 0x130 Next operation pointer: 0x0130 ESW 0x500 = 4 S >>Script logic Hz: 29 Script logic Hz: 2,943 Script logic Hz: 2,940 Script logic Hz: 2,942 >Script logic Hz: 2 Script logic Hz: 1E 4 ^= 32 ; Disable the 1 second script logic Hz output >
When an "S" or "S =" command is executed, the script operation pointer string is output to the COM1 serial port. It helps to have the command you'll need in the clipboard and just paste "E 4 ^= 32" into the terminal window.
Scripts obey all rules which apply to a System Command, with the additional restriction of length: 50 BYTEs for scripts, 80 BYTEs for Commands. For example, the iHex memory change command requires that the device be in Manager or Administrative mode to actually make any change. If the device is not in either of those modes at the time the script command is issued, the desired change will not take place.
Script extensions are also like command extensions in that they are enabled by placing a script extension handler routine in FLASH and entering its address in EEfptrScriptExts (which is defined in SystemEEPROM.Def) in EEPROM.
The Script Processor only enbuffers a script command into the Parsing Buffer; it does not directly call the System Command Processing routine, since it doesn't know what else may be occurring in the system. If there is something in the parsing buffer (for example, an incomplete command being typed, or even just a single space character), the Script Processor will wait to enbuffer the script command. Only the main Operating System routine actually calls the System Command Processor and does that in the Foreground. Note that a Background process can be interrupted by the Foreground process.
Here is an example of a bootup script:The content and meaning of each of the ten (10) script lines:> DE+ 0xB0 0x70 00B0: 3B 20 42 6F 6F 74 75 70-20 49 6E 69 74 3A 20 00 ; Bootup Init: . 00C0: 45 20 31 20 7E 3D 20 30-78 43 30 00 45 53 20 30 E 1 ~= 0xC0.ES 0 00D0: 78 31 44 46 20 3D 20 30-78 33 41 00 4E 2A 2A 00 x1DF = 0x3A.N**. 00E0: 4E 44 2B 00 50 20 3D 20-38 00 50 47 3D 31 20 00 ND+.P = 8.PG=1 . 00F0: 56 57 20 34 20 3D 20 39-30 30 20 4D 00 54 4D 32 VW 4 = 900 M.TM2 0100: 20 56 20 34 00 50 42 3D-31 00 45 20 30 78 31 39 V 4.PB=1.E 0x19 0110: 20 3D 20 30 78 31 35 00-45 20 33 32 20 3D 20 30 = 0x15.E 32 = 0 0120: 78 32 32 00 FF FF FF FF-FF FF FF FF FF FF FF FF x22............. >
; Bootup Init: | This is simply a comment | |
E 1 ~= 0xC0 | Disable both the sequencing and multitasking logic | |
ES 0x1DF = 0x3A | Set the format of the Register Dump ("R") command | |
N** | Load the default nRF24L01+ configuration | |
P = 8 | Configure the WS2812 routine for 8 pixels (24 BYTEs) | |
PG=1 | Set all 8 pixels to Green, intensity 1, and output them | |
VW 4 = 900 M | Initialize a WORD timer for 900 mSec | |
TM2 V 4 | Run the timer to perform the delay | |
PB=1 | Set all 8 pixels to Blue, intensity 1, and update them | |
E 0x19 = 0x15 | Configure the heartbeat LED to use PORT B, BIT 5 | |
E 32 = 0x22 | Configure the Manager/Admin mode indicator LED to use PORT C, BIT 2 |
Also see: | The PrintScriptProgramHz system function, "S" command documentation and the Annunciate example program which invokes scripts. |