Code covered by the BSD License  

Highlights from
Read binary Rigol waveforms

from Read binary Rigol waveforms by Paul Wagenaars
Read binary waveform (.wfm) files stored by Rigol oscilloscopes

readRigolWaveform(filename, varargin)
function varargout = readRigolWaveform(filename, varargin)
%Reads a binary waveform (.wfm) file stored by a Rigol oscilloscope.
%
% readRigolWaveform(filename) Displays information about the recorded
% signal(s) in the waveform file and plots the signal(s).
%
% filename - filename of Rigol binary waveform
%
%
% [y, nfo] = readRigolWaveform(filename) Reads the signal(s) in the
% specified file.
%
% filename - filename of Rigol binary waveform
% y        - column array with data. If both channels were recorded it
%            contains two channels.
% nfo      - structure with time axis and other information
%            nfo.x0: time corresponding to first sample
%            nfo.dx: sample time (= 1 / sample_frequency)
%            nfo.notes: text field other oscilloscope settings
%

if ~exist('filename', 'var')
    error('Error using this function. For help type: help readRigolWaveform');
end

if nargout == 0
    fprintf('---\nFilename: %s\n', filename);
end

%% Open the file and check the header
if ~exist(filename, 'file')
    error('Specified file (%s) doesn''t exist.', filename);
end

fid = fopen(filename, 'r');
if fid == -1
    error('Unable to open %s for reading.', filename);
end

% Check first two bytes
header = fread(fid, 2, '*uint8');
if (header(1) ~= 165) || (header(2) ~= 165)
    error('Incorrect first two bytes. This files does not seem to be a Rigol waveform file.');
end


%% Check which channels were recorded
fseek(fid, 49, -1);
ch1Recorded = (fread(fid, 1, '*uint8') == 1);
fseek(fid, 73, -1);
ch2Recorded = (fread(fid, 1, '*uint8') == 1);


%% Nr. of data points
fseek(fid, 28, -1);
N = fread(fid, 1, 'uint32=>double');
if nargout == 0
    fprintf('Record length: %dk\n', N / 1024);
end


%% Time axis
if nargout == 0
    fprintf('- Time axis\n');
end
fseek(fid, 84, -1);
time.scale = fread(fid, 1, 'uint64=>double') * 1e-12;
time.delay = fread(fid, 1, 'int64=>double') * 1e-12;
fseek(fid, 100, -1);
time.fs = fread(fid, 1, 'single=>double');

nfo.x0 = -N / 2 / time.fs + time.delay;
nfo.dx = 1 / time.fs;
if nargout == 0
    fprintf('    scale: %ss/div\n', nr2str(time.scale));
    fprintf('    delayed: %ss\n', nr2str(time.delay));
    fprintf('    sample frequency: %sS/s\n', nr2str(time.fs));
end


%% Read ch1 and ch2 information
if ch1Recorded
    ch1Info = readChannelInfo(fid, 1, (nargout == 0));
else
    ch1Info = [];
end
if ch2Recorded
    ch2Info = readChannelInfo(fid, 2, (nargout == 0));
else
    ch2Info = [];
end


%% Read ch1 and ch2 data
fseek(fid, 272, -1);
if ch1Recorded
    ch1Data = (125 - fread(fid, N, 'uint8=>double')) / 250 * 10 * ch1Info.scale;
    ch1Data = ch1Data - ch1Info.position;
end
if ch2Recorded
    ch2Data = (125 - fread(fid, N, 'uint8=>double')) / 250 * 10 * ch2Info.scale;
    ch2Data = ch2Data - ch2Info.position;
end


%% Trigger mode
if nargout == 0
    fprintf('- Trigger\n');
end
fseek(fid, 142, -1);
triggermode = fread(fid, 1, '*uint16');
if triggermode == hex2dec('0000')
    trigger.mode = 'edge';
elseif triggermode == hex2dec('0101')
    trigger.mode = 'pulse';
elseif triggermode == hex2dec('0303')
    trigger.mode = 'vid';
elseif triggermode == hex2dec('0202')
    trigger.mode = 'slope';
elseif triggermode == hex2dec('0004')
    trigger.mode = 'alt';
elseif triggermode == hex2dec('0505')
    trigger.mode = 'pattern';
elseif triggermode == hex2dec('0606')
    trigger.mode = 'duration';
else
    error('Unknown trigger mode.');
end
if nargout == 0
    fprintf('    mode: %s\n', trigger.mode);
end

triggersource = fread(fid, 1, '*uint8');
if triggersource == 0
    trigger.source = 'ch1';
elseif triggersource == 1
    trigger.source = 'ch2';
elseif triggersource == 2
    trigger.source = 'ext';
elseif triggersource == 3
    trigger.source = 'ext/5';
elseif triggersource == 5
    trigger.source = 'acLine';
elseif triggersource == 7
    trigger.source = 'dig.ch';
else
    error('Unknown trigger source.');
end
if nargout == 0
    fprintf('    source: %s\n', trigger.source);
end

%% Close file
fclose(fid);


%% Plot signals
if nargout == 0
    figure;
    tf = nfo.x0 + (N - 1) * nfo.dx;
    t = linspace(nfo.x0, tf, N);
    
    if exist('ch1Data', 'var') && exist('ch2Data', 'var')
        plot(t, ch1Data, t, ch2Data);
        legend('Ch1', 'Ch2');
    elseif exist('ch1Data', 'var')
        plot(t, ch1Data);
        legend('Ch1');
    else
        plot(t, ch2Data);
        legend('Ch2');
    end
    grid on;
    xlabel('Time (s)');
    ylabel('Voltage (V)');
end


%% Assign output arguments
if nargout >= 1
    % Assign signal y
    if ch1Recorded && ~ch2Recorded
        y = ch1Data;
    elseif ~ch1Recorded && ch2Recorded
        y = ch2Data;
    else
        y = [ch1Data ch2Data];
    end
    varargout{1} = y;
end
if nargout >= 2
    nfo.notes = createNotes(time, ch1Info, ch2Info, trigger);
    varargout{2} = nfo;
end


end  % end of main function


%% Function: readChannelInfo
function [ info ] = readChannelInfo(fid, chNr, printInfo)
    % Data addresses (decimal) for ch1 and ch2
    % [scale, position, probe attenuation]
    allAddresses = [
        36 40 46
        60 64 70
    ];
    adrs = allAddresses(chNr, :);
    
    if printInfo
        fprintf('- Ch%d\n', chNr);
    end
       
    % Vertical scaling
    fseek(fid, adrs(1), -1);
    info.scale = fread(fid, 1, 'uint32=>double') * 1e-6;
    if printInfo
        fprintf('    scale: %sV/div\n', nr2str(info.scale));
    end
    
    % Vertical position
    fseek(fid, adrs(2), -1);
    info.position = fread(fid, 1, 'int16=>double') / 25 * info.scale;
    if printInfo
        fprintf('    position: %sV\n', nr2str(info.position));
    end

    % Probe attenuation
    fseek(fid, adrs(3), -1);
    probeatten = fread(fid, 1, '*uint16');
    if probeatten == hex2dec('3F80')
        info.probeatten = 1;
    elseif probeatten == hex2dec('4120')
        info.probeatten = 10;
    elseif probeatten == hex2dec('42C8')
        info.probeatten = 100;
    elseif probeatten == hex2dec('447A')
        info.probeatten = 1000;
    else
        error('Unknown ch%d probe attenuation.', chNr);
    end
    if printInfo
        fprintf('    probe attenuation: %gx\n', info.probeatten);
    end
end


%% Function: createNotes
function [ notes ] = createNotes(timeInfo, ch1Info, ch2Info, triggerInfo)
    notes = sprintf('time.scale = %ss/div\n', nr2str(timeInfo.scale));
    notes = sprintf('%stime.delay = %ss\n', notes, nr2str(timeInfo.delay));
    notes = sprintf('%stime.fs = %sS/s\n', notes, nr2str(timeInfo.fs));
    if ~isempty(ch1Info)
        notes = sprintf('%sch1.scale = %sV/div\n', notes, nr2str(ch1Info.scale));
        notes = sprintf('%sch1.position = %sV\n', notes, nr2str(ch1Info.position));
        notes = sprintf('%sch1.probe_attenuation = %gx\n', notes, ch1Info.probeatten);
    end
    if ~isempty(ch2Info)
        notes = sprintf('%sch2.scale = %sV/div\n', notes, nr2str(ch2Info.scale));
        notes = sprintf('%sch2.position = %sV\n', notes, nr2str(ch2Info.position));
        notes = sprintf('%sch2.probe_attenuation = %gx\n', notes, ch2Info.probeatten);
    end
    notes = sprintf('%strigger.mode = %s\n', notes, triggerInfo.mode);
    notes = sprintf('%strigger.source = %s\n', notes, triggerInfo.source);
end


%% Function: nr2str
function [ nrString ] = nr2str(number)
    absnr = abs(number);
    if absnr == 0
        nrString = sprintf('%g ', number);
    elseif absnr < 1e-9
        nrString = sprintf('%g p', number / 1e-12);
    elseif absnr < 1e-6
        nrString = sprintf('%g n', number / 1e-9);
    elseif absnr < 1e-3
        nrString = sprintf('%g u', number / 1e-6);
    elseif absnr < 1
        nrString = sprintf('%g m', number / 1e-3);
    elseif absnr < 1e3
        nrString = sprintf('%g ', number);
    elseif absnr < 1e6
        nrString = sprintf('%g k', number / 1e3);
    elseif absnr < 1e9
        nrString = sprintf('%g M', number / 1e6);
    else
        nrString = sprintf('%g G', number / 1e9);
    end
end

Contact us at files@mathworks.com