File: BitsPlusMovieDemo.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (131 lines) | stat: -rw-r--r-- 5,175 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
% BitsPlusMovieDemo
%
% BitsPlusMovieDemo displays a counterphase flickering grating, by lookup
% table animation, using the Bits++ box.
%
% Note that you need to precompute the cluts and write them into
% offscreen memory in advance, so that the blits happen fast.  In
% this example, each clut goes into its own offscreen window.  In
% real applications, we have found that the precomputation is considerably
% faster if we allocate one large offscreen window and put each clut
% into a different rect inside of it.

% 9/20/02  dhb  Version created from ClutMovieDemo.
% 10/xx/02 jmh  Fixed it up.
% 11/4/02  dhb, jmh Comments, etc.
% 9/20/03  dhb  No more calls to BitsPlus mex file.

clear; close all

% Define screen
whichScreen=max(Screen('Screens'));

% Create a sinusoidal image in a Matlab matrix. The grating is
% scaled between 1 and 255. The creation happens in two steps. First
% create a sinusoidal vector, then replicate this vector to produce a
% sinusoidal image. The replication is done by an outer product. This is
% not the fastest way to do it in Matlab, but it is a little clearer.
nPixels = 256;
cyclesPerImage = 4;
sinVector = 1+(1+sin(2*pi*cyclesPerImage*(1:nPixels)/nPixels))/2*254;
sinImage = ones(nPixels,1)*sinVector;

% Create a set of color lookup tables (cluts) for animating the
% grating. Each clut starts life as a 256 by three matrix. But
% since we write them into the frame buffer to talk to the Bits++
% box, we then create an offscreen window for each clut and write
% it in.  This needs to be done in advance so that the blit of
% the lookup table is fast. 
%
% The computed set of cluts produces one cycle of counterphase flicker.
% We also create a uniform clut (offClut) to initialize the display.
%
% The variable nCluts determines the number of temporal quantization intervals.
%
% This routine does not do gamma correction -- it's purpose is just
% to show how to interface to the Bits++.
nCluts = 80;
theCluts = zeros(256,3,nCluts);
theContrasts = sin(2*pi*(0:nCluts-1)/nCluts);
fprintf('Computing %g cluts: ',nCluts);

% Open up the a window on the screen & initialize the clut.
% This is done by calling the Screen function of the Psychophysics
% Toolbox. We need to open the onscreen window first, so that
% the offscreen storage allocated subsequently is properly
% matched to the onscreen frame buffer.
[window,screenRect] = Screen(whichScreen,'OpenWindow',128,[],32);
Screen('LoadClut', window, (0:255)'*ones(1,3));

% Generate a clut for the background and use USB interface
% to write it into Bits++.
offClut = ones(256,3)*(2^14-1)/2;
BitsPlusSetClut(window,offClut);

% Magic rect for writing the clut into the frame buffer.
bitsPlusRect = [0     0   524     1];

% Draw grating onto the screen using PsychToolbox.
% We don't see it at this stage becuase we've got
% a uniform clut in the Bits++.
Screen(window,'PutImage',sinImage); 
 
% Loop through, compute clut, push into created offscreen memory.
for i = 1:nCluts
	if (rem(i,10) == 0)
		fprintf('%g ',i);
	end
	contrast = theContrasts(i);
	lowValDev = (1-contrast)/2;
	highValDev = (1+contrast)/2;
	clutEntries = round(linspace(lowValDev*(2^14-1),highValDev*(2^14-1),256)');
	theCluts(:,:,i) = [clutEntries clutEntries clutEntries];
	bitsPlusClutRow(i,:,:) = BitsPlusEncodeClutRow(theCluts(:,:,i));  % converts to 1X524X3
	[w(i),temp]=Screen(window,'OpenOffscreenWindow',[],bitsPlusRect);
	Screen(w(i),'PutImage',bitsPlusClutRow(i,:,:),temp);	% draw value of CLUT into offscreen windows
end
fprintf('. Done.\n');				

% Animate the clut.  The timing works a little different from
% the way we think about a conventional clut.  We want to write
% the clut into the first line of the frame buffer after the raster
% has gone by, so that we don't get half of one clut and half of
% another.  The new clut won't latch into the Bits++ until the
% raster goes by the first line of the frame buffer, i.e. at the
% start of the next frame.  So the timing sequence is a) wait
% for blanking, b) delay a suitable amount so that the raster
% has gone by the first line, c) write in the new clut.  This clut
% then takes effect on the next frame, not the one where we wrote it.
% The parameter rasterDelay below determines what we mean by "suitable
% amount."  Also, we need a last call to WaitBlanking at the end of the
% loop so that we don't truncate the last frame.
nCycles=8;
clutCounter = 1;
rasterDelay = 0.003;
s0=0;f0=0;f=0;s=0;rem(1,1);
Screen(window,'WaitBlanking'); WaitSecs(rasterDelay);
[f0,s0]=Screen(window,'PeekBlanking');
for i=1:nCluts*nCycles
	Screen('CopyWindow',w(clutCounter),window,bitsPlusRect,bitsPlusRect);
	Screen(window,'WaitBlanking'); WaitSecs(rasterDelay);
	s(i)=GetSecs;
	if (clutCounter == nCluts); clutCounter = 1; else; clutCounter = clutCounter +1; end
end
s=diff(s);
frames1=sum(s)*FrameRate(whichScreen)-length(s);
Screen(window,'WaitBlanking'); WaitSecs(rasterDelay);
[f,s]=Screen(window,'PeekBlanking');

% Write the off clut back in so we end with a uniform field
WaitSecs(1);
f=f-f0;
s=s-s0;
clutsShown=nCluts*nCycles;

% Close the window.
Screen(window,'Close');

% Set the Bits++ clut to linear ramp
BitsPlusBlank(whichScreen);