## Copyright (C) 2019 Marcin Mleczko ## ## This file is free software: you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## -*- texinfo -*- ## @deftypefn {} {@var{ltsRes} =} LTspice2Ovtave (@var{filename}) ## This function loads simulation results created by LTspice. ## ## @var{filename} points to the '.raw' file which holds your simulation results ## in a binary data format. LTspice creates this file during simulation. ## (If your schematic lives in MySchematic.asc than your simulation results ## will end up in MySchematic.raw) ## ## @var{ltsRes} is a struct containing the data found in @var{filename}. It has ## several members with hopefully selfexplanatory names. I. e. ## varNames holds a list of net names (voltages) and current names as definend ## in the schematic in LTspice. varData_StPar1 holds the correspondig data. ## ## If a parameter sweep (.step param directive) is detected, varData_StPar1, ## varData_StPar2,.. are created, each for every swept parameter combination. ## stepParams stores a list of parameter combinations with matching indices. ## ## Currently only transient simulations (.tran) are supported. No interpolation ## or data smoothing has been implemented. ## @end deftypefn ## Author: Marcin Mleczko ## Description: Load LTspice simulation results into octave workspace structure ## Version: 0.0.7 function ltsRes=LTspice2Octave(filename) [fid msg]=fopen(filename,'rb'); if (fid == -1) error(msg); return; endif [buf, count] = fread(fid, 10, 'char', 0, 'ieee-le'); if (buf(2) == 0) format = 'binary'; fseek(fid,0,"bof"); else format='ascii'; error("ascii format not supported"); fclose(fid); return end len_header=0; str_header=''; while ( 1 ) [buf, count] = fread(fid, 100, 'uint16=>char', 0, 'ieee-le'); len_header=len_header+count; str_header=[str_header buf']; idx_str_Bin=strfind (str_header, 'inary'); if (idx_str_Bin ) len_header=idx_str_Bin+6; str_header=str_header(1:len_header); break; end end clear buf count; [s, e, te, m, ts]=regexp(str_header, "Plotname:(.*)\n",'dotexceptnewline'); ltsRes.simType=ts{1,1}{1,1}; clear s e te m ts; if ( length(strfind(ltsRes.simType, "Transient")) < 1) error("Only transient simulations (.tran) supported for now..."); return; endif [s, e, te, m, ts]=regexp(str_header, "Flags:(.*)\n",'dotexceptnewline'); ltsRes.simFlags=ts{1,1}{1,1}; clear s e te m ts; if ( length(strfind(ltsRes.simFlags, "stepped"))>0) logfid=fopen([filename(1:end-3) "log"], "rb"); % get the step params from the log file logString=0;k=1; while ( 1 ) logString=fgetl(logfid); if (length(logString) < 1) % empty line continue; elseif (logString(1) < 0) % EOF break; endif if (length (strfind(logString, ".step")) > 0) ltsRes.stepParams{1,k}=logString(6:end); k++; endif endwhile fclose(logfid); clear logString, k; else ltsRes.stepParams{1,1}="not a stepped simulation"; endif [s, e, te, m, ts]=regexp(str_header, "No\\.\\s*Variables:(.*)\n",'dotexceptnewline'); ltsRes.noVars=uint64(str2double(ts{1,1})-1); clear s e te m ts; [s, e, te, m, ts]=regexp(str_header, "No\\.\\s*Points:(.*)\n",'dotexceptnewline'); ltsRes.noPts=uint64(str2double(ts{1,1})./length(ltsRes.stepParams)); clear s e te m ts; [s, e, te, m, ts]=regexp(str_header, "Offset:(.*)\n",'dotexceptnewline'); ltsRes.Offset=str2double(ts{1,1}); clear s e te m ts; [s, e, te, m, ts]=regexp(str_header, "Variables:\\s*\n(.*)Binary:",'dotall'); for k=1:1:ltsRes.noVars [s, e, te, m, tsVn]=regexp(ts{1,1}{1,1}, ["\n\\s*(" num2str(k) ")\\s*(\\S*)\\s*(\\S*)\\s*\n"],'dotexceptnewline','ignorecase'); [num2str(k) " " tsVn{1,1}{1,2}]; ltsRes.varNames{1,k}=tsVn{1,1}{1,2}; ltsRes.varTypes{1,k}=tsVn{1,1}{1,3}; end clear s e te m ts tsVn str_Header; bin_data_start=len_header*2; fseek(fid, bin_data_start,"bof"); [ltsRes.time count]=fread (fid, ltsRes.noPts, 'double' ,4*ltsRes.noVars,'ieee-le'); ltsRes.time=abs(ltsRes.time)+ltsRes.Offset; %every var value is stored as float (= 4 bytes) for k=1:1:length(ltsRes.stepParams) for l=1:1:ltsRes.noVars rpos=bin_data_start+(8+4*ltsRes.noVars).*ltsRes.noPts.*(k-1) +8+4*(l-1); fseek(fid, rpos,"bof"); count=uint64(0); max_frd_attps=5; for m=1:1:max_frd_attps [ltsRes.(["varData_StPar" num2str(k)])(:,l) cnt]=fread (fid, ltsRes.noPts, 'float', 4*(ltsRes.noVars-1)+8,'ieee-le'); count=count+uint64(cnt); if (uint64(count) == ltsRes.noPts) break; elseif ( uint64(count) ~= ltsRes.noPts && m==max_frd_attps ) error("not enough points read... k:%d l:%d ltsRes.noPts:%d count:%d",k, l, ltsRes.noPts, count ); endif endfor endfor endfor fclose(fid); clear k l; endfunction