--- title: "T/S-1500 Biorhythm Monitor" id: 71908 type: "computer_media" slug: "t-s-1500-biorhythm-monitor" url: "http://localhost/computer_media/t-s-1500-biorhythm-monitor/" markdown_url: "http://localhost/computer_media/t-s-1500-biorhythm-monitor.md" published_at: "2026-10-20T14:07:49+00:00" modified_at: "2026-10-26T17:27:25+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/10/BIO.png" excerpt: "Charts physical, sensitivity and cognitive biorhythm cycles for up to seven days from a birth date, with an on-screen form and a printer copy option." post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1500" slug: "ts1500" taxonomy: "post_tag" url: "http://localhost/tag/ts1500/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" - name: "Timex/Sinclair 1500" slug: "ts-1500" taxonomy: "model" url: "http://localhost/model/ts-1500/" genre: - name: "Entertainment" slug: "entertainment" taxonomy: "genre" url: "http://localhost/type/entertainment/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/TS-1500%20Biorhythm%20Monitor%20%28198x%29%28-%29%28TS1500%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/10/BIO.png" media_type_tags: "Entertainment" --- # T/S-1500 Biorhythm Monitor Works out your physical, sensitivity and cognitive biorhythm cycles from your birth date and a chosen start date, and plots them for one to seven days. Name, birth date, start date and number of days go into a framed on-screen form, and an ERRORS box flags values that are too big. The chart shows the day of the week, the date and the month and year for each column, with an inverse `P`, `S` or `C` marking each cycle’s position and an inverse `*` where cycles overlap. The heading shows the number of days you have been alive. When the chart is finished you can copy it to the printer, run the program again or quit. The opening screen reads "WELCOME TO THE T/S-1500 BIORHYTHM MONITOR". The tape holds a normal copy and an autorun copy of the same program. ## Program Analysis ### Program Structure - Lines 10–272: set up arrays for day names, month names and month lengths, then call the input form at 4100. - Lines 4100–5270: the input form, with range checks and right-aligned display of each number in the form. A ready screen warns that the display will go blank for about 30 seconds while the program works in `FAST` mode. - Lines 290–680: date arithmetic. The century is removed from both years, the day of the year is built from month lengths with a leap year correction, and the total days lived `S` and an absolute day number `D3` are worked out. - Lines 741–1950: plotting. For each day the program prints the weekday (from `D3` modulo 7), the date and the month and year, works out the three cycle values, and draws the markers in a column. The date then moves on by one day, rolling over months and years. - Lines 4000–4095: the key and the C/R/Q option loop. `COPY` sends the screen to the printer. ### Notable Techniques - Cycle positions come from `INT (20*SIN ((S/P-INT (S/P))*6.28318)+40.5)` with `P=18+5*I`, giving the standard 23-, 28- and 33-day periods. Values from 20 to 60 are mapped to screen rows with two straight-line formulas, one for each half of the curve. - Overlap is checked two ways: matching cycle values are drawn as `*`, and so is any marker that falls on the same row as the one just drawn. - A 64×64 string array `C$` is set up, but only its diagonal `C$(X,X)` is used, as a one-dimensional map of which cycle sits at each value. That uses 4K of memory to hold 64 characters. - Markers are printed with `CHR$` codes for inverse letters (181 = P, 184 = S, 168 = C, 151 = *). - Line 774 changes a one-day request into two so that the column spacing `(Q-1)*25/(D9-1)` never divides by zero. ### Potential Issues - Line 1940 uses `Y(1)` (the birth year) instead of `Y(2)` when resetting February’s length after a year rollover, so a chart that crosses into a new year can get leap years wrong. - Leap years are taken as every fourth year, with no century rule. - Day entry is checked against a February length of 28, so a 29 February birth date is rejected. - The ready screen asks you to press ENTER, but any key carries on. - Lines 6000–6010 cannot be reached. The download also includes a BBDOS adaptation of this program from the BBDOS 4.0 distribution disks for the AERCO FD-ZX disk interface ([BBDOS](/?p=72719), Bill Bell, 1986). Q and a name of “R” return to BBDOS with `RAND USR 11000`, C prints the chart through BBDOS’s 24-line copy instead of `COPY`, and the zero line is drawn with `PRINT` instead of `PLOT`. Everything else runs on a plain 16K machine, but Q, C and R call BBDOS, so they need the FD-ZX interface. A README in the zip explains this. The BBDOS copy was read from two AERCO FD-ZX disks in Joe’s collection with a new reader for FD-ZX disk images, and was tested in ZEsarUX on an emulated 16K ZX81 by charting seven days. ## Source Code ``` 1 REM 10 REM "BIORHYTHM" 20 FAST 25 CLS 30 DIM A(12) 40 DIM B$(12,3) 50 DIM C$(64,64) 55 LET Z$="" 60 DIM A$(12,3) 70 LET Z=0 71 DIM X(3) 72 LET Q$=" " 74 LET ST=99 212 LET A$(1)="MON" 213 LET A$(2)="TUE" 214 LET A$(3)="WED" 215 LET A$(4)="THU" 216 LET A$(5)="FRI" 217 LET A$(6)="SAT" 218 LET A$(7)="SUN" 220 LET A(1)=31 222 LET A(2)=28 224 LET A(3)=31 225 LET A(4)=30 227 LET A(5)=31 228 LET A(6)=30 229 LET A(7)=31 230 LET A(8)=31 232 LET A(9)=30 234 LET A(10)=31 236 LET A(11)=30 238 LET A(12)=31 250 LET B$(1)="JAN" 252 LET B$(2)="FEB" 254 LET B$(3)="MAR" 256 LET B$(4)="APR" 258 LET B$(5)="MAY" 260 LET B$(6)="JUN" 262 LET B$(7)="JUL" 264 LET B$(8)="AUG" 266 LET B$(9)="SEP" 268 LET B$(10)="OCT" 270 LET B$(11)="NOV" 272 LET B$(12)="DEC" 280 GOSUB 4100 290 FAST 302 FOR N=10 TO 100 304 IF N*100>Y(1) THEN GOTO 308 306 NEXT N 308 LET Y(1)=Y(1)-((N-1)*100) 310 IF M(1)=1 THEN GOTO 411 320 LET A(2)=29-SGN (Y(1)/4-INT (Y(1)/4)) 330 FOR I=1 TO M(1)-1 340 LET D(1)=D(1)+A(I) 350 NEXT I 411 LET D0=D(2) 415 LET Y(2)=Y(2)-((N-1)*100) 422 LET A(2)=29-SGN (Y(2)/4-INT (Y(2)/4)) 430 IF M(2)=1 THEN GOTO 500 440 FOR I=1 TO M(2)-1 450 LET D(2)=D(2)+A(I) 460 NEXT I 500 LET S=0 505 FOR I=Y(1)+1 TO Y(2)-1 510 IF I/4=INT (I/4) THEN LET S=S+1 515 NEXT I 520 IF Y(1)/4=INT (Y(1)/4) THEN LET S=S+1 530 IF D(1)>59 THEN GOTO 600 550 LET S=S+((Y(2)-Y(1)-1)*365) 560 LET S=S+(365-D(1)) 570 LET S=S+D(2) 580 GOTO 650 600 IF Y(1)/4=INT (Y(1)/4) THEN LET S=S-1 610 GOTO 550 650 LET D3=Y(2)*365+D(2) 660 FOR I=1 TO Y(2)-1 670 IF I/4=INT (I/4) THEN LET D3=D3+1 680 NEXT I 720 LET D(2)=D0 740 GOSUB 2000 741 FOR N=1 TO 63 742 PLOT N,17 743 NEXT N 745 FOR N=0 TO 31 746 PRINT AT 2,N;CHR$ 8 747 NEXT N 750 FOR Q=1 TO D9 752 FOR I=1 TO 63 753 LET C$(I,I)="-" 754 NEXT I 760 LET GG=D3-1 770 LET E=INT (7*(GG/7-INT (GG/7))+0.5)+1 774 IF D9=1 THEN LET D9=2 775 LET R=(Q-1)*25/(D9-1) 780 PRINT AT 3,R;A$(E) 790 PRINT AT 4,R;D(2) 800 LET Z7=0 810 IF Z<1 THEN GOTO 900 815 IF D(2)<>1 THEN GOTO 940 900 PRINT AT 5,R;B$(M(2)) 905 LET Z7=1 907 IF Y(2)>=100 THEN LET Y(2)=100*(Y(2)/100-INT (Y(2)/100)) 910 PRINT AT 6,R;Y(2) 915 LET Z=Z+1 940 IF A$(E)="SUN" THEN GOTO 1000 950 REM 960 REM 965 REM 970 GOTO 1060 1000 REM 1005 REM 1010 REM 1060 FOR I=1 TO 3 1070 LET P=18+(5*I) 1080 LET X(I)=INT (20*SIN ((S/P-INT (S/P))*6.28318)+40.5) 1090 NEXT I 1100 REM 1114 PRINT AT 13,31;"0" 1115 PRINT AT 13,0;"0" 1116 LET C$(X(1),X(1))="P" 1120 IF X(1)<>X(2) THEN GOTO 1400 1130 IF X(1)<>X(3) THEN GOTO 1400 1140 IF X(2)<>X(3) THEN GOTO 1400 1150 LET C$(X(1),X(1))="*" 1160 GOTO 1800 1400 IF X(1)<>X(2) THEN GOTO 1500 1410 LET C$(X(3),X(3))="C" 1420 GOTO 1510 1500 IF X(2)<>X(3) THEN GOTO 1600 1510 LET C$(X(2),X(2))="*" 1520 GOTO 1800 1600 LET C$(X(2),X(2))="S" 1610 IF X(1)=X(3) THEN GOTO 1150 1620 LET C$(X(3),X(3))="C" 1800 REM 1810 FOR X=15 TO 63 1811 IF C$(X,X)="-" THEN GOTO 1830 1812 IF C$(X,X)="P" THEN LET J$=CHR$ 181 1813 IF C$(X,X)="S" THEN LET J$=CHR$ 184 1814 IF C$(X,X)="C" THEN LET J$=CHR$ 168 1815 IF X=40 THEN LET T=13 1816 IF X>40 THEN LET T=INT (X*-.2173913)+21 1817 IF X<40 THEN LET T=INT (X*-.2)+21 1818 IF C$(X,X)="*" THEN LET J$=CHR$ 151 1819 IF T=ST THEN LET J$=CHR$ 151 1820 PRINT AT T,R;J$ 1821 PRINT AT 21,31;"█";AT 21,31;" " 1822 LET ST=T 1830 NEXT X 1835 LET ST=99 1840 REM 1850 LET D3=D3+1 1860 LET S=S+1 1865 LET D(2)=D(2)+1 1870 IF D(2)"" THEN GOTO 4352 4280 PRINT AT 21,0;"WHAT IS YOUR NAME?" 4290 INPUT Z$ 4300 IF LEN (Z$)<12 THEN GOTO 4350 4310 PRINT AT 10,20;"TOO LONG" 4320 PAUSE 150 4330 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒▒" 4340 GOTO 4280 4350 PRINT AT 7,18;Z$ 4352 DIM M(2) 4354 DIM D(2) 4356 DIM Y(2) 4360 FOR N=1 TO 2 4370 IF N=2 THEN GOTO 4400 4380 PRINT AT 20,0;"*DATE OF BIRTH* " 4390 GOTO 4410 4400 PRINT AT 20,0;"*DATE TO START GRAPH* " 4410 PRINT AT 21,0;" ENTER MONTH " 4420 INPUT M(N) 4430 IF M(N)>12 THEN GOTO 4480 4450 IF M(N)<10 THEN PRINT AT 16,4+((N-1)*15);M(N) 4460 IF M(N)>9 THEN PRINT AT 16,3+((N-1)*15);M(N) 4470 GOTO 4500 4480 PRINT AT 10,20;"TOO BIG" 4490 PAUSE 150 4492 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒" 4495 GOTO 4420 4500 PRINT AT 21,0;" ENTER DAY " 4505 INPUT D(N) 4510 IF D(N)>A(M(N)) THEN GOTO 4550 4520 IF D(N)<10 THEN PRINT AT 16,7+((N-1)*15);D(N) 4530 IF D(N)>9 THEN PRINT AT 16,6+((N-1)*15);D(N) 4540 GOTO 5000 4550 PRINT AT 10,20;"TOO BIG" 4560 PAUSE 150 4570 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒" 4580 GOTO 4505 5000 PRINT AT 21,0;" ENTER YEAR (ALL 4 DIGITS)" 5010 INPUT Y(N) 5012 IF Y(N)<=9999 THEN GOTO 5020 5014 PRINT AT 10,20;"TOO HIGH" 5016 PAUSE 150 5017 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒][▒]▒" 5018 GOTO 5010 5020 IF Y(N)>=10 THEN GOTO 5023 5021 PRINT AT 16,13+((N-1)*15);Y(N) 5022 GOTO 5030 5023 IF Y(N)>=100 THEN GOTO 5026 5024 PRINT AT 16,12+((N-1)*15);Y(N) 5025 GOTO 5030 5026 IF Y(N)>=1000 THEN GOTO 5029 5027 PRINT AT 16,11+((N-1)*15);Y(N) 5028 GOTO 5030 5029 PRINT AT 16,10+((N-1)*15);Y(N) 5030 NEXT N 5040 PRINT AT 20,0;" " 5050 PRINT AT 21,0;"ENTER NO. OF DAYS TO PLOT (1-7)" 5060 INPUT D9 5070 IF D9<=7 THEN GOTO 5130 5080 PRINT AT 10,20;"TOO MANY" 5100 PAUSE 150 5110 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒][▒][▒]" 5120 GOTO 5060 5130 PRINT AT 11,9;D9 5140 PRINT AT 21,0;" ";AT 20,0;"IS ALL THE DATA CORRECT? (Y/N)" 5150 IF INKEY$ ="N" THEN GOTO 4190 5160 IF INKEY$ ="Y" THEN GOTO 5180 5170 GOTO 5150 5180 FAST 5182 CLS 5185 PRINT AT 1,3;"THE COMPUTER IS NOW READY" 5190 PRINT AT 2,3;"TO MAKE A BIORHYTHM CHART" 5195 PRINT AT 3,3;"FOR ";Z$;"." 5200 PRINT AT 5,3;"WHEN YOU ARE READY, ALL YOU" 5205 PRINT AT 6,3;"NEED TO DO IS PRESS [E][N][T][E][R]" 5210 PRINT AT 8,3;"THE COMPUTER WILL THEN GO" 5215 PRINT AT 9,3;"BLANK FOR APPROXIMATELY 30" 5220 PRINT AT 10,3;"SECONDS. " 5225 PRINT AT 12,3;"WHEN THE GRAPH C0MES UP, YOU" 5230 PRINT AT 13,3;"WILL HAVE 3 OPTIONS AVAILABLE" 5235 PRINT AT 15,5;"[C]-COPY GRAPH ONTO PRINTER" 5240 PRINT AT 17,5;"[R]-RUN THE PROGRAM AGAIN" 5245 PRINT AT 19,5;"[Q]-STOP THE PROGRAM" 5250 PRINT AT 21,3;"PRESS [E][N][T][E][R] WHEN READY" 5255 SLOW 5260 IF INKEY$ ="" THEN GOTO 5260 5270 RETURN 5299 STOP 5300 CLS 5310 PRINT AT 3,5;"THANK-YOU FOR PLAYING" 5315 PRINT AT 5,0;"AND I HOPE YOU ENJOYED YOURSELF." 5320 STOP 6000 PRINT AT 21,31;"▐";AT 21,31;"▌" 6010 GOTO 1830 9995 SAVE "BI[O]" 9996 RUN ```