Fixed a bug in Select Case which resulted in incorrect evaluation of the Case statements. The problem was dependent on the state of memory.
Fixed possible source of skipped scans when using SDM instructions, SerialInRecord, or SerialOutBlock simultaneously in multiple sequences. The event used to synchronize measurement and processing in PipeLineMode was being used in SequentialMode and Slow sequences too. The synchronization is not needed in these cases because the acquisition code is called from processing. The problem was that the event was cleared prior to calling the acquisition code. If multiple threads (slow sequences) were using the event the possibility was present that the event could be cleared just after being set and prior to be recognized. This left a thread hanging until it timed out. This caused skipped scans. The fix was to wait for the event only if in PipeLineMode in the fast scan. This added additional checking for the condition. This changed all SDM instructions, SerialInRecord, and SerialOutBlock.
Added function FileSize(filehandle). Returns the number of bytes in the previously opened file pointed to by filehandle.
Added Table Output instruction Median. Median(reps,Source,MaxN,datatype,DisableVar) maintains at most, the last MaxN values of source (one for each call to the table with DisableVar inactive) and at output sorts that values and stores the Median.
Added instruction SortSpa. SortSpa(Dest,Swath,Source) requires Dest and Source to be the same type (LONG or IEEE4 are allowed) and Sorts (in ascending order) the values from Source into Dest. Source and Dest can be the same variable and the Sort is done in place. If Dest and Source are different Source is copied to Dest and then the Sort is done on Dest.
Added an instruction DataLong which behaves like Data but the data is converted as a Long rather than as a float. The Read function was changed to assume nothing of the destination type. Read just moves the data into the destination. The user must ensure that values loaded with Data go into Float variables, and values loaded with DataLong are read into Long variables.
Added String functions: Left(), Right(), LTrim(), RTrim(), Trim(), and Replace().
Added ConstTable..EndConstTable which allows constants to be grouped together to allow a keyboard/display, (and later terminal) menu to change them. This is similar to the *4 functionality of the CR10X.
Added the CRBasic '&' operator that concatenates strings, which is compatible with VB Basic.
Added bit shift operators >> and <<.
Added function FileTime(FileHandle). Returns file creation time as seconds since 1990. If failure returns -2^31.
Added function FileRename(old_fname,new_fname) where the file names are strings. Returns TRUE if successful and FALSE if not. If no drive is specified CPU: is assumed. If the drives are different the file is moved to the new location and the old file is removed. If the new_fname already exists then FALSE is returned.
Fixed displaymenu mode -3 to not show the initial screen at startup.
Fixed Move() instruction to work when the destination array overlaps the source array.
Improved to not require space between If and '(' or ')' and Then. Also applies to While and Select.
Fixed custom menu correctly showing long strings in pick lists.
Fixed resolving the type of expressions using only table.field. This was found by DisplayValue when a type other than float was used.
Fixed const strings. To conserve memory a change was made to release all constant expression memory after the constant was resolved. The problem with this was that string constants were using the expression memory space as the location for the string. A pointer to this location was later used to resolve references to the constant. With the memory freed the desired constant was no longer there. This was fixed by allocating new memory for the string alone, then the string is copied into the new memory and the expression memory released.
Fixed setting station name via SetVar (LoggerNet) if greater than 8 chars sent, restore the name back to 8.
Fixed DSP4 problem: After leaving the DSP4 off for a varying amount of time measured values would go to NAN. The problem was caused by the dsp4 routines masking interrupts too long. This caused the slow sequence switching interrupt to be missed and resulted in slow sequence measurement errors. The program being using performed calibration and BiasComp in the slow sequence. When the measurements were corrupted all other measurements went to NAN because the calibration gains were wrong. The fix was to set the interrupt mask to a lower level in the dsp4 functions, this allows the high priority slow sequence slicing to complete.
Fixed dropping ME line in CS-I/O port when recompiling a new program.
Improved auto-baud detection.
Fixed FileCopy to always remove the destination file before copying.
When out of memory error occurs while compiling, don't allow software to get table definitions. The response code of access denied is returned because the table definitions are not valid and there is no memory available to do anything.
Changed formatting drives and deleting files to nullify the power-up and run file if they are set, but the files do not exist.
Fixed Replace, Mid and other string functions when one of their parameters other than the first is an expression that includes a string function.
Fixed the CHR so that it does not use excess memory.
Improved to allow expressions of length greater than 256.
Changed TDR100 cable length parameter to accept variables and also to allow "repping" through multiple cable lengths if the () syntax is used with an array.
Fixed TimeIntoInterval(). For the case when the clock was set backward, the function returned true on the first instance of the time into the interval is TRUE.
Fixed FileControl and FileDownload stopping the current program when communicating via serial comms (CS-I/O or RS232).
Fixed RS232 Communications getting garbage bytes on input. This was caused in the receive data interrupt. Moved the check for more bytes in the FIFO to be at the top of the loop instead of the end.
Fixed TableFile when it is time to output and no records have been stored. Don't create empty file and return 0 in result parameter.
Added Predefined Constants: CR1000, CR3000, CR800, CR5000, and CR9000X. Also added predefined constant LoggerType that will be set to the same value as the corresponding constant for the respective logger type. This allows the conditional compilation to work across logger types (one program can run in multiple logger types). Example: #if LoggerType = CR3000, const MYRANGE = MV20, #else const MYRANGE = MV25, #endif
When adding a variable see if it is already used as an alias.
Added table definition output to pre-compiler.
Added Conditional compilation with #if, #elseif, #else and #endif. All expressions must evaluate to constants, but can use constants already declared.
Added FileList function.
Changed SDMGeneric to handle destination type string when numvalues > 1 and bytes per value = 1, to not give out of bounds error at compile.
Added FileCopy function. Works like FileRename (when different drives are specified).
Changed Timer function to use "system time" as its reference. This eliminates issues with being called outside Scan...NextScan, and being called from subroutines, etc., and allows timing within scans (with 10mS resolution) without disabling low power standby.
Fixed passing constant strings in subroutines. The size of the string was not correctly evaluated if it was not a variable.
Fixed If statement uninitialized variable passed into expression evaluator. This caused possible varout of bounds errors if using a variable string in the expression.
Fixed Median with reps > 0. When the end of the table was reached data was being written beyond the end pointer causing possible watchdogs.
Changed Data and DataLong to allow expressions. Expressions must evaluate to a constant.
Fixed a rare memory corruption bug caused by calling memory allocation routine requesting 0 bytes. The memory is checked two ways and if memory lined up just right the alloc of zero bytes caused the two passes to give different results for the number of unallocated blocks. This resulted in a mem fail3 error.
Added a check for empty DisplayMenu ... EndMenu, and empty SubMenu ... EndSubMenu. These were crashing the pre-compiler.
Added a new mode to DisplayMenu to not show the system menu at all. This is done with code -3. Security level 2 is used (same as setting variables from other display menus).
Changed the ^ operator to always return a float even when the operators are longs.
Changed FileClose() to return EBADFP (17) if the file handle is not valid, instead of 0 (private).
Changed Ln(X) when X is NaN or X <= 0 to return NaN instead of 0.
Added checking in all Table instructions to make sure they are not used in conditional statements. Also, added checking to catch DataInterval occurring multiple times in a DataTable..EndTable.
Changed Delay to allow variable for interval if delaying processing.
Fixed Sortspa and Median to deal with NAN's, and +/- INF. NAN will be sorted to the top of the array (most minimum values).
Changed handling of CS I/O ME line to keep ME active through a program download.
Changed handling of CS I/O ring line to deal with CR1000KD glitching the lines when plugged in. When first plugged in the CR9000X was detecting the keyboard/display as a ME device and driving ME high for 40 seconds until time out. This held off any comms to the keyboard/display for 40 sec.
Fixed CR9070 pulse count measuring frequency to get correct value on the first valid cycle. The time of the first edge was not being saved with the count.
Fixed CR9070 pulse count to work when scan buff depth is greater than 1. Previously the time values were not buffered with scan data, but rather replaced each scan. If processing got behind the time read was not correct. Now the times are buffered with the counts. This has always been an issue with the CR9070.
Fixed the problem of hanging after a DevConfig OS download. This was a Cache problem. Part of the old OS was remaining in the cache even though it is shut off and later re-enabled after the new OS was started. With a cache coherency problem the old code was executing rather than the new. Even a watchdog did not correct the problem because the cache lines remained marked as clean through a watchdog reset. Now the lines are forced to dirty (as was assumed before).
Fixed FieldCalStrain header problem when doing shunt cals with the strain source parameter set to NULL. The header was getting garbage. Now it will be loaded with a Null string.
Changed to not truncate table names to 8 characters in the status table.
Fixed setting StationName via keyboard/display and BMP setVar (used by LoggerNet Server).
Changed Keyboard/ Display Realtime Data display to deal with final storage read pointer not on a 4 byte boundary. CR1000/CR3000 can deal with reading and writing to 4byte values that are not 4 byte address aligned, but the CR5000, and CR9000X crash (watchdog) in this situation.
Fixed Select case evaluation in CR9000X/CR5000. The pointer to the case expression was defined as a pointer double. This broke CR9000X/CR5000 Select Case statements because a double in these loggers is 8 bytes not 4. This was introduced when the Select Case was changed to handle strings.
Fixed subroutine passing longs and floats to strings. The conversion to string was not correct.
Fixed converting parameters of different types in subroutines.
Translated NAN when converting from floats to ints and ints to floats.
Fixed converting Long NaN to strings.
When declaring aliases make sure they are not predefined (or user defined) constants.
Changed Histogram4D if all 4 dimensions are used then the output will be linearized. Since the OS only keeps 3 dimensions internally, the output must be linearized to successfully pass the tabledefs to LoggerNet.
Fixed Replace() function when the string to be replaced is of a different size than its replacement.
Improved FileOpen to recognizes all open mode strings that can write to files (w, a, and anything with + as the second char). Files that open for writing are added to the file manage list.
Improved to not allow the same subroutine to be called from separate processing tasks concurrently.
Fixed only getting one record from tables (if not full) using LoggerNet server.
Fixed GetRecord to a string variable, formatting FP2 values. Too many digits of precision were being printed.
Fixed Sampling FP2 into FP2 and NSEC into NSEC (using table.field as source in Sample instruction).
Fixed a problem with using Exit Sub (instead of ExitSub). If the space was missing the instruction was treated like EndSub and the parser reset a flag signaling that we were in a subroutine.
For all cases, when increment Status.VarOutOfBounds, flag a warning in the Status.CompileResults.
Fixed SDMCD16AC to work as explained in the help. When source is LONG and declared >= reps*16 then each element of source represents a port on the SDMCD16AC. Also handle reps > 1 when type is LONG and all ports on SDMCD16AC represented in a single variable (the source was not being incremented).
Changed SDMCAN to force any id's < -2047 to be 11 bit id's with 0 as the id. This avoids having to detect -0 to send id 0 with 11 bits of address.
Added checking for parameters that pass entire strings (TableName param in DataTable, FieldNames, etc.) to verify that the " (quotes) are matched. There was a case of Fieldnames with a leading " and no trailing " that was causing problems in the created data files due to a carriage return being passed on as part of the fieldname.
Added debug mode in InstructionTimes to detect out of bounds and determine which line it occurred on.
Fixed Resynchronization of time in slow sequences after time is set. Previously all resync was done in the Main sequence. Now each processing thread will detect that time has changed and re-sync on their own. The lastslowscan variable in the status table is updated with the timestamp time of the scan that is finishing when the processing for that scan is complete.
Fixed Precompiler command line option -l (listing table names and field names to a file). This is not the new full table defs functionality that will soon be added, but a feature used by the editor to show the table info.
Changed name of LookupDefine to TimedControl.
Added one tick to the delay calculated for the Delay instruction when using the RTOS to time the delay. This will delay at least as much (not less) time as the user specifies in the instruction.
Added checking to the file functions to verify that the file handle is valid before returning a value.
Fixed MenuItem displaying and editing string variables.
Added checking of the ConstTable changes before forcing the recompile of the program.
Fixed error checking for slicing in slow sequence measurements. Found cases where insufficient time remained to slice in any values. When this condition was not detected, the timing of the resulting scan was wrong.
Fixed a problem in the CF-Card driver. Code was added to avoid polling for the drive to be ready forever. An extra semi-colon caused the timeout check to always pass (i.e., timeout occurred), so if the drive (CF Card controller) was not immediately ready then an error code was returned and the file could not be opened. The effect of this bug was that an existing file on the card was assumed to not be present when it really was. The remaining bytes on the card were allocated for a file of the same name and when the file of the same name was created the old was removed. The new file was a very small file and the old file was removed resulting in almost an empty disk.
Fixed a C compiler created problem with optimization. The mt_busy variable that is incremented to lock out use of the RTOS was not getting written back to memory before other registers were loaded. If an interrupt happened between loading the RTOS variable (a semaphore in this case) and incrementing and writing back mt_busy, the semaphore was left in a bad state and all tasks but one were locked from using the semaphore. This locked up the machine. The fix to this was to use an assembly macro to perform the lock of the RTOS. Optimization will not re-order in-line asm statements.
Changed RealTime instruction to load the user array with "system realtime" if the instruction is used outside of a Scan..NextScan. The resolution of this time is 10mS (from the ticker source).
Speed up starting slow sequence scans in pipeline mode. After setting up the period for the scan interval also set the event so the first one runs. This also required handling the case of someone clearing the event before the Slow Measurement arbitrator decrements it (resulting in evt < 0).
Fixed calculating the buffer size for SDM measurements made in Slow sequences, when the measurements are not in a Scan..NextScan.
Changed the pwr function to accept non-integer exponents. Now pwr works the same as ^.
Fixed UINT2 when sampling from one table to another.
Changed terminal mode prompt from CR9000> to CR9000X> so that dev config can correctly identify a CR9032 as such.
Fixed terminal mode display of the record number to show unsigned rather than signed.
Flagged compile error if a variable is referenced with more dimensions than declared.
Fixed data collection after record number rolls over (from 0x7FFFFFFF to 0x80000000). Now works with LoggerNet, but PC9000 only collects from the rollover to the most recent (data prior to the rollover is not collected).
Updated CR9058, and CR9052 OS's to rev 04. This was due to a bug fix in the CR9052. NOTES: Fixed a bug that stopped feeding the CR9052 output fifo in fir mode after 2^31 output measurements. 231 measurements = 11.9 hours at 50 kHz. 2^31 measurements = 497 days at 50 Hz. This bug caused communications with the CR9032 to hang, leading to stack errors and skipped scans. The issue was roll-over on num_measurements_complete. num_measurements_complete will now "peg" at 2e9 counts.
Fixed recovery from? loss of signals from CR9052. With bug found above the recovery was taking 46 minutes. This was due to having to finish all subscans before realizing there was a problem. The check was moved closer in the loop so that detection and hence recovery is quicker.
Fixed a problem loading OS's to filter modules. Two OS loads were required to get the new code into the CR9052. This was due to not waiting long enough after completing the file load for the response from the CR9052.
Improved Select Case to allow strings.
Improved Running Average so that NaN to go thru the buffer, but still not using it in the average valuation.
Improved FieldCalStrain: added gf_raw (raw gage factor), gf_adj (adjusted gage factor), and strain (the output from the strain calc) to the header information. This required adding the strain_calc parameter to the instruction (it is the last parameter).
Removed the program file from the BMP get compile results. This is loaded into the status compile results string now so adding to the download response was redundant.
Changed LoadFieldCal when creating a new file to load the file with the current values of all variables in the file. This allows the user to do initialization and then execute LoadFieldCal and have their initialized values be loaded the next time the program starts if a calibration is not done to load the file via FieldCal.
Fixed ASCII instruction to convert character as an unsigned rather than signed value.
Fixed SplitStr calculation of the end of the input string. The incorrect calculation was causing variables beyond the input string to be overwritten.
Fixed WindVector output option 3 causing memory corruption. Option 3 was updating values that it should not have been and overwriting memory.
Fixed parsing TableName.FieldName for long names (> 28 characters)
Changed GetRecord() so if it tries to return records that do not exist, store NAN (or null string) instead of leaving the destination variable alone.
If out of memory while compiling just hang and let comms get compile results to avoid using NULL pointers.
Fixed converting floats to Longs for instruction parameters that required a long ( DOUBLEtoLONG_END ).
Changed Timer() function to allow variable timer number and fixed so compiling will not crash if a variable is used for timer number.
Fixed parsing constant integer parameters of functions to consistently give a compile error if a variable is used instead of a constant.
Fixed parsing strings to allow multiple ';' within the string.
Fixed SDMCD16AC working in lookup mode to not advance the event that synchronizes with processing (because no processing runs in lookup mode).
Fixed a data collection problem. When using a card and the CPU has filled, allow the search to go back the full size of the CPU (numrecs + extra lapse records). There was a case found where the CPU numrecs was 10 (even though it really had room for 30 with lapses), the card had written 20 records and a total of 31 records had been stored. When collecting this table the collection got stuck at 20. The first 20 records were retrieved from the card, and the algorithm for searching the CPU only allowed records 22..31 to be retrieved (the most recent 10 records). This left record 20, and 21 in no-mans land (i.e., there was not enough records buffered to write to the card and the search algorithm would not allow going back more than 10 records in the CPU).
Fixed SortSpa and Median. Algorithm for sorting was going out of bounds, and under some conditions only sorting part of the array.
Changed wind vector so that if the resultant mean wind speed is output, it will use the same units as the mean wind speed (when FieldNames() is present).
Fixed units on output instructions when there is fieldnames to look for the alias name units also.
Fixed showing table names in terminal and keyboard/display when > than 8 chars.
Changed Histogram, Histogram4D and RainFlow to load NAN in processing string if the parameter is not a constant.
Changed FieldCal so if it has reps of zero then don't return error code (just don't do anything).
Fixed aborting a BMP comms RPC midstream. When loading a file that requires multiple BMP packets and the filename is too long, aborting the transaction with LoggerNet was not working properly. With this fix the message code for invalid file is returned immediately after the first packet. This causes LoggerNet to abort the download, and report an error.
Changed Histogram, Histogram4D and RainFlow to load NaN in processing string if the parameter is not a constant.
Changed GetRecord to allow a variable index into an array for the dest.
Loaded a warning message if variable out of bounds occurs during run time. Only one message is loaded. This allows the user to determine which var is going out of bounds.
Fixed error message when scan interval is too short. The line number was associated with the next scan not the one with the problem.
Fixed CR9058 in superscan restarting after skipped scans or time set.
Fixed TimerIO with constant all done flag to give some time to other tasks in case no incoming signal is active. The priority of the task is moved up and a poll interval is set up at 10uS resolution. When the event occurs the priority is returned to normal. The priority must be moved up so that we don't get swapped out and not return for a long time (this gives occasional invalid frequency measurements due to jitter in the polling interval).
Fixed using bad pointers for measurement slicing when a skipped Slow scan in pipeline mode occurs. One discovered symptom of this bug was the loss of time. The Slow sequence had to be making measurements and the processing time had to be long enough to skip scans.
Allowed BOOL8 data type in Data Table
Changed FileReadLine() to return -1 when at the end of the file.
Fixed Replace() function to make sure it has enough room to hold the resulting string on the stack.
Changed TableName.FieldName access when returning Time of Max or Time of Min. 1) by default return seconds since 1990 instead of Usec since 1990 (this avoids overflow of 32 bit integer). 2) if the FieldNameIndex (first parameter in Table.Field(x,y)) is < 0 then Usec into the Sec will be returned. Also changed GetRecord to return times as Sec since 1990.
Changed TableName.FieldName when returning integer type (LONG or Time) and storing into a Long. Code was added to avoid returning a float and then converting back to integer (and thereby possibly losing resolution).
Changed FieldCal to avoid propogating NANs into Multiplier and Offsets. If the incoming Offset is NAN it is changed to 1 prior to the Calibration calculation. If the Multiplier is NAN or 0 it is set to 1 prior to the calculation.
Added terminal mode way to reboot (recompile) a program. This is done by typing "reboot" from the terminal prompt. There is a one second timeout between each character to avoid inadvertently entering this mode.
If using table.field and reading a time of max or time of min into a string variable, convert the time to timestamp form rather than integer of seconds since 1990. Also, when returning time of max or min convert to unsigned integer rather than signed, then convert to the user requested type.
Allowed reps to be a variable in FieldCal. At run time return an error code if reps is not set to 1 or the fill size of the declared array. This allows zeroing (or calibrating) all sensors in an array or a single sensor.
Fixed SampleFieldCal to work with FieldCalStrain.
Fixed InstructionTimes() so that if the line number is 0 it will not write into a previously declared variable.
Changed DataEvent so that it writes its own LineNumber since it does not pass its own structure back to the compiler.
Allowed reps to be a variable in FieldCal. At run time return an error code if reps is not set to 1 or the fill size of the declared array. This allows zeroing (or calibrating) all sensors in an array or a single sensor.
Fixed SampleFieldCal to work with FieldCalStrain.
Changed so if unable to open drive for Run/Stop program then nullify power-up and run now programs if on that drive so it can be formatted.
Improved so after editing a program via Keyboard/Display the run now program was not being changed correctly.
Fixed communications on RS232. Input driver was occasionally loading a bogus character into the buffer which caused CRC checksum to fail and comms to stall. Restructuring the Rx interrupt fixed this.
Added FieldCalStrain for zeroing and shunt calibration of strain gages.
Fixed retrieving public and status tables via data collect when record number exceeds 2^31-1.
Fixed compiler crash if using a variable in a parameter that expects a constant.
Fixed parameter passing in subroutines using strings.
Fixed Compiler crash if no subroutines are defined and a Call subname is used.
Reject downloads of files with names longer than 31 chars (no more room in non-volatile memory for Run now and run on power-up program names).
Fixed compiler crash if using a variable in a parameter that expects a constant.
Fixed parameter passing in subroutines using strings.
Improved to not allow format of device that holds the run now or run on power-up file. This is the same functionality as the CR1000.
Improved to not allow old OS's to use the CPU drive after it is formatted FAT32. Also, newer OS's will not use old FAT CPU (it will be reformatted).
Fixed CS I/O comms to SC32B. The SDE line was left high after determining that an ME device was connected. This messed up the SC32B.
Fixed Compiler crash if no subroutines are defined and a Call subname is used.
Changed FieldCal: 1) Made NumAvg a variable. This required adding another field to the header line information. The NumAvg field will contain a variable name if a variable is used, and a value if a constant is used. Also required changing the keyboard/display GUI to prompt for a value if NumAvg is a variable. 2) Add a field in the header first line to tell software how many total lines to parse (fieldcals + aliases). 3) changed the header version number to 2.
Fixed setting up data pointers for the card when power is removed immediately after a flush. This was causing data to be out of sync in the file. CardConvert was able to get the data back in sync, but it required the user to use the recover option.
Fixed parsing parameter strings that have ';' character in them. The semicolon is used to delimit parameters internally by the parser. It is actually inserted into the parameter list and later parsed out. If a string with an intended ';' character was parsed an error occurred. The parsing was changed to limit the search for the the ';' to only take place outside of strings.
Added Signature function. Returns a number 0..65535 that is a Campbell Scientific pseudo random signature of the CRBasic code and then reinitializes the signature seed to &HAAAA (43690). This allows the user to make sure different sections of the program have not changed. Notes: 1). The signature will not be active until the first occurrence of Signature, in order to avoid taking signatures when not needed. Therefore, the first use of Signature will always return 43690 (&HAAAA). 2). Blank lines and comments are not included in the signature.
Added Include "drv:FileName" declaration.
Fixed PC compiler to correctly find and open Include files. It assumes the file resides in the same directory as the main program file.
If a compile error occurs in a Include file, then the error message will have: line: error. The editor will need to be changed to support going to the line number of the correct file.
Fixed parsing subroutine parameters. Check to make sure parameter expression is not all whitespace before parsing it.
Changed functions that push pointers on the expression stack to have their own opcodes to do so. Previously bits were set in the opcode to load a pointer rather than a value.
Changed all functions that return integers rather than doubles to handle return differently.
Deal with Alias for FieldCal measurement variable. The list of aliases and their index in the array is added to the header file for the Calibration wizard to parse out.
Removed limitation of 8 parameters in subroutines.
Fixed real-time graphing in scope mode. The value in the upper right was getting garbled. The user-entered max and min values for the screen are adjusted so the all values in the range will fit in a reduced screen that will not overwrite the values on top and bottom. If the graph goes out of this range then the values will be overwritten and there is a "dead" space in the upper right by the current value where no pixels will be written.
Changed SplitStr() so that quoted strings are optionally handled by keeping text inside the quotes in tact.
Fixed sampling table.special_field(1,1) into data tables. For this to work the table which you are sampling from must be previously declared. The special fields are: .OUTPUT, .RECORD, .TIMESTAMP, .EVENTEND, .TABLESIZE, .EVENTCOUNT, and .TABLEFULL.
Increased the allowable table name length to 20 chars.
Fixed powerup.ini processing to not continuously load OS.