|
Post by busaboy on Mar 1, 2023 19:05:10 GMT
I haven't had any luck getting a QuickBasic 4.5 program from a very old application note to work in either QB64 or QuickBasic 4.5. The article is so old no one is around to ask questions. Unfortunately I haven't used QuickBasic in over 20 years so my skills are rusty. The program S2P2LIB1.bas reads in an S-parameter ASCII text file BFP780.s2p and converts it to an electrical model in ASCII text BFP780.LIB to be used in Spice circuit analysis. I fixed the obvious errors in the PDF and copy/paste but there still could be formatting errors or typos. The error message as shown in S2P2LIB1.jpg alludes to input file BFP780.s2p being bad but it isn't. To isolate the problem(s) I created S2P2LIB.bas and a simplified test file, ATF.s2p. The error message as shown in S2P2LIB.jpg indicates "subscript out of range". Every change I've made like extra DIMs fails so I obviously don't understand the error. Any help would be appreciated. Tom S2P2LIB1.zip (697.35 KB)
|
|
|
Post by bplus on Mar 1, 2023 20:51:39 GMT
Deleted: Nevermind
|
|
|
Post by busaboy on Mar 2, 2023 0:18:14 GMT
Any comment including negative ones are welcome.
|
|
|
Post by bplus on Mar 2, 2023 0:52:51 GMT
I went over it and Dim everything under Option _Explicit that it forces.
I thought I fixed something when I shared L$ but it was my own comment mark that disabled L$ under "Common". BTW Common Shared is now replaced by just Shared, since multiple modules are not needed these days, that's neither here nor there though. I do think the Arrays should be Dim after Common or Shared.
Oh heck here is what I got that runs error free but even I can tell it's not correct yet.
Option _Explicit ' lets see what needs DIM '$Debug 'S2P2LIB1-- converts S2P tables to PSpice-compatible frequency-response tables. 'Written in QuickBASIC (v4.5). See 'HelpMessage' SUB for additional comments. 'DECLARE SUB ParseDataLine () ' dont need this 'DECLARE SUB HelpMessage () ' ditto 'Dim D(16), M(50, 9)
Dim Shared D(16) ' As Single >> add shared Dim Shared M(50, 9) ' As Single >> ditto Dim Shared L$ ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<< this needs to get into Parse Sub 'Common Shared D(), M(), L$ ' >>>>> let do this without Common and before Dim them
Dim As Long False, True, DataLine, EODat, InTheData, k, p, offSet, F Dim C$, ufn$, HDR$, G$, M$, p$ Dim S$(1 To 4), E$(1 To 4) Dim As Single prevPH, PH, UWP, DB
False = 0: True = Not False DataLine = 0: EODat = False 'C$ = Command$ ' needs changes so Help screens are displayed C$ = "ATF.s2p" 'Decomment and edit in uncompiled version. If UCase$(Right$(C$, 4)) = ".S2P" Then 'Plausible command$ found. ufn$ = Left$(C$, Len(C$) - 4) Else Call HelpMessage ': System End If Open C$ For Input As #1 Open ufn$ + ".LIB" For Output As #2 Print #2, ".SUBCKT " + ufn$ + " 1 2 3; Port1 Port2 Common" Print #2, "*Subcircuit generated by S2P2LIB1.EXE on " + Date$ While Not (EOF(1) Or EODat) Line Input #1, L$ L$ = LTrim$(L$) 'Get rid of any leading spaces. If Left$(L$, 1) = "!" Then Print #2, "*" + Right$(L$ + " ", Len(L$)) If Left$(L$, 1) = "#" Then HDR$ = UCase$(L$): Print #2, "*" + L$ If Val(L$) > 0 Then InTheData = True ParseDataLine DataLine = DataLine + 1 For k = 1 To 9: M(DataLine, k) = D(k): Next End If If Val(L$) = 0 And InTheData = True Then EODat = True Wend Close #1 Print #2, " ": Print #2, "R1N 1 5 -50": Print #2, "R1P 5 7 100" Print #2, "R2N 2 4 -50": Print #2, "R2P 4 6 100" S$(1) = "*S11 FREQ DB PHASE": S$(2) = "*S21 FREQ DB PHASE" S$(3) = "*S12 FREQ DB PHASE": S$(4) = "*S22 FREQ DB PHASE" E$(1) = "E11 7 9 FREQ {V(5,3)}=": E$(2) = "E21 6 8 FREQ {V(5,3)}=" E$(3) = "E12 9 3 FREQ {V(4,3)}=": E$(4) = "E22 8 3 FREQ {V(4,3)}=" G$ = "_+_(###.##gHz_,+###.##_, +###.##)" 'Format for gHz data M$ = "_+_(#####.##MHz_,+###.##_, +###.##)" 'Format for MHz data If InStr(HDR$, "MHZ") Then p$ = M$ Else p$ = G$ For p = 1 To 4 'Build S11, S21, S12, and S22 blocks in sequence. Print #2, " ": Print #2, S$(p): Print #2, E$(p) offSet = 0: prevPH = 0 'Clear variables used to unwrap phase. For F = 1 To DataLine 'Successive frequency values. PH = M(F, 2 * p + 1) 'Current phase data. If Abs(PH - prevPH) > 180 Then offSet = offSet - 360 * Sgn(PH - prevPH) prevPH = PH UWP = PH + offSet 'UnWrapped Phase. DB = 20 * Log(M(F, 2 * p)) / Log(10): 'Convert magnitude to DB values. Print #2, Using p$; M(F, 1); DB; UWP Print "."; 'Something to look at. Next F: Next p Print #2, " ": Print #2, ".ENDS" Print "Finished. Result saved in file "; ufn$; ".LIB" Close #2 End
Sub HelpMessage Print "WBA 7/94. This utility converts an S-parameter file *.S2P having" Print "a magnitude and angle (degrees) format into a PSPICE subcircuit" Print "file *.LIB which uses the Analog Behavioral Model option." Print "The source file should be in the current directory." Print "A 50 ohm reference impedance is assumed." Print "GHz frequency units are assumed unless the *.S2P files contains" Print "a header record beginning with '#' and followed by 'MHz'" Print " " Print "USAGE: S2P2LIB *.S2P " End Sub
Sub ParseDataLine Dim As Long k, CH, SP Dim D$, CH$ k = 1: D$ = "" Print "L$="; L$ ' debug ' <<<<<<<<<<<<<<<<<<<<<<<<< where is this L$ coming from??? Share it!!! Print "LenL$="; Len(L$) ' debug For CH = 1 To Len(L$) + 1 Print "CH="; CH ' debug CH$ = Mid$(L$ + " ", CH, 1) Print "CH$="; CH$ ' debug 'Print "k="; k 'debug If CH$ <> " " Then D$ = D$ + CH$ ': SP = 0 'Print "CH$="; CH$ ' debug Print "D$="; D$ 'debug Print "Val(D$)="; Val(D$) 'debug If CH$ = " " And SP = 0 Then D(k) = Val(D$): k = k + 1: SP = 1: D$ = " " 'something wrong here Print "SP="; SP 'debug Print "D(k)="; D(k) 'debug <<< added (k) to D Print "k="; k 'debug 'Print "D(k)="; D(k) 'debug Next 'CH If k <> 10 Then Print "Error: Didn't find 9 numbers parsing the following data line:" Print "" Print "SP="; SP 'debug Print "D(k)="; D(k) 'debug Print "D$="; D$ 'debug Print "CH$="; CH$ ' debug Print "k="; k 'debug Print "" Print L$ Print "" Print "Check *.S2P file": End End If End Sub
|
|
|
Post by busaboy on Mar 2, 2023 2:08:43 GMT
I commented out all the "Print XX 'debug" lines in the file you pasted. The program still thinks the input file "ATF.s2p" is bad, "Error: Didn't find 9 numbers parsing the following data line: "
All the variants of the program seem to process the last "If CH$" line wrong. It may be processing the first "If CH$" line wrong as well.
The original program, S2P2LIB1.bas the line is: If CH$ = "" And SP = 0 Then D(k) = Val(D$): k = k + 1: SP = 1: D$ = " "
The program thinks "ATF.s2p" is bad when it isn't. That's when I added all the "Print" debug lines hoping to spot what is wrong. For one, k never increments above 1. It should be 1-9 and 10 drops to End Sub.
I think CH$ = "" is a typo in the PDF so I modified the line to be: If CH$ = " " And SP = 0 Then D(k) = Val(D$): k = k + 1: SP = 1: D$ = " "
Unfortunately changing CH$ = "" to CH$ = " " caused the "subscript out of range" error. If you ignore the error, k does increment but there is still something wrong with this line.
FYI
ATF.s2p is a simplified files with only 1 line of data. A real file would have many lines of data.
k = count of numbers in each line of the file, ATF.s2p. The count should be 9 like shown below. k is supposed to increment from 1-9 and 10 drops to End Sub. This causes the next line in the file to be read. 1.0 0.93 -41 5.58 143 0.050 71 0.45 -23
SP = " " or Spaces
L$ = Line of data in ATF.s2p as it's being "processed". Since ATF.s2p only has one line, L$=1.0 0.93 -41 5.58 143 0.050 71 0.45 -23
CH = number count
CH$ = character, For above line of data, CH$=1 CH$=. CH$=0 CH$= "blank"
|
|
|
Post by bplus on Mar 2, 2023 3:15:32 GMT
OK I threw out your parse sub and did it my own way!
Option _Explicit ' lets see what needs DIM '$Debug 'S2P2LIB1-- converts S2P tables to PSpice-compatible frequency-response tables. 'Written in QuickBASIC (v4.5). See 'HelpMessage' SUB for additional comments. 'DECLARE SUB ParseDataLine () ' dont need this 'DECLARE SUB HelpMessage () ' ditto 'Dim D(16), M(50, 9)
ReDim Shared D(1 To 16) ' <<<< REDIM to make D a dynamic array Dim Shared M(50, 9) ' As Single >> ditto Dim Shared L$ ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<< this needs to get into Parse Sub 'Common Shared D(), M(), L$ ' >>>>> let do this without Common and before Dim them
Dim As Long False, True, DataLine, EODat, InTheData, k, p, offSet, F Dim C$, ufn$, HDR$, G$, M$, p$ Dim S$(1 To 4), E$(1 To 4) Dim As Single prevPH, PH, UWP, DB
False = 0: True = Not False DataLine = 0: EODat = False 'C$ = Command$ ' needs changes so Help screens are displayed C$ = "ATF.s2p" 'Decomment and edit in uncompiled version. If UCase$(Right$(C$, 4)) = ".S2P" Then 'Plausible command$ found. ufn$ = Left$(C$, Len(C$) - 4) Else Call HelpMessage ': System End If Open C$ For Input As #1 Open ufn$ + ".LIB" For Output As #2 Print #2, ".SUBCKT " + ufn$ + " 1 2 3; Port1 Port2 Common" Print #2, "*Subcircuit generated by S2P2LIB1.EXE on " + Date$ While Not (EOF(1) Or EODat) Line Input #1, L$ L$ = LTrim$(L$) 'Get rid of any leading spaces. If Left$(L$, 1) = "!" Then Print #2, "*" + Right$(L$ + " ", Len(L$)) If Left$(L$, 1) = "#" Then HDR$ = UCase$(L$): Print #2, "*" + L$ If Val(L$) > 0 Then InTheData = True ParseDataLine ' loads D() with file numbers DataLine = DataLine + 1 For k = 1 To 9: M(DataLine, k) = D(k): Next End If If Val(L$) = 0 And InTheData = True Then EODat = True Wend Close #1 Print #2, " ": Print #2, "R1N 1 5 -50": Print #2, "R1P 5 7 100" Print #2, "R2N 2 4 -50": Print #2, "R2P 4 6 100" S$(1) = "*S11 FREQ DB PHASE": S$(2) = "*S21 FREQ DB PHASE" S$(3) = "*S12 FREQ DB PHASE": S$(4) = "*S22 FREQ DB PHASE" E$(1) = "E11 7 9 FREQ {V(5,3)}=": E$(2) = "E21 6 8 FREQ {V(5,3)}=" E$(3) = "E12 9 3 FREQ {V(4,3)}=": E$(4) = "E22 8 3 FREQ {V(4,3)}=" G$ = "_+_(###.##gHz_,+###.##_, +###.##)" 'Format for gHz data M$ = "_+_(#####.##MHz_,+###.##_, +###.##)" 'Format for MHz data If InStr(HDR$, "MHZ") Then p$ = M$ Else p$ = G$ For p = 1 To 4 'Build S11, S21, S12, and S22 blocks in sequence. Print #2, " ": Print #2, S$(p): Print #2, E$(p) offSet = 0: prevPH = 0 'Clear variables used to unwrap phase. For F = 1 To DataLine 'Successive frequency values. PH = M(F, 2 * p + 1) 'Current phase data. If Abs(PH - prevPH) > 180 Then offSet = offSet - 360 * Sgn(PH - prevPH) prevPH = PH UWP = PH + offSet 'UnWrapped Phase. DB = 20 * Log(M(F, 2 * p)) / Log(10): 'Convert magnitude to DB values. Print #2, Using p$; M(F, 1); DB; UWP Print "."; 'Something to look at. Next F: Next p Print #2, " ": Print #2, ".ENDS" Print "Finished. Result saved in file "; ufn$; ".LIB" Close #2 End
Sub HelpMessage Print "WBA 7/94. This utility converts an S-parameter file *.S2P having" Print "a magnitude and angle (degrees) format into a PSPICE subcircuit" Print "file *.LIB which uses the Analog Behavioral Model option." Print "The source file should be in the current directory." Print "A 50 ohm reference impedance is assumed." Print "GHz frequency units are assumed unless the *.S2P files contains" Print "a header record beginning with '#' and followed by 'MHz'" Print " " Print "USAGE: S2P2LIB *.S2P " End Sub
Sub ParseDataLine Dim As Long i, spaceF Dim b$, c$ ReDim temp$(1 To 1) 'remove extra spaces in L$ so just 1 separates each data item For i = 1 To Len(L$) c$ = Mid$(L$, i, 1) If c$ = " " Then If spaceF Then ' skip it! already have space Else b$ = b$ + c$: spaceF = 1 End If Else b$ = b$ + c$: spaceF = 0 End If Next L$ = b$ ' with extra spaces removed
Split L$, " ", temp$() For i = 1 To 9 D(i) = Val(_Trim$(temp$(i))) Print "i, temp$(i), "; i, temp$(i), D(i) Next End Sub
Sub Split (SplitMeString As String, delim As String, loadMeArray() As String) Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim) dpos = InStr(curpos, SplitMeString, delim) Do Until dpos = 0 loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos) arrpos = arrpos + 1 If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String curpos = dpos + LD dpos = InStr(curpos, SplitMeString, delim) Loop loadMeArray(arrpos) = Mid$(SplitMeString, curpos) ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct End Sub
The file got written without errors thrown. Is it right?
.SUBCKT ATF 1 2 3; Port1 Port2 Common *Subcircuit generated by S2P2LIB1.EXE on 03-01-2023 * ATF-10236 Truncated for debug * S-PARAMETERS at Vds=2V Id=25mA *# ghz s ma r 50 *FREQ S11 S21 S12 S22 *GHZ MAG ANG MAG ANG MAG ANG MAG ANG R1N 1 5 -50 R1P 5 7 100 R2N 2 4 -50 R2P 4 6 100 *S11 FREQ DB PHASE E11 7 9 FREQ {V(5,3)}= +( 1.00gHz,- 0.63, - 41.00) *S21 FREQ DB PHASE E21 6 8 FREQ {V(5,3)}= +( 1.00gHz,+ 14.93, +143.00) *S12 FREQ DB PHASE E12 9 3 FREQ {V(4,3)}= +( 1.00gHz,- 26.02, + 71.00) *S22 FREQ DB PHASE E22 8 3 FREQ {V(4,3)}= +( 1.00gHz,- 6.94, - 23.00) .ENDS
OK D didn't have to be Dynamic but it doesn't matter. I was setting up for Split to load D() array directly but Split is setup to do Strings. So I had to remove extra spaces in L$ data line from the file, split L$ into temp$() and then take Val of temp to convert to single number type. So main code picks up D() and does what it does to create file.
|
|
|
Post by busaboy on Mar 2, 2023 4:00:59 GMT
Yes
I have an alternate program and confirmed the output is correct.
I will look at the changes you made.
Thank You!
|
|
|
Post by bplus on Mar 2, 2023 16:47:44 GMT
There most certainly IS a way to parse a line of data delineated by spaces without Split.
Now that I know that's all we were doing in parse, I can rewrite that sub to work without Split. It would pretty much go the way I did to eliminate extra spaces from the L$ line.
|
|
|
Post by bplus on Mar 2, 2023 16:58:28 GMT
Well that didn't take long:
Option _Explicit ' lets see what needs DIM '$Debug 'S2P2LIB1-- converts S2P tables to PSpice-compatible frequency-response tables. 'Written in QuickBASIC (v4.5). See 'HelpMessage' SUB for additional comments. 'DECLARE SUB ParseDataLine () ' dont need this 'DECLARE SUB HelpMessage () ' ditto 'Dim D(16), M(50, 9)
ReDim Shared D(1 To 16) ' <<<< REDIM to make D a dynamic array Dim Shared M(50, 9) ' As Single >> ditto Dim Shared L$ ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<< this needs to get into Parse Sub 'Common Shared D(), M(), L$ ' >>>>> let do this without Common and before Dim them
Dim As Long False, True, DataLine, EODat, InTheData, k, p, offSet, F Dim C$, ufn$, HDR$, G$, M$, p$ Dim S$(1 To 4), E$(1 To 4) Dim As Single prevPH, PH, UWP, DB
False = 0: True = Not False DataLine = 0: EODat = False 'C$ = Command$ ' needs changes so Help screens are displayed C$ = "ATF.s2p" 'Decomment and edit in uncompiled version. If UCase$(Right$(C$, 4)) = ".S2P" Then 'Plausible command$ found. ufn$ = Left$(C$, Len(C$) - 4) Else Call HelpMessage ': System End If Open C$ For Input As #1 Open ufn$ + ".LIB" For Output As #2 Print #2, ".SUBCKT " + ufn$ + " 1 2 3; Port1 Port2 Common" Print #2, "*Subcircuit generated by S2P2LIB1.EXE on " + Date$ While Not (EOF(1) Or EODat) Line Input #1, L$ L$ = LTrim$(L$) 'Get rid of any leading spaces. If Left$(L$, 1) = "!" Then Print #2, "*" + Right$(L$ + " ", Len(L$)) If Left$(L$, 1) = "#" Then HDR$ = UCase$(L$): Print #2, "*" + L$ If Val(L$) > 0 Then InTheData = True ParseDataLine ' loads D() with file numbers DataLine = DataLine + 1 For k = 1 To 9: M(DataLine, k) = D(k): Next End If If Val(L$) = 0 And InTheData = True Then EODat = True Wend Close #1 Print #2, " ": Print #2, "R1N 1 5 -50": Print #2, "R1P 5 7 100" Print #2, "R2N 2 4 -50": Print #2, "R2P 4 6 100" S$(1) = "*S11 FREQ DB PHASE": S$(2) = "*S21 FREQ DB PHASE" S$(3) = "*S12 FREQ DB PHASE": S$(4) = "*S22 FREQ DB PHASE" E$(1) = "E11 7 9 FREQ {V(5,3)}=": E$(2) = "E21 6 8 FREQ {V(5,3)}=" E$(3) = "E12 9 3 FREQ {V(4,3)}=": E$(4) = "E22 8 3 FREQ {V(4,3)}=" G$ = "_+_(###.##gHz_,+###.##_, +###.##)" 'Format for gHz data M$ = "_+_(#####.##MHz_,+###.##_, +###.##)" 'Format for MHz data If InStr(HDR$, "MHZ") Then p$ = M$ Else p$ = G$ For p = 1 To 4 'Build S11, S21, S12, and S22 blocks in sequence. Print #2, " ": Print #2, S$(p): Print #2, E$(p) offSet = 0: prevPH = 0 'Clear variables used to unwrap phase. For F = 1 To DataLine 'Successive frequency values. PH = M(F, 2 * p + 1) 'Current phase data. If Abs(PH - prevPH) > 180 Then offSet = offSet - 360 * Sgn(PH - prevPH) prevPH = PH UWP = PH + offSet 'UnWrapped Phase. DB = 20 * Log(M(F, 2 * p)) / Log(10): 'Convert magnitude to DB values. Print #2, Using p$; M(F, 1); DB; UWP Print "."; 'Something to look at. Next F: Next p Print #2, " ": Print #2, ".ENDS" Print "Finished. Result saved in file "; ufn$; ".LIB" Close #2 End
Sub HelpMessage Print "WBA 7/94. This utility converts an S-parameter file *.S2P having" Print "a magnitude and angle (degrees) format into a PSPICE subcircuit" Print "file *.LIB which uses the Analog Behavioral Model option." Print "The source file should be in the current directory." Print "A 50 ohm reference impedance is assumed." Print "GHz frequency units are assumed unless the *.S2P files contains" Print "a header record beginning with '#' and followed by 'MHz'" Print " " Print "USAGE: S2P2LIB *.S2P " End Sub
Sub ParseDataLine Dim As Long i, spaceF, j Dim b$, c$ For i = 1 To Len(L$) c$ = Mid$(L$, i, 1) If c$ = " " Then If spaceF Then ' skip it! already have space Else j = j + 1 ' we have data item D(j) = Val(b$) b$ = "" spaceF = 1 End If Else b$ = b$ + c$: spaceF = 0 ' building a number End If Next If Len(b$) Then ' handle left overs j = j + 1 ' we have data item D(j) = Val(b$) End If
Print "check data:" For i = 1 To j Print i, D(i) Next End Sub
Definitely nicer as D() is loaded directly and Split sub not needed.
|
|
|
Post by busaboy on Mar 2, 2023 21:57:25 GMT
I just noticed that yesterdays version left out the file name, ATF. This version fixes it. .SUBCKT 1 2 3; Port1 Port2 Common Todays includes ATF .SUBCKT ATF 1 2 3; Port1 Port2 Common Test file BFP780.s2p, fails. I get a "Line 41: (in main module) Subscript out of range" error. I checked BFP780.s2p with a text editor, but can't find anything wrong with it. My other program converts it fine. Test files BFR90AC.S2P and 2BF996S.S2P work. Test files.zip (253.08 KB)
|
|
|
Post by bplus on Mar 3, 2023 2:37:07 GMT
OK easy fix, that other data file had 75 lines of data and M() was only setup for 50. I switched it to 100 and changed the file to BFP780.s2p It ran fine here are results: Attachments:Fix for BPF780.zip (4.35 KB)
|
|
|
Post by busaboy on Mar 3, 2023 3:12:23 GMT
Thank you. I found the same issue but it took me way longer. ;-)
|
|