Login | Register (Invite Only)
Title: Page Telegram of Amfile.org
Description: Brown Hats Collective F' Around and Find Out user of the Interwebs and Project Developer for a Cause Toward Insuring a Future of Liberty without Illusion.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@=:---#@@@#%@@@*=+#@%====@@@@..:--@#====@-==#@@@+===#@%=-+@... -@@@@*@@@=+@%-*@ @@@.*@-.@@@.:@@==@:=@+ -..*@@@:# @:@=.=. #%.#@@@@ ::..@.%#.@@ %+ %@@% #@@-.@+ #@ @@@.*@+.@@@:.@@.#@%*@*.@.-*@@%@#.@.@=.%..#% *@@@@ %:+:+:@@=@@ #+ %@@+..@@= %: @@ @@@..-.=@@:* %@.%#=+@+..:@@@@@@*.@@@=..:@@@ %@%%% :.@@+-@:=#@ ...@@@:+ @@+ :- @@ @@@.+@@@@@.- =@.#@.-@*.@:=@@@@@+ @@@+:@-:@% @@*=@ @=%#+-@-.#@ @*.%@@.- #@=. + @@ @@@.+@@@@+.@..@:*%.*@*.@%.@@@@%- +@@=:@%.@@.%@:=@ @@=*#:@::@@ *# =@--% -@:- * @@ @@-::#@@%::+::*@-:=%@::.::@@@@+-::@*:.:::@::...%:::::#@*:==@#==@+:*.:=::%:-=::=@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#-. .-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*. .+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .++: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@+ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@: =@@@@@@@@@@+ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@# .@@@@@@@@@@@@. *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@. %@@@@@@@@@@@@%. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@- #@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@= #@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@%##***#%@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@* %@#:.. .:+@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@= =. : -@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .=%@@@@@@@+: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@# .%@@@@@@@@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@# .*@@@@@@@@@@@@@@@@%: -@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@%. .@@@@@@*%@@@@%#@@@@@@= *@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@. :@@@@@@@@:-@@*.%@@@@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@+ :@@@@@@@@@@---.@@@@@@@@@@= :@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. @@@@@@@@@@@. @@@@@@@@@@@: #@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@= #@@@+--#@@@@ #@@@@%#@@@@@. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. :@%- .%@@- .@@@*. .+@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *+. .@@@#*@@@= .#@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .# =@@-.@@%. += .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. -@. @@. %@: #% %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@- +% =% .@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@% :+ .+ +@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@: .: .- .@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@% # .# =@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@@= -@ @- .@@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@@@. .@@ @@. %@@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@@@@@: :@@@ @@@. .*@@@@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@@@@@@#+#@@@@ @@@@=.:%@@@@@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. :@@@@@@-..:*@@ @@#-..:%@@@@@# %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .@@@@@: .@ @. .@@@@@- .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *@@@% @. .@ *@@@@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. .@@@+ @- .@. -@@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@+ +@@%. .@* :@- .*@@%. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. %@@@- *@% #@%. :%@@@. %@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@* .@@@@%=-+@@@. @@@*--#@@@@- -@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@*=@@@@@@@@@@: @@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@. .%@@@@@@@@@@@@@@@@@@@- .#@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@%. +@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@%. .+@@@@@@@@@@@@%: +@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@%. -*%@@@@@#=. .*@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@: .%@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+. .=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=. .-%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%###%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
' Live EMF Plotter 3.0 by AmFile.org August 2025
' Designed for exotic spectrum identification and abuse assessments using sensory and RF equipment data logging.
' This script enables interactive visualization of EMF data from CSV logs, allowing real-time adjustments for
' detailed analysis of magnetic field anomalies, potential interference patterns, and abuse indicators in RF environments.
' Adapt software as needed to live plot from any dataset.
DEFINT A-Z
OPTION BASE 1
DIM SHARED DataCount AS LONG
DIM SHARED MaxData AS LONG
DIM SHARED TimeStamp AS STRING * 20
DIM SHARED XVal AS SINGLE
DIM SHARED YVal AS SINGLE
DIM SHARED ZVal AS SINGLE
DIM SHARED MagVal AS SINGLE
DIM SHARED TempMag AS SINGLE
DIM SHARED FileName AS STRING
DIM SHARED HomeActive AS INTEGER
DIM SHARED Multiplier AS INTEGER
DIM SHARED GrayscaleMode AS INTEGER
DIM SHARED AxesColor AS INTEGER
DIM SHARED EMFPalette(0 TO 15) AS _UNSIGNED LONG
Multiplier = 1 ' Default multiplier
GrayscaleMode = 0 ' Default normal mode
' Colors for contrast: Blue (1) for X, Green (10) for Y, Cyan (11) for Z, Red (12) for Mag
CONST COLORX = 1
CONST COLORY = 10
CONST COLORZ = 11
CONST COLORMAG = 12
' Screen dimensions for SCREEN 12: 640x480
CONST SCREENWIDTH = 640
CONST SCREENHEIGHT = 480
CONST PLOTHEIGHT = 360 ' Plot area height, adjusted to avoid overlap
CONST PLOTBOTTOM = SCREENHEIGHT - 80 ' Bottom margin for labels
CONST PLOTLEFT = 50 ' Left margin for Y axis
CONST PLOTRIGHT = SCREENWIDTH - 50 ' Right margin
CONST MAX_PLOT_POINTS = 640 ' Max points to plot for performance on large scopes
' Initialize arrays with large initial size to reduce resizing
REDIM SHARED TimeStamp(1 TO 100000) AS STRING * 20
REDIM SHARED XVal(1 TO 100000) AS SINGLE
REDIM SHARED YVal(1 TO 100000) AS SINGLE
REDIM SHARED ZVal(1 TO 100000) AS SINGLE
REDIM SHARED MagVal(1 TO 100000) AS SINGLE
SCREEN 12
CALL SetPalette(GrayscaleMode) ' Initialize to normal mode
' Cross-platform CSV file listing
DIM SHARED CSVFiles(100) AS STRING
DIM SHARED FileCount AS INTEGER
FileCount = 0
IF _OS$ = "WINDOWS" THEN
SHELL "dir *.csv /b > csvlist.txt"
ELSE
SHELL "dir *.csv /b > csvlist.txt"
END IF
OPEN "csvlist.txt" FOR INPUT AS #1
DO WHILE NOT EOF(1)
FileCount = FileCount + 1
LINE INPUT #1, CSVFiles(FileCount)
LOOP
CLOSE #1
KILL "csvlist.txt"
IF FileCount = 0 THEN
PRINT "No CSV files found in current directory."
END
END IF
' Prompt user to select file
PRINT "Select CSV file for EMF data analysis:"
FOR i = 1 TO FileCount
PRINT i; ": "; CSVFiles(i)
NEXT i
DO
INPUT "Enter number: ", sel
LOOP UNTIL sel >= 1 AND sel <= FileCount
FileName = CSVFiles(sel)
GOSUB LoadData
MaxData = DataCount
' Initial scope: full dataset
StartIdx& = 1
EndIdx& = DataCount
HomeActive = 0
DO
' Handle auto-reload if Home active
IF HomeActive THEN
TIMER ON
StartTime! = TIMER
DO
IF TIMER - StartTime! >= 2 THEN
GOSUB LoadData
MaxData = DataCount
EndIdx& = MaxData
StartIdx& = MaxData - 999
IF StartIdx& < 1 THEN StartIdx& = 1
EXIT DO
END IF
LOOP
END IF
CALL SetPalette(GrayscaleMode) ' Set palette based on mode
' Plot the data
CLS
' Draw top and bottom lines for scope boundaries
LINE (PLOTLEFT, PLOTBOTTOM)-(PLOTRIGHT, PLOTBOTTOM), AxesColor ' Bottom line
LINE (PLOTLEFT, PLOTBOTTOM - PLOTHEIGHT)-(PLOTRIGHT, PLOTBOTTOM - PLOTHEIGHT), AxesColor ' Top line
LOCATE 28, 1: PRINT "Time/Index"
LOCATE 14, 1: PRINT "uT"
' Validate scope indices
IF StartIdx& < 1 THEN StartIdx& = 1
IF EndIdx& > MaxData THEN EndIdx& = MaxData
IF StartIdx& > EndIdx& THEN SWAP StartIdx&, EndIdx&
IF EndIdx& < StartIdx& + 10 THEN EndIdx& = StartIdx& + 10
' Find min/max for Y scaling and peaks
MinY! = 1E+38
MaxY! = -1E+38
peakX! = -1E+38
peakY! = -1E+38
peakZ! = -1E+38
peakM! = -1E+38
FOR i& = StartIdx& TO EndIdx&
IF XVal(i&) < MinY! THEN MinY! = XVal(i&)
IF YVal(i&) < MinY! THEN MinY! = YVal(i&)
IF ZVal(i&) < MinY! THEN MinY! = ZVal(i&)
IF MagVal(i&) < MinY! THEN MinY! = MagVal(i&)
IF XVal(i&) > MaxY! THEN MaxY! = XVal(i&)
IF YVal(i&) > MaxY! THEN MaxY! = YVal(i&)
IF ZVal(i&) > MaxY! THEN MaxY! = ZVal(i&)
IF MagVal(i&) > MaxY! THEN MaxY! = MagVal(i&)
IF XVal(i&) > peakX! THEN peakX! = XVal(i&)
IF YVal(i&) > peakY! THEN peakY! = YVal(i&)
IF ZVal(i&) > peakZ! THEN peakZ! = ZVal(i&)
IF MagVal(i&) > peakM! THEN peakM! = MagVal(i&)
NEXT i&
IF MaxY! = MinY! THEN MaxY! = MinY! + 1 ' Avoid divide by zero
' Plot width based on downsampled points
size& = EndIdx& - StartIdx& + 1
CONST MAX_PLOT_POINTS = 640 ' Max points to plot for performance on large scopes
IF size& > MAX_PLOT_POINTS THEN
stepSize! = size& / MAX_PLOT_POINTS
PlotWidth! = (PLOTRIGHT - PLOTLEFT) / MAX_PLOT_POINTS
ELSE
stepSize! = 1
PlotWidth! = (PLOTRIGHT - PLOTLEFT) / size&
END IF
' Plot each series with downsampling if needed
LastX! = PLOTLEFT
LastY_X! = PLOTBOTTOM - ((XVal(StartIdx&) - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
LastY_Y! = PLOTBOTTOM - ((YVal(StartIdx&) - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
LastY_Z! = PLOTBOTTOM - ((ZVal(StartIdx&) - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
LastY_Mag! = PLOTBOTTOM - ((MagVal(StartIdx&) - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
FOR p = 1 TO MAX_PLOT_POINTS - 1
CurrX! = PLOTLEFT + p * PlotWidth!
binStart& = StartIdx& + (p - 1) * stepSize!
binEnd& = binStart& + stepSize! - 1
IF binEnd& > EndIdx& THEN binEnd& = EndIdx&
sumX! = 0: sumY! = 0: sumZ! = 0: sumMag! = 0
count& = 0
FOR j& = binStart& TO binEnd&
sumX! = sumX! + XVal(j&)
sumY! = sumY! + YVal(j&)
sumZ! = sumZ! + ZVal(j&)
sumMag! = sumMag! + MagVal(j&)
count& = count& + 1
NEXT j&
IF count& > 0 THEN
avgX! = sumX! / count&
avgY! = sumY! / count&
avgZ! = sumZ! / count&
avgMag! = sumMag! / count&
ELSE
avgX! = 0
avgY! = 0
avgZ! = 0
avgMag! = 0
END IF
CurrY_X! = PLOTBOTTOM - ((avgX! - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
CurrY_Y! = PLOTBOTTOM - ((avgY! - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
CurrY_Z! = PLOTBOTTOM - ((avgZ! - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
CurrY_Mag! = PLOTBOTTOM - ((avgMag! - MinY!) / (MaxY! - MinY!)) * PLOTHEIGHT
LINE (LastX!, LastY_X!)-(CurrX!, CurrY_X!), COLORX
LINE (LastX!, LastY_Y!)-(CurrX!, CurrY_Y!), COLORY
LINE (LastX!, LastY_Z!)-(CurrX!, CurrY_Z!), COLORZ
LINE (LastX!, LastY_Mag!)-(CurrX!, CurrY_Mag!), COLORMAG
LastX! = CurrX!
LastY_X! = CurrY_X!
LastY_Y! = CurrY_Y!
LastY_Z! = CurrY_Z!
LastY_Mag! = CurrY_Mag!
NEXT p
' Title at top
LOCATE 1, 1: PRINT "Live EMF Plotter 3.0 by AmFile.org August 2025"
' Date/time scope range at top
tempStart$ = ""
tempEnd$ = ""
IF StartIdx& >= 1 AND StartIdx& <= MaxData THEN tempStart$ = TimeStamp(StartIdx&)
IF EndIdx& >= 1 AND EndIdx& <= MaxData THEN tempEnd$ = TimeStamp(EndIdx&)
LOCATE 2, 1: PRINT "Scope: "; StartIdx&; " to "; EndIdx&; " ("; tempStart$; " to "; tempEnd$; ")"
' All other labels at bottom below the chart scope
LOCATE 26, 1: PRINT "Peak X: "; peakX!; " Y: "; peakY!; " Z: "; peakZ!; " M: "; peakM!; " uT"
IF GrayscaleMode THEN
LOCATE 27, 1: PRINT "X: Dark Gray, Y: Medium Gray, Z: Light Gray, Mag: Lighter Gray"
ELSE
LOCATE 27, 1: PRINT "X: Blue, Y: Green, Z: Cyan, Mag: Red"
END IF
LOCATE 28, 1: PRINT "[H]elp [P]rint Mode"
IF HomeActive THEN LOCATE 29, 1: PRINT "(Home Active - Last 1000, Auto-Reload)"
' Handle input
DO
k$ = INKEY$
LOOP WHILE k$ = ""
Inc& = Multiplier * 10 ' Base increment, adjust as needed
CtrlDown = _KEYDOWN(100305) OR _KEYDOWN(100306) ' Ctrl key (left or right)
SELECT CASE UCASE$(k$)
CASE CHR$(27): END ' ESC
CASE "S"
' Save screenshot as 24-bit BMP
DateTime$ = MID$(DATE$, 7, 4) + MID$(DATE$, 1, 2) + MID$(DATE$, 4, 2) + "_" + MID$(TIME$, 1, 2) + MID$(TIME$, 4, 2) + MID$(TIME$, 7, 2)
GOSUB SaveBMP
CASE "H"
GOSUB ShowHelp
CASE "P"
GrayscaleMode = NOT GrayscaleMode
CASE CHR$(0) + CHR$(72) ' Up - Widen (zoom out)
center& = (StartIdx& + EndIdx&) / 2
width& = EndIdx& - StartIdx& + 1
newWidth& = width& + Inc& * 2 ' Add to both sides
StartIdx& = center& - newWidth& / 2
EndIdx& = center& + newWidth& / 2 - 1
IF StartIdx& < 1 THEN StartIdx& = 1
IF EndIdx& > MaxData THEN EndIdx& = MaxData
CASE CHR$(0) + CHR$(80) ' Down - Thin (zoom in)
center& = (StartIdx& + EndIdx&) / 2
width& = EndIdx& - StartIdx& + 1
newWidth& = width& - Inc& * 2 ' Subtract from both sides
IF newWidth& < 10 THEN newWidth& = 10
StartIdx& = center& - newWidth& / 2
EndIdx& = center& + newWidth& / 2 - 1
IF StartIdx& < 1 THEN StartIdx& = 1
IF EndIdx& > MaxData THEN EndIdx& = MaxData
CASE CHR$(0) + CHR$(75) ' Left - Shift left
IF CtrlDown THEN Shift& = 1000 ELSE Shift& = Inc&
StartIdx& = StartIdx& - Shift&
EndIdx& = EndIdx& - Shift&
IF StartIdx& < 1 THEN StartIdx& = 1
IF EndIdx& < StartIdx& + 10 THEN EndIdx& = StartIdx& + 10
IF EndIdx& > MaxData THEN EndIdx& = MaxData
CASE CHR$(0) + CHR$(77) ' Right - Shift right
IF CtrlDown THEN Shift& = 1000 ELSE Shift& = Inc&
StartIdx& = StartIdx& + Shift&
EndIdx& = EndIdx& + Shift&
IF EndIdx& > MaxData THEN EndIdx& = MaxData
IF StartIdx& > EndIdx& - 10 THEN StartIdx& = EndIdx& - 10
IF StartIdx& < 1 THEN StartIdx& = 1
CASE CHR$(0) + CHR$(79) ' End - Full dataset
StartIdx& = 1
EndIdx& = MaxData
HomeActive = 0
CASE CHR$(0) + CHR$(71) ' Home - Last 1000
EndIdx& = MaxData
StartIdx& = MaxData - 999
IF StartIdx& < 1 THEN StartIdx& = 1
HomeActive = -1
CASE "1" TO "9" ' Numpad for multiplier
Multiplier = VAL(k$)
END SELECT
LOOP
LoadData:
DataCount = 0
OPEN FileName FOR INPUT AS #2
DO WHILE NOT EOF(2)
LINE INPUT #2, line$
IF line$ <> "" THEN
comma1 = INSTR(line$, ",")
comma2 = INSTR(comma1 + 1, line$, ",")
comma3 = INSTR(comma2 + 1, line$, ",")
comma4 = INSTR(comma3 + 1, line$, ",")
comma5 = INSTR(comma4 + 1, line$, ",")
IF comma1 > 0 AND comma2 > comma1 AND comma3 > comma2 AND comma4 > comma3 AND comma5 > comma4 THEN
DataCount = DataCount + 1
IF DataCount > UBOUND(TimeStamp) THEN
newSize& = DataCount * 1.5 + 10000 ' Grow dynamically
REDIM _PRESERVE SHARED TimeStamp(1 TO newSize&) AS STRING * 20
REDIM _PRESERVE SHARED XVal(1 TO newSize&) AS SINGLE
REDIM _PRESERVE SHARED YVal(1 TO newSize&) AS SINGLE
REDIM _PRESERVE SHARED ZVal(1 TO newSize&) AS SINGLE
REDIM _PRESERVE SHARED MagVal(1 TO newSize&) AS SINGLE
END IF
TimeStamp(DataCount) = LEFT$(line$, comma1 - 1)
XVal(DataCount) = VAL(MID$(line$, comma1 + 1, comma2 - comma1 - 1))
YVal(DataCount) = VAL(MID$(line$, comma2 + 1, comma3 - comma2 - 1))
ZVal(DataCount) = VAL(MID$(line$, comma3 + 1, comma4 - comma3 - 1))
MagVal(DataCount) = VAL(MID$(line$, comma4 + 1, comma5 - comma4 - 1))
END IF
END IF
LOOP
CLOSE #2
IF DataCount = 0 THEN
PRINT "No valid data loaded from CSV."
END
END IF
RETURN
SaveBMP:
DIM FileSize AS LONG
DIM y AS INTEGER, x AS INTEGER, c AS INTEGER, r AS INTEGER, g AS INTEGER, b AS INTEGER
DIM rgb AS _UNSIGNED LONG
DIM Signature AS STRING * 2
DIM Reserved AS STRING * 4
DIM Offset AS STRING * 4
DIM HeaderSize AS STRING * 4
DIM Width AS STRING * 4
DIM Height AS STRING * 4
DIM Planes AS STRING * 2
DIM BitsPerPixel AS STRING * 2
DIM Compression AS STRING * 4
DIM ImageSize AS STRING * 4
DIM XPelsPerMeter AS STRING * 4
DIM YPelsPerMeter AS STRING * 4
DIM ColorsUsed AS STRING * 4
DIM ImportantColors AS STRING * 4
DIM Blue AS STRING * 1
DIM Green AS STRING * 1
DIM Red AS STRING * 1
' Create a standard 24-bit Windows BMP file
OPEN DateTime$ + ".bmp" FOR BINARY AS #3
' BITMAPFILEHEADER (14 bytes)
Signature = CHR$(66) + CHR$(77) ' "BM" signature
PUT #3, , Signature
FileSize = 54 + SCREENWIDTH * SCREENHEIGHT * 3 ' Header + pixel data (24-bit)
FileSizeStr$ = MKL$(FileSize) ' Predefine MKL$ result
PUT #3, , FileSizeStr$ ' File size
Reserved = STRING$(4, 0) ' Reserved bytes
PUT #3, , Reserved
Offset = MKL$(54) ' Offset to pixel data
PUT #3, , Offset
' BITMAPINFOHEADER (40 bytes)
HeaderSize = MKL$(40) ' Header size
PUT #3, , HeaderSize
Width = MKL$(SCREENWIDTH) ' Width
PUT #3, , Width
Height = MKL$(SCREENHEIGHT) ' Height
PUT #3, , Height
Planes = MKI$(1) ' Planes
PUT #3, , Planes
BitsPerPixel = MKI$(24) ' Bits per pixel
PUT #3, , BitsPerPixel
Compression = MKL$(0) ' Compression (none)
PUT #3, , Compression
ImageSize = MKL$(SCREENWIDTH * SCREENHEIGHT * 3) ' Image size
PUT #3, , ImageSize
XPelsPerMeter = MKL$(2835) ' X pixels per meter (approx 72 DPI)
PUT #3, , XPelsPerMeter
YPelsPerMeter = MKL$(2835) ' Y pixels per meter
PUT #3, , YPelsPerMeter
ColorsUsed = MKL$(0) ' Colors used (0 for 24-bit)
PUT #3, , ColorsUsed
ImportantColors = MKL$(0) ' Important colors
PUT #3, , ImportantColors
' Pixel data (bottom-up, 24-bit RGB)
FOR y = SCREENHEIGHT - 1 TO 0 STEP -1
FOR x = 0 TO SCREENWIDTH - 1
c = POINT(x, y) ' Get pixel color index (0-15)
IF c < 0 OR c > 15 THEN c = 0 ' Validate color index to prevent errors
rgb = EMFPalette(c) ' Get RGB value from palette
r = _RED32(rgb) ' Extract red using QB64 built-in
g = _GREEN32(rgb) ' Extract green using QB64 built-in
b = _BLUE32(rgb) ' Extract blue using QB64 built-in
Blue = CHR$(b)
Green = CHR$(g)
Red = CHR$(r)
PUT #3, , Blue
PUT #3, , Green
PUT #3, , Red ' Write BGR one byte at a time
NEXT x
NEXT y
CLOSE #3
RETURN
ShowHelp:
CLS
LOCATE 1, 1: PRINT "Key Mappings:"
LOCATE 2, 1: PRINT "Up arrow: Widen scope (zoom out) by multiplier * 10 points"
LOCATE 3, 1: PRINT "Down arrow: Thin scope (zoom in) by multiplier * 10 points"
LOCATE 4, 1: PRINT "Left arrow: Shift left by multiplier * 10 points"
LOCATE 5, 1: PRINT "Right arrow: Shift right by multiplier * 10 points"
LOCATE 6, 1: PRINT "Ctrl + Left/Right: Shift by 1000 points"
LOCATE 7, 1: PRINT "1-9: Set multiplier to 1-9"
LOCATE 8, 1: PRINT "Home: View last 1000 points, enable auto-reload every 2s"
LOCATE 9, 1: PRINT "End: View full dataset, disable auto-reload"
LOCATE 10, 1: PRINT "S/s: Save screenshot as BMP (date_time.bmp)"
LOCATE 11, 1: PRINT "H/h: This help screen"
LOCATE 12, 1: PRINT "P/p: Toggle grayscale mode for printing (white background)"
LOCATE 14, 1: PRINT "Press any key to continue..."
DO
k$ = INKEY$
LOOP WHILE k$ = ""
RETURN
SUB QuickSort (arr() AS SINGLE, low AS LONG, high AS LONG)
DIM stack(1 TO 100) AS LONG ' Stack for iterative QuickSort, max depth 100
DIM top AS INTEGER
top = 0
top = top + 1: stack(top) = low
top = top + 1: stack(top) = high
DO WHILE top > 0
high = stack(top): top = top - 1
low = stack(top): top = top - 1
IF low < high THEN
pivot! = arr((low + high) \ 2)
i& = low
j& = high
DO
WHILE arr(i&) < pivot!: i& = i& + 1: WEND
WHILE arr(j&) > pivot!: j& = j& - 1: WEND
IF i& <= j& THEN
tempSwap! = arr(i&): arr(i&) = arr(j&): arr(j&) = tempSwap!
i& = i& + 1
j& = j& - 1
END IF
LOOP WHILE i& <= j&
IF low < j& THEN
top = top + 1: stack(top) = low
top = top + 1: stack(top) = j&
END IF
IF i& < high THEN
top = top + 1: stack(top) = i&
top = top + 1: stack(top) = high
END IF
END IF
LOOP
END SUB
SUB SetPalette (mode AS INTEGER)
IF mode = 0 THEN
_PALETTECOLOR 0, _RGB32(0, 0, 0) ' Black
_PALETTECOLOR 1, _RGB32(0, 0, 170) ' Blue
_PALETTECOLOR 10, _RGB32(0, 170, 0) ' Green
_PALETTECOLOR 11, _RGB32(0, 170, 170) ' Cyan
_PALETTECOLOR 12, _RGB32(170, 0, 0) ' Red
_PALETTECOLOR 15, _RGB32(255, 255, 255) ' White
EMFPalette(0) = _RGB32(0, 0, 0)
EMFPalette(1) = _RGB32(0, 0, 170)
EMFPalette(10) = _RGB32(0, 170, 0)
EMFPalette(11) = _RGB32(0, 170, 170)
EMFPalette(12) = _RGB32(170, 0, 0)
EMFPalette(15) = _RGB32(255, 255, 255)
AxesColor = 15
ELSE
_PALETTECOLOR 0, _RGB32(255, 255, 255) ' White background
_PALETTECOLOR 1, _RGB32(50, 50, 50) ' Dark gray for X
_PALETTECOLOR 10, _RGB32(100, 100, 100) ' Medium gray for Y
_PALETTECOLOR 11, _RGB32(150, 150, 150) ' Light medium gray for Z
_PALETTECOLOR 12, _RGB32(200, 200, 200) ' Light gray for Mag
_PALETTECOLOR 15, _RGB32(0, 0, 0) ' Black for axes and text
EMFPalette(0) = _RGB32(255, 255, 255)
EMFPalette(1) = _RGB32(50, 50, 50)
EMFPalette(10) = _RGB32(100, 100, 100)
EMFPalette(11) = _RGB32(150, 150, 150)
EMFPalette(12) = _RGB32(200, 200, 200)
EMFPalette(15) = _RGB32(0, 0, 0)
AxesColor = 15
END IF
END SUB Language: qBASIC 4.5