--- title: "VDAQ – A Data Acquisition Development Program" type: "article" slug: "vdaq-a-data-acquisition-development-program" url: "http://localhost/article/vdaq-a-data-acquisition-development-program/" markdown_url: "http://localhost/article/vdaq-a-data-acquisition-development-program.md" published_at: "2025-08-02T14:27:51+00:00" modified_at: "2026-06-21T23:20:18+00:00" featured_image: url: "http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0068-1024x892-1.jpg" excerpt: "Here is a program that demonstrates a simple yet effective way to get analog information (data) into your ZX81/TS1000/TS1500 computer, with a minimum of additional hardware. Also included are various plot and display routines so you can get visual and printed output of your acquired data. Along the way it will show you various \"tricks\"…" category: - name: "SyncWare News" slug: "syncware-news" taxonomy: "category" url: "http://localhost/category/periodicals/syncware-news/" post_tag: - name: "Down East Computers" slug: "down-east-computers" taxonomy: "post_tag" url: "http://localhost/tag/down-east-computers/" - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "Hardware project" slug: "hardware-project" taxonomy: "post_tag" url: "http://localhost/tag/hardware-project/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" - name: "Type-in program" slug: "type-in-program" taxonomy: "post_tag" url: "http://localhost/tag/type-in-program/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Fred Nachbaur" slug: "fred-nachbaur" taxonomy: "indiv" url: "http://localhost/indiv/fred-nachbaur/" publication_r: id: 10245 title: "SyncWare News" type: "periodical" url: "http://localhost/periodical/syncware-news/" authors_r: - name: "Fred Nachbaur" slug: "fred-nachbaur" taxonomy: "indiv" url: "http://localhost/indiv/fred-nachbaur/" volume: "1" issues_articles: - id: 38991 title: "SyncWare News v1" type: "issue" url: "http://localhost/issue/syncware-v1/" pages: "63-72" pubdate: "1984" product_reviews: - id: 14536 title: "VOTEM" type: "product" url: "http://localhost/product/votem/" archive_link: false companies_articles: - id: 10825 title: "Down East Computers" type: "company" url: "http://localhost/company/down-east-computers/" article_media: - id: 51396 title: "VDAQ1-HR" type: "computer_media" url: "http://localhost/computer_media/vdaq1-hr/" --- # VDAQ – A Data Acquisition Development Program Here is a program that demonstrates a simple yet effective way to get analog information (data) into your ZX81/TS1000/TS1500 computer, with a minimum of additional hardware. Also included are various plot and display routines so you can get visual and printed output of your acquired data. Along the way it will show you various “tricks” and other tidbits that might help out in your programming. A little background is in order. My original intent was to write a “universal” data acquisition program for the popular “[VOTEM](http://VOTEM)” analog interface. “Universal” is a pretty broad term, though; it didn’t take me long to realize that a truly general program would be difficult to implement in 16K. A better approach is to write a number of customized programs, each tailored for a certain range of applications. If nothing else, possibilities for display and printer formats are almost endless, not to mention ways in which the data may be processed once acquired. So what I’ll try to do in this series of articles is to present some “basics” from which you can expand to suit your application. In this issue I present a complete program which will sample data at a rate from about 1 sample per sec. to about 350 samples per second, with resolution between 8 bits (fastest sample rate) and 14 bits (slowest sample rate.) It can store 2048 discrete samples, each one consisting of two bytes. Data is organized into “screens” of 64 samples. Each screen can be acquired/displayed individually, or several screens can be chained for longer timebases. As listed, the capacity is 32 screens, but you can easily make this more or less with simple changes. TS2040 printer is supported, and you can even do “side-winder” plots with a vertical resolution of 60 points and length (width?) depending only on the number of screens plotted. Plot limits are easily changed, and screen plots are done in machine-code for speed, Since this program is optimized for speed, no data display occurs during acquisition, and there are no additional pause routines for longer time-bases, This will be the topic for the next issue. But for now, let’s backtrack a little and look at how the hardware works, and then at what you’ll need, hardware-wise, to make the software work. ### Theory There are several ways to get analog data into a computer. The usual approach is to use an analog-to-digital converter; such devices have at least one analog input channel, and a digital data bus for output. The binary number appearing at the data bus is proportional to the voltage at the analog input. Converters are available to give a resolution anywhere between 8 and 14 bits (15 bit with a minus sign is present “state of the art”; that’s 4 significant figures. ed.), depending on the accuracy required. Eight-bit converters are relatively easy to implement on an eight-bit CPU like the Z80, since the data can be impressed directly onto the CPU’s data bus. For higher-resolution A-D’s the acquisition has to be done in two “chunks,” using some decoding scheme to first look at the first 8 bits of the output bus, then at the remaining bits. In either case, the page to start a conversion can be either I/O or memory-mapped. The resulting data is then loaded into memory for subsequent display and other processing. With all its advantages (mainly speed) this approach does have a few drawbacks. First among these is that it requires connection to the computer’s data bus (8 lines) as well as to at least part of the address and control busses (lines like MREQ, IORQ, RAMCS, etc). Another drawback is that matters start getting quite complicated if greater than 8-bit resolution is required. Because of all the circuitry needed, most folks would prefer simply buying a commercial module rather than mess with all those wires, decoding, timing circuits, etc. See the [Ener-Z](http://localhost/company/ener-z/) [Report Generator](http://localhost/product/report-generator/) review elsewhere in this issue for an overview of one such package. Another is the [Computer Continuum](http://localhost/company/computer-continuum/) “(8+8)*8” A-D, D-A board (reviewed in a future issue.) There is another route we can take if high speed (faster than about 300 per second on the ZXTS) is not of the essence. It is an old method, but still very useful. In this method, the voltage is first converted into a stream of on-off pulses whose frequency is proportional to the input voltage. Such a device is called, aptly enough, a “voltage-to-frequency converter,” or more simply a “V-F.” Now all that is required is a single IN port bit to get the stream of pulses into the computer, It is a serial rather than parallel approach. Your ZX/TS has a dedicated input port already the EAR jack. A single Z80 IN A,(FE) command gets the state of the EAR jack input in bit 7 (the most significant bit;) from there it is a simple matter to write software to count how many pulses (state changes) appear during a fixed time span – the resulting count will be proportional to the input voltage. By appropriately modifying the IN command, this approach will work with any computer with an IN port such as a cassette input. Calibration can be done entirely in software, making the hardware aspect simple indeed. V-F converters almost always use a circuit ealled an “integrator,” which provides an output voltage proportional to the integral of the input voltage. This means that the higher the voltage to the input, the faster the output from the integrator will ramp up (increase). This signal is applied to a comparator, and when it exceeds the comparators upper trip point the comparator toggles (changes state), at the same time resetting the integrator. Result – the higher the input voltage, the higher the frequency of the pulses at the output of the comparator. See Figure 1. This is called “single slope V-F conversion.” Also possible is what is termed “dual-slope conversion,” in which the conversion is done in two steps; a known reference voltage is used to ramp the integrator up, and the unknown voltage is used to ramp the signal back down. The ratio of the ramp-down time to the ramp-up time equals the ratio of the reference voltage to the unknown voltage, from which the unknown voltage can be easily derived. The dual-slope approach is more immune to drift and other inaccuracies, and allows “auto-calibration” in dedicated devices like the ubiquitous Digital Volt Meter (DVM). (Virtually all inexpensive DVM’s use some variant on this approach – as I mentioned earlier, we’re not dealing with anything new and esoteric here.) When using V-F data acquisition, accuracy depends on the “acquisition interval.” This is how long we are counting, and therefore how many counts we read for a given input voltage. If “full-scale” (the highest voltage we wish to measure) only returns 256 counts, we get 8-bit accuracy; but if it returns 16384 counts at full scale we have 14-bit accuracy. So you see that the more accurate you want it, the longer you’ll have to sample the input pulses. How fast you can go depends on computer speed; on the ZX-TS it takes about 1 second to get maximum resolution (better than 14 bit, or about -005%). At the other extreme, we can get 8-bit resolution (about .5%) with acquisition times down to a few milliseconds. In this program we’ll experiment with the relationship between speed and accuracy by making the acquisition interval equal to the sampling interval; as soon as one sample is acquired, the program goes right on to the next, with no additional timing pauses. Timing is varied by changing the acquisition interval; as a result, the full-scale count and the number of counts per volt changes with sample-rate, and has to be compensated for when converting the counts into voltage or other units. Next time we’ll add programmable pauses so the sampling interval is greater than the acquisition interval for longer time-bases (minutes, hours, days). This will also allow time to update a continuous display during acquisition. You are encouraged to customize and improve these programs from there, to come up with exactly what you need for your application. What applications can it be put to? Well, just briefly mentioning some of the possible input devices should help suggest plenty of ideas. You could use a potentiometer for position sensing (simple robotics, wind or antenna rotor direction indication, ete.), a photocell (light meter, etc.) or a strain transducer (for forces, stresses.) Use a microphone as the heart of a decibel (sound level) meter, Let’s not forget about temperature probes, for clinical/ meteorological “thermographs,” solar heating control, or heat-transfer studies. For some uses you won’t even need the V-F, The obvious example is as a frequency counter (this program will handle frequencies from about 2 Hz to about 20 kHz.) Similarly, you won’t need the V-F for such things as radiation monitors (just run a Geiger counter output to the EAR jack and have the computer count the pulses. Use Tom’s moving-trend routine to smooth the data as required.) A final point before we get on to brass tacks is that the V-F approach lends itself very well to remote sensing; you can locate the V-F with the sensing device, and bring the data to the computer along a single digital line (use a comparator for cleanup at the receiving end if needed.) This is much more accurate and free of glitches than running a long analog line, and is cheaper and easier than bringing the data in on parallel data + control lines. But now that I’ve firmly convinced you that “you NEED this program,” let’s take care of the hardware aspect, and then briefly go over the system software (the fun part). [![Image](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0068-1024x892.jpg "SyncWare News v1n1-6_0068")](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0068.jpg) ### The Hardware If you have a ZX/TS with 16K RAM and a VOTEM analog interface, you already have all the hardware you need, If you don’t have a VOTEM, you should consider purchasing either a complete or partial kit (any combination of bare board, documentation and V-F chip). (they are still available, ed.) Down East Computers! prices are not out of line, and their unit is the best approach if you’re not willing ot build a V-F board from scratch. For those of you who don’t mind a little hardware hacking, I’m printing a “rip-off” circuit for the LM331 V-F chip, derived from the National Semiconductor application notes for this device. It is accurate, inexpensive, and quite readily obtainable (if you can’t find it a your local jobbers’, check with the nearest location of Avnet/Hamilton). Values shown are for a 1 volt full scale sensitivity, you can easily sense higher ranges by preceding the V-F with a resistive voltage divider. The absolute precision of the other parts is non-critical, since we’ll calibrate the final circuit anyway (using a software scale constant). What IS important is that the timing parts be stable with temperature; the timing capacitor should be polystyrene or polycarbonate, and the resistors should be metal-film. Avoid extreme temperature changes around the V-F board if possible. Wiring is non-critical, and you can use wire-wrap on a perf board to do the actual construction. You can power the V-F from the computer supply, or use a small battery (especially recommended if you’ll be locating the interface remotely). You can use the Radio Shack 276-1790 V-F, F-V IC. Applications notes are provided with the part. (Though we won’t be using it, this unit also allows you to convert from a frequency back to a voltage you could conceivably work up a circuit which will translate a frequency -such as you can make available at the MIC jack- into an analog voltage, which can be used to control such things as proportional heaters, motors, etc. More about this in a future installment.) If you’re using a VOTEM, you should disconnect capacitor C8 at the input to the V-F, or replace it with a much smaller unit (eg. DL uF), otherwise you’ll get considerable waveform distortion due to its filtering effect. (A 20 Hz. square wave won’t look the least bit “square.”) Whatever V-F circuit you use, the maximum output frequency should be limited to about 25 kHz. At higher frequencies you’ll rapidly get inaccuracy due to “strobing” effects, since the rate at which the sampling loop runs is about 65 kHz. The amplitude requirement is that the “on” voltage should be 2-5 volts, and the “off” voltage should be a few tenths of a volt maximum. Duty cycle (ratio of on-time to total cycle time) is non-critical, but shouldn’t deviate too far from 50% for best results. Run the output to the EAR jack, and the hardware and interfacing is complete. The Software In order to be able to present the entire program in one installment, I’ll have to gloss over some “fine points” regarding the program this time. This is perhaps just as well, since what you learn on your own is much more likely to stick than what you read. Instead, I’ll concentrate on how to get the program entered into your computer, and on how to use it once it’s debugged and safely on tape. Thus you’ll have something to play with while we’re working up the additions and improvements for the next episode. You shouldn’t have much difficulty entering and debugging it, and you can use any of several different ways to enter the machine-code portion. ### The Machine Code First you have to enter the machine-code. Start with the usual line 1 REM statement, 407 bytes long. Use a toolkit or enter it the “hard way,” one character at a time. Another way of doing it is shown in the listing for line 1 in the BASIC listing on page XX. Enter 1 PRINT 9 followed by 50 repetitions of +0. The computer interprets each zero as a floating point number – so it uses up six additional bytes for the binary representation of each zero. The first 0 takes 7 bytes, each +0 takes 8 bytes. We’re using the ZX’s extravagant number storage to our advantage, requiring only 101 keystrokes to enter 407 bytes. Note that this won’t work using 1 REM 0+0+… because after a REM, the zeros are interpreted as characters (1 byte each). So use PRINT, then change the PRINT to a REM using POKE 16513,234. However you get the REM statement in there, you can check that you have the right length by entering PRINT PEEK 16921, which should return 118 (end of line marker). If you want to make line 1 more resistant to accidental deletion, POKE 16510,0 to assign it a line number of zero. Now enter a decimal loader as on page XX, setting the counter limits (in line 10) FOR A=16514 TO 16843, and use the values shown in the decimal table. Or use a hex loader or assembler and enter the program from the Hot-Z listings. The locations from 41CCh (16844d) to 41D7h (16855) are machine-code variables, and need not be entered. Similarly, the 64 bytes at 41D8-4217h (16856-16920d) represent a machine-code “array”, which holds the “timing value” for each screen. If you want more than 32 screens, make the original REM longer – e.g. for 40 screens, add two more “+0″‘s (16 bytes). This timing value is the number that is loaded into 409C-409Dh (16551/2d) in the acquisition routine, which determines how many times the program loops to take another look at the state of the inport bit 7, and sets our acquisiton interval or “window.” The first three routines are nested loops; MULTISCREEN calls ACQUIRE A SCREEN, which calls ACQUIRE A POINT. You could save some time between samples to improve accuracy as low timing values by writing it as one routine, but I left it as shown to make it a little easier to follow. The acquisition routine is a slight variation on the routine supplied with VOTEM. The next routine gets the start address of the specified screen being written to/read from. The data is stored in the first BASIC variable, D$(4096), which has to be twice as long as the total number of points, Although the array is actually organized as 32 screens of 64 2-byte points, DIM D$(32,64,2) or DIM D$(32,128) will not work with this storage system, D$ must be single dimensioned. The next routine draws the axes MUCH faster than any BASIC loop could, especially for the vertical axis. The rest of the code is the data graphing program, consisting of an arithmetic package (so we can do 16-bit by 16-bit division) which is called by the plotting routine to evaluate each “position. The arithmetic package is a portion of the run-time package of [Bob Berch’s](http://localhost/company/bob-berch/) [ZX COMPILER](http://localhost/product/zx-compiler/), and is actually more than we need here, as it also contains multiplication, ABS, SGN and other functions. It was used here to demonstrate that a compiler (especially Bob Berch’s, of [Cinagro Software](http://localhost/company/cinagro-software/), 19 Jacques St., Rochester, NY 14620) is a very worthwhile thing to buy even if you’re more interested in hand-assembly; you can find many useful routines in the run-time package that will save you time in assembly by giving you function utilities to call when needed. Stay tuned to SWN for a significant article by Bob which shows how you can drive a serial printer from your MIC jack meanwhile, make it worth his while to submit this article (and otherwise keep supporting your machine) by ordering his compiler or other programs. If you wish to get graphs dumped to your Centronics printer via Memotech CIF, you have to enter the print buffer and conversion table as per SWN 1:3, then enter the machine-code of this program into a line 2 REM statement. It will be displaced by 348d bytes, starting at 16862. You will have to change (offset by 348) all CALLs and references to machine-code variables or use Hot-Z Ii to relocate it for you. You’ll also have to change routine addresses in the BASIC, and add the screen-dump given in 1:4 to replace the COPY command. [![Image](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0071.jpg "SyncWare News v1n1-6_0071")](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0071.jpg) ### The BASIC Once the machine-code is in, the BASIC should present no special problems. You might want to rearrange the menu options – e.g. put “Initialization” as option 1 and start it at line 1000, put “Acquire a Screen” at option 2 and start at 2000, or however you want it. Though the BASIC listing is only 2 pages long, there’s quite a lot going on here, including some “frills” you could do without (like the pseudo-INPUT routine at 8000, which inputs 2 digit numbers without pressing Enter, or 1 digit numbers using Enter). When using RUN for the first time (after SAVEing in case you have bugs in the machine-code), the program goes to the initialization/ calibration part of the program. You have to calibrate first voltage (calibrating the V-F) and then the time-base (calibrating the computer). Use a voltage close to full-scale, and monitor it with an accurate DVM while pressing Enter. The reference to “switches 3, 6 and 7” refer to VOTEM, in which this connection measures the 1V reference built into the V-F. The display will disappear for about 1 second, then input the measured reference voltage. The program prints the observed count and counts per volt (at the longest timing value possible). Then you have to time how long it takes to acquire a screen of 64 points; it will be between 60 and 66 seconds, depending on the speed of your particular machine. Enter the actual time, and the computer is calibrated for time-base. When acquiring data, you have three options for starting the acquisition; by pressing a key (option “K”), when the input frequency becomes non-zero (press “N”) or when the input frequency goes to zero (press “Z”). You may have other requirements, which you should be able to program if you study how these options work. #### Some Important Variables Here are some of the crucial variables in the program. Some (like R, CL, C0) are also machine code variables: the address is shown where applicable. - VREF – full scale calibration value - C – counts at VREF. C0=65535 (later a tem. var.) - C1 – counts per volt at C0=65535 - C0 – (16540-41) Timing value (number of acquisition loops). C0=65535*TB/TREF. Stored in CO array for each screen. - TREF – Time required to acquire 1 screen at C0=65535 - TB – Time-base for 64 acquisitions (1 screen) - SR – Sample Rate (mSec.)=1000*TB/64 - CM – counts per volt (or kHz.)=C1*C0/65535 - CL – (16852/53) Count at lower plot limit (=PL*CM) - CH – Count at upper plot limit =PH*CM - R – (16850/51) Plot ratio =(CH-CL)/(max. y val.) Y-position given by (count-CL)/R - PL – value at bottom of graph - PH – value at top of graph - DP – order of magnitude of accuracy (for # of decimal places) Operation of the rest of the features is pretty straight-forward, and the prompts should help. When doing a side-winder plot, you might save paper if you first do a “dry run” (prints to screen only) to make sure your data doesn’t go off scale. Multi-screen acquisition and display asks first which screen to start at, then how many screens the acquisition is to run. Obviously you can’t acquire more screens than you have available after the starting screen. The program then loads the timing value into the timing value machine-code array for each screen involved. (Assures correct scaling for each screen when plotting and printing later.) Line 9999 shows an interesting option to the STOP command, first reported in [SYNAPSE](http://localhost/periodical/synapse/) (Central PA Users’ Group). Look ma, no report code! Verify that the program indeed has stopped by pressing Enter or LISTing. Another tidbit is demonstrated in lines 20902210 and a couple other places, S1 and S2 are the two bytes of the SEED variable which is set by RAND. This is a great way to convert a decimal number (e.g. R) into two-byte form; just RAND R, and then PEEK 16434 and 16435 to get the high and low bytes for that number. One warning – it doesn’t work with zero, since RAND 0 means the same as RAND – ie get the value currently in the FRAMES variable. So for the low-count variable CL (count corresponding to the bottom of the screen) we have to use another approach (lines 2120-2130), as this variable may be zero. I first saw this programming device in [Ralph Coletti’s](http://localhost/indiv/ralph-coletti/) newsletter (no longer being published,) though it has also appeared in a couple other publications, Lines 4-7 restore the program listing cursor and the top line in automatic listings to line 8, in case you list line 1 and the automatic listing gets stuck. These POKEs can be done in the immediate mode also. When printing the data values, the program takes the acquisition interval into account and shows you only as many decimal places as you can expect for that acquisition rate. You may wish to change the display format; this routine prints a two-column listing specifically with the TS2040 in mind, but is a little awkward for “screen-only” data display. Likewise, you might come up with a faster side-plot approach, perhaps using a m/c routine similar to the single-screen plot. Other challenges: – write additional lines in the printing routine to compensate for the non-zero time between acquisitions. Modify the program to VREF work with [Nissim Elmaleh’s](http://localhost/company/nissim-elmaleh/) Software-only Hi-Res or [Russell’s](http://localhost/company/g-russell-electronics/) HRP hi-res printer package, or with Memotech HRG or other hi-res hardware package. Translate the program for use with the TS2068 shouldn’t give much trouble, though upgrading the display routines to hi-res might give you a challenge. Work out the machine-code to plot quantities with negative slope factors (such as most temperature probes.) Above all, have fun with this! [![Image](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0069.jpg "SyncWare News v1n1-6_0069")](http://localhost/wp-content/uploads/2025/08/SyncWare-News-v1n1-6_0069.jpg) ## Source Code: VDAQ1-HR ``` 0# NEXT CLEAREP#)5 ▘T#5[V]RND FAST 5[2]RND DIM [2]RND DIM GOSUB # GOSUB # CLEAR;~~ RETURN COPYC,,▀ GOSUB # GOSUB #Y CLEAR DIM ▘U#Y= GOSUB # CLEAR DIM GOSUB # GOSUB #[B]▘# E(RND GOSUB PI CLEAR5 RNDY2 GOSUB #ACS UNPLOT ▘▘▀Y INPUT ▘▘▀ GOSUB # CLSY<> DIM /[7] UI# RETURN ""5 IF # FASTQ#7Q CLEAR7Q FAST7Q LPRINT 7Q#7Q DIM Y DIM )5 ▞[I];#( UNPLOT Q LPRINT 7#[J] LPRINT FAST). GOSUB #ACS UNPLOT 6P#Y▘MI# LPRINT 6£RNDTAN 5I#ACS #""INT ? 5I#ACS #COS ACS ▚E(RND▘;▀[J] GOSUB PI GOSUB #£RND6£RND FOR Q TAN 2▘/▝2 RETURNLN AINKEY$ GOSUB #RNDRNDY[H][)]**STR$ ##ACS SACS SACS S[J]#***[>]LEN ▒#+C▖ACS ▀/ RAND STR$ LN [D]INKEY$ GOSUB #R#, FASTE[Y]#ACS [1]#▗▗▗#""##,,ACS >[3][I] LPRINT SGN AT ACS INKEY$ 4▀[7]/▘[N]/RNDVAL # NEW SAVE [)] GOSUB #5T##▐###A 0DDDDDD▞ #,,▘[J]#,,AT FAST GOSUB #[Y]#[J]#####DDDDD,,;2▞; GOSUB #£RND;6R# LPRINT TAN RETURNINKEY$ S▝ PLOT "": ACS #C▀J:█- #;#R#>TAN LN AINKEY$ GOSUB #RNDRNDY3[(]**Y[H][)]#**2▘LN [D]INKEY$ U5RNDLN DIM INKEY$ TAN LN SCROLL▝LN [Y]PI# LPRINT RND EJ#/▀EL#6N#EDRND▘▌ ,, GOSUB #RNDRND GOSUB #F#4=7UF#CHR$ ▒MF#MRNDRNDUG#MINKEY$ RND/ SLOW7 FAST▘ ▒ACS #C▝:▘VAL A NEWZ#DDD GOSUB #N#; FOR AT UO# RETURN2,4▝ACS ZACS INKEY$ C▘JM5RNDVAL STR$ LN ▛PISGN AT <5RNDRNDP( STEP 5INKEY$ RNDOACS #4,,UF#MRNDRND LPRINT /[/]URNDRNDMF#UG#MINKEY$ RND LPRINT /[,,]) SAVE #5 FOR PI#7#5 SLOWPIQ-54#) 7 FAST RETURN[7]4▌5 SLOWPIQ+▞+5▒▘; FOR 5 #;#VAL STR$ FASTSGN <▘3 GOSUB [K]SGN AT ( CONT E FOR PI)5 ;6 FOR PI LPRINT /VAL 5INKEY$ RNDQ▝Y[E]M2#5RNDRND#LN #INKEY$ U2#X RETURN,,C▝/ GOTO Y3M2#5INKEY$ RND#55RNDQ 5RNDRNDQ~~LN ▛PI55RNDQ TO 5RNDRNDQ"LN ▛PIU2#XC▝/NOT 55RNDQ TO Y M2#5INKEY$ RND#5RNDRNDQ,,LN ▛PI5RNDRNDQ#LN ▛PIU2#LEN ▘ S▝/ THEN55RNDQ 5INKEY$ RNDQ 5RNDRNDQ~~LN ▛PI5INKEY$ RNDQ 5RNDRNDQ[E]LN ▛PITAN ▞ ACS (#[-]INKEY$ 5 #C▀LEN █#7/ PAUSE U3# RETURN COS Y M3#/$ U3# RETURN▘COS Y▘M3# ▞# GOSUB #(RND FOR PAUSE ,,AT / POKE 7#7#7))#7<"#[L]COS / PAUSE COPY ▌O[3]*▀R7H COPY# COPY-# 2S# 2 TO TAN ##=0=▞:▞=> COPYE£RND▘▞ ,,LN SCROLL▝<>5T#)▘=[J]PEEK CLSLN #?S▌3PEEK CLSINT £<= CLS▗K LET ACS #4###7ACS #49 FAST#ACS GACS B▗▗ACS =▄#ACS )[3][I]#▞▒[J]ACS ▘3#<= CLS3K CLS#PEEK CLS( LET LPRINT /USR RETURN LPRINT C<<= CLS3K CLS0ACS [.]<>7<># ACS #C[D]/[4]VAL # AND ▒▌I,GJ▝[V]2[~~]$[U]?[F]▝[V]2[E]$[5]W;R[X][A][~~]?)?[~~]W[T]7S8+COO[X][A]6"((OK[N]K6:[5]W[B][A][X][A]6?[T]Q[T]7[T]7HO[4]BM£ZJ▙;YJ8JIJ8[W][7][5][5]([H][V][~~]TI▀[~~]█I▀[~~]0??9X[3][V]9F++▌█+▌▌F?[N][7]XD[V]=F[E][N][N]█[E])[6]6[3]J0[L]UK[R][L]▝W/W,W[S][L][V]▘[O][O]X5[6]5MY//,Y[S][I]4▌GCX["][6]CQ[7]=)[;]HHHZGGGX[6][6]$9TT$[;][;][;][I]8*[Q][9]5[C]Z66-344/[U]/▗L[P]▚E.[£]D▗[2][P][P]▗X▗,▗~~GKGK[£][R][B]W[H]J7S(S[N]~~[H]▚▚[R][£][R][R]W[H],V,,,["]"▀[T]▒▒£C£[7]▜)[V])[0]▙[7]█[M])[F][R][~~]["]6H▜["][V]D[0]["][7]█ZXU[R];[R]6[R]K(/?[Y]?[R]█[+][F][F]D[2][J]6HQDDD[Y]███GRO[+]5£[V]N[V]Z/▞▛N/B[V]Z?[W][W][<][<]"▛;?[Y][Y]BBB[T];-GGGM"ADD[S]>███[T];8[F]E"""[T][6]4[6][T][6]U[6][T]K7HK[N]JL▜[N][E]V=VWV[N][N][X][/][/][/]0T[C]U[E]===WW[?][2],,<*<[Q][Z];F33["]V[P]V[?][2]G▌[£]U[Q]U[C]UO["]["][2][?][2][?][2],HIP[U]7/[U][U][V])[0]▀]S" CLEAR▚#S$ CLEARQ# /▛ CLEAR▚# CLEARQ# PRINT CLEAR#INKEY$ CLEAR#RND LET /, CLEARACS ##4INT PRINT CLEAR#INKEY$ CLEAR#RND LET ([8]TAN *** SILICON MOUNTAIN PRESENTS***#█[V][-][F]█[D][A][T][A]█[A][C][Q][U][I][S][I][T][I][O][N]█[+]█[D][I][S][P][L][A][Y]█##E£RND)NOT ▝; FOR 5C#▘PI GOSUB [K]▘(BTAN ▘ )[9]=.#[N]C><= RETURN▛K PLOT ▀.#[N]C▛<= RETURN▛S PLOT / DIM TAN YRNDE INPUT #6 INPUT #M LIST #LN [S]#E INPUT ##7#7U LIST #XCOS / DIM U LET #XCOS M LET #LN CHR$ #6 INPUT #/ LIST Y█E(RND)▞ ; GOSUB # GOTO #",,XC▝/ IF 6 INPUT #TAN LN [Y]PILN LPRINT RNDLN ~~#LN COS #Y▝ PRINT LN [C]# LET XC▝/ PLOT LN COS #TAN :▘#[E] NEW█#STR$ LN [~~]# STOPLN [~~]# FOR LPRINT #[B]CQ#[L] FAST GOSUB # GOSUB # FASTAT SGN 5 RZ PRINT ##2▒DK▌[?] GOSUB #/,,▗ GOSUB #S▀ GOSUB PIXW14 GOTO # LET K LLIST ACS #4▘ FOR ACS #COS /"LN [=]#ACS (SQR /▀#▛SQR FOR [B] GOSUB # GOSUB #TAN VAL ▞(##▌: DACS )*K▘;( RUN AT TAN CLEARQINKEY$ E INPUT #[J] PRINT #7#7 FAST CLEAR##VAL LPRINT GOSUB # POKE # GOSUB #S4 GOSUB # PAUSE #LN R#)~~ ;# RETURN S( CLEAR#PI CLEAR CLEAR#RNDLN ## LPRINT LET LEN ▘ KVAL TAN ▘ ##▘▘▀ [9]=[9]=[9]=[9]=5▖5▖5▖5▖ THEN# THEN#)▝)▝)▝)▝)▝)▝-*##▒ 1 REM [V][D][A][Q][1][-][H][R] F.NACHBAUR "85 2 REM GOTO 500 TO RESTART: [D][O][N][T]█[U][S][E]█[R][U][N] 4 FOR I=N1 TO LEN S$ 5 POKE 25537,128+CODE S$(I) 6 RAND USR PR 7 REM █ 8 NEXT I 9 RETURN 10 REM [D][O][N][T]█[C][H][A][N][G][E]█[L][I][N][E][S]█[1][-][1][0] V1.40 11 IF INKEY$ <>"" THEN GOTO O0 12 IF INKEY$ ="" THEN GOTO 12 15 LET Z$=INKEY$ 18 RETURN 500 CLS 505 RAND USR LRM 520 SLOW 530 PRINT TAB VAL "6";"[V][-][F]█[D][A][T][A]█[A][C][Q][U][I][S][I][T][I][O][N]",,,TAB N4;"PROGRAM 1, V 1.40-HR";TAB N4;"SAMPLE RATE 3 MS TO 1 SEC.",,,TAB N2;"(C)1985 BY F.NACHBAUR" 540 PRINT ,,"[O][P][T][I][O][N][S][:]",,,,"1. ACQUIRE DATA (1 FILE)",,,"2. PLOT DATA",,,,"3. PRINT DATA",,,,"4. RE-SET PLOT LIM.",,,"5. INITIALIZE",,,,"6. MULTI-FILE AQ.",,,"S. SAVE "; 550 GOSUB O0 560 LET Z$=INKEY$ 580 IF Z$="S" THEN GOTO VAL "9990" 600 IF Z$>"6" OR Z$<"0" THEN GOTO H5 610 CLS 620 GOTO N2*H5*VAL Z$ 1010 LET N=N1 1020 GOSUB FI 1030 POKE VAL "25329",N+N1 1040 PRINT "ENTER TIME BASE (.1-";TREF;" SEC): "; 1050 INPUT TB 1060 IF TB<.1 OR TB>TREF THEN GOTO VAL "1050" 1070 LET C0=(K64*TB/TREF) 1080 RAND C0 1090 POKE VAL "25020",PEEK S1 1100 POKE VAL "25021",PEEK S2 1110 GOSUB FS 1120 PRINT TB 1130 PRINT ,,"START BY [K]EY OR [N]ON-[Z]ERO INPUT ?" 1135 FAST 1140 PAUSE K64 1142 LET Z$=INKEY$ 1150 GOTO 1140+(80 AND Z$="K")+(120 AND (Z$="N" OR Z$="Z")) 1160 RAND USR AQ 1180 SLOW 1190 PRINT AT P1,N0;"[A][C][Q][U][I][R][E][D]" 1200 GOTO CO 1220 PRINT AT P1,N0;"[A][N][Y]█[K][E][Y][:]" 1230 PAUSE K64 1250 GOTO 1160 1260 PRINT AT P1,N0;"CHECKING..." 1265 PAUSE N1 1270 LET C=USR AQP 1280 IF (C AND Z$="N") OR (NOT C AND Z$="Z") THEN GOTO 1160 1290 GOTO 1265 2005 CLS 2010 GOSUB FI 2015 GOSUB FR 2030 PRINT ,,"1,2 OR 4 FILES?" 2040 INPUT M 2050 IF (M=N1 OR M=N2 OR M=N4) AND (M+FL<=VAL "17") THEN GOTO VAL "2070" 2060 PRINT "[I][N][V][A][L][I][D]" 2065 GOTO VAL "2030" 2070 POKE VAL "25318",N4/M 2075 POKE VAL "17266",N4/M 2080 FAST 2090 LET R=INT ((CH-CL)/VAL "160") 2100 RAND R 2110 POKE R1,PEEK S1 2120 POKE R2,PEEK S2 2125 POKE CL2,INT (CL/TFS) 2130 POKE CL1,CL-TFS*PEEK CL2 2140 RAND USR VAL "25115" 2150 POKE X1,N0 2160 POKE Y1,VAL "7" 2170 LET S$=("1 HOR. DIV.="+STR$ (SR*N2*M)+" MSEC."+" ")( TO 32) 2180 GOSUB N4 2190 RAND USR LRM 2200 POKE BL,N1 2210 LET S$="MIN.="+((STR$ ((PEEK CL1+TFS*PEEK CL2)/CM))+" ")( TO 5)+" : MAX.="+((STR$ (R*160/CM))+" ")( TO 5) 2220 PRINT AT P1+N1,N0;S$ 2230 POKE BL,N2 2240 RAND USR HRM 2250 GOTO CO 3000 GOSUB FI 3020 FAST 3030 GOSUB FR 3040 CLS 3050 PRINT ,,"FILE NO:",FL,"TIME BASE =",TB;" SEC.","SAMPLE RATE = ";SR;" MSEC",,,,,"[N][O]█[M][S][E][C]█[V][O][L][T][A][G][E]██[N][O]█[M][S][E][C]█[V][O][L][T][A][G][E]",, 3060 LET DP=O0**INT (VAL ".2"+LN CM/LN O0) 3070 FOR A=N1 TO VAL "32" 3080 FAST 3090 LET D=N2*(A-N1)+PEEK 25326+TFS*PEEK 25327 3100 LET VL=(PEEK D+TFS*PEEK (D+1))/CM 3110 LET VL=(INT (VL*DP))/DP 3120 LET VH=(PEEK (D+64)+TFS*PEEK (D+65))/CM 3130 LET VH=(INT (VH*DP))/DP 3140 PRINT A;TAB 3;INT (A*SR+N1/N2);TAB 9;VL;TAB 16;"▌";A+32;TAB 20;INT ((A+32)*SR+N1/N2);TAB 26;VH 3150 IF A=14 THEN PAUSE K64 3155 IF INKEY$ ="Z" THEN COPY 3160 IF A=14 THEN CLS 3170 NEXT A 3180 GOTO CO 4000 PRINT "PRESENT LIMITS:",,"MIN. VOLTAGE=";PL,"MAX. VOLTAGE=";PH 4010 PRINT ,,"CHANGE TO:",,"MIN.="; 4020 INPUT PL 4030 PRINT PL,,"MAX.="; 4040 INPUT PH 4050 PRINT PH,,"OK?" 4060 GOSUB O0 4070 IF Z$="Y" THEN GOTO CO 4080 CLS 4090 GOTO VAL "4000" 5000 PRINT "[I][N][I][T][I][A][L][I][Z][E][:]" 5180 LET PL=N0 5190 LET PH=N1 5200 LET N=N1 5210 PRINT "APPLY AND MEASURE VREF",,,"VREF="; 5220 INPUT VREF 5230 PRINT VREF 5240 POKE VAL "25020",VAL "255" 5250 POKE VAL "25021",VAL "255" 5260 FAST 5270 LET C=USR AQP 5290 PRINT ,," MAX COUNT=";C 5300 LET C1=C/VREF 5310 PRINT "1V COUNT AT MAX TIME=";C1;" " 5320 LET FL=N1 5330 GOSUB VAL "7915" 5340 LET C0=K64 5350 GOSUB FS 5360 PRINT ,,"GET READY TO SET TIME-BASE:" 5370 PAUSE K64 5390 RAND USR AQ1 5400 SLOW 5410 PRINT ,,"TIME=?"; 5420 INPUT TREF 5430 PRINT TREF 5440 GOTO CO 6000 CLS 6020 PRINT "START AT " 6030 GOSUB FI 6040 PRINT 6050 GOSUB SS 6055 IF FL+N>VAL "17" THEN GOTO VAL "6000" 6060 PRINT ,,,,"(EACH SCREEN)=" 6070 GOTO VAL "1030" 7900 LET N$="WHICH FILE? (1-16)= " 7905 GOSUB INP 7910 LET FL=A 7920 POKE VAL "25324",FL 7925 RAND USR ST 7930 RETURN 7950 LET N$="HOW MANY FILES? ( TO "+STR$ (VAL "17"-FL)+"): " 7960 GOSUB INP 7970 LET N=A 7980 RETURN 8000 PRINT ,,N$; 8010 INPUT A 8030 PRINT A 8040 IF A>N0 AND A