% RTC a pedestrian Real-Time Clock
%
% - start
% [par] = rtc
%
% - start with previously saved geometry
% [par] = rtc('i',par);
%
% - stop
% [par] = rtc % toggle
% rtc s % delete clock
%
% - display/retrieve current geometry parameters
% rtc d
% par=rtc('d');
%
% - update geometry
% [par] = rtc('u',par);
%
% - show parameter description
% rtc h
%
% - save current geometry in mat-file <fn> var <v>
% [par] = rtc('S',fn);
%
% - reload geometry from mat-file <fn> var <v>
% [par] = rtc('L',fn);
%
% EXAMPLE
% rtc; % start real-time clock
% par=rtc('d'); % get current geometry
% par.F.w=[[300 300]... % change figure position
% [400 400]];
% par.F.col=[.5 .75 .75]; % change figure bg color
% par.H.mark='diamond'; % change HR marker
% par.H.fcol=[1 1 0]; % change HR color
% par.M.fcol=[.4 .5 .75]; % change MIN color
% par.M.size=3; % change MIN size
% rtc('u',par); % apply
% pause(5); % run
% rtc; % stop
% pause(5); % wait
% rtc; % cont
% created:
% us 29-May-2003 / CSSM
% modified:
% us 01-Jun-2003 16:42:20 / TMW
%--------------------------------------------------------------------------------
function opar=rtc(id,npar)
persistent par
% START-UP SECTION
%--------------------------------------------------------------------------------
if ~nargin
% toggle
if ~isempty(par)
if strcmp(par.t.Running,'on')
par=do_stop(par);
set(par.v.th,'string','RTC> stopped. waiting for <rtc>');
else
par=do_start(par);
set(par.v.th,'string','');
end
else
if ~strcmp(lower(mfilename),'rtc')
error('RTC> file name MUST be: rtc.m');
end
% get clock parameters
par=get_par(par,0);
% create timer
par.t=timer('timerfcn',par.v.com{1});
set(par.t,'period',1);
set(par.t,'executionmode','fixedrate');
set(par.t,'startdelay',0);
set(par.t,'name','RTC');
% create clock
par=get_clock(par,1);
par=set_clock(par);
set(par.fh,'handlevisibility','off');
setappdata(par.fh,'par',par);
par=do_start(par);
end % ~isempty(par)
if nargout
opar=par;
end
return;
end % ~nargin
% RUN-TIME SECTION
%--------------------------------------------------------------------------------
if ~id
if ~isempty(par)
par=set_clock(par);
end
return;
end
clflg=0;
if ~isempty(par) & ishandle(par.fh)
set(par.fh,'handlevisibility','on');
end
switch id
% retrieve current geometry
case {'d' '-d'}
if ~isempty(par)
par=do_stop(par);
par.F.w=get(par.fh,'position');
disp('RTC> current geometry:');
disp(par);
par=do_start(par);
else
disp('RTC> not running');
end
% show geometry parameters
case {'h' '-h'}
if ~isempty(par)
par=do_stop(par);
par=get_par(par,1);
else
par=get_par(par,0);
end
dbtype(mfilename,par.v.hp);
if ~isempty(par)
if ~isempty(par.t)
par=do_start(par);
else
par=[];
end
end
% init with previous geometry parameters
case {'i' '-i'}
if ~isempty(par)
rtc s;
end
par=rtc;
par=do_stop(par);
if nargin > 1
t=par.t; % keep current timer
d=par.start;
par=npar;
par.t=t;
end
par=do_stop(par);
par=rtc('-u',par);
par=do_stop(par);
rtc('-u',par); % keep this logic!
par.start=d;
% update with new geometry parameters
case {'u' '-u' 'U'}
if ~isempty(par)
par=do_stop(par);
if nargin > 1
par=npar;
else
fh=findall(0,'tag','RTC');
par=getappdata(fh,'par');
end
wp=par.F.w; % keep current fig pos
par=get_clock(par,0);
par=set_clock(par);
par.F.w=wp;
if id ~= 'U'
set(par.fh,'resizefcn',''); % no recursion!
set(par.fh,'position',par.F.w);
set(par.fh,'resizefcn',par.v.com{3});
end
par.F.w=get(par.fh,'position');
setappdata(par.fh,'par',par);
par=do_start(par);
else
disp('RTC> not running');
end
% stop/delete clock
case {'s' '-s'}
par=do_stop(par);
clflg=1;
case {'S' '-S'}
if ~isempty(par)
par.F.w=get(par.fh,'position');
v=par;
v.t=[];
save(npar,'v');
else
disp('RTC> not running');
end
case {'L' '-L'}
tpar=get_par([],0);
v=load(npar);
v.v.ver=tpar.ver; % update
v.v.v=tpar.v;
if isfield(v,'v')
par=rtc('-i',v.v);
else
disp(sprintf('RTC> cannot load <%s>',npar));
end
otherwise
disp(sprintf('RTC> unknown option <%s>',id));
end
if nargout
opar=par;
end
if clflg
if ~isempty(par)
set(par.fh,'deletefcn',''); % no recursion!
delete(par.t);
delete(par.fh);
par=[];
end
elseif ~isempty(par) & ishandle(par.fh)
set(par.fh,'handlevisibility','off');
end
return;
%--------------------------------------------------------------------------------
function par=get_clock(par,mode)
% init date string
c=fix(clock);
par.v.ho=c(4)-1;
cdat=[datestr(clock,8) ' / ' datestr(clock,1)];
% create some vals once only
par.v.ha=pi/180*rem((360:-30:0)+90,360);
par.v.ma=pi/180*rem((360:-6:0)+90,360);
z=pi/180*(0:.1:359);
z=par.C.rad*exp(i*z);
x=real(z);
y=imag(z);
% set fig/axis props
if isempty(par.F.w) % try a default
s=get(0,'screensize');
wl=1.2*s(3:4)/4; % trial and error
par.F.w=[(2.3*wl)-[10 30] wl]; % wintel box
end
if mode
par.fh=figure(...
'position',par.F.w,...
'tag','RTC',...
'doublebuffer','on',...
'createfcn','',...
'deletefcn',par.v.com{2},... % stop timer
'resizefcn',par.v.com{3},... % update window
'menu','none',...
'toolbar','none',...
'pointer','watch',...
'numbertitle','off',...
'name','Real-Time Clock',...
'color',par.F.col);
else
cla;
set(par.fh,'color',par.F.col);
end
par.F.w=get(par.fh,'position');
set(gca,'xlim',par.F.xfac*par.C.rad*[-1 1]);
set(gca,'ylim',par.F.yfac*par.C.rad*[-1 1]);
axis off;
axis equal;
% set hand props
par.v.hh=line(0,0,1,... % HR hand
'linestyle',par.H.mod,...
'linewidth',par.H.wid,...
'color',par.H.col);
par.v.mh=line(0,0,2,... % MIN hand
'linestyle',par.M.mod,...
'linewidth',par.M.wid,...
'color',par.M.col);
par.v.sh=line(0,0,3,... % SEC hand
'linestyle',par.S.mod,...
'linewidth',par.S.wid,...
'color',par.S.col);
% set date string props
par.v.dh=text(0,par.D.frad,cdat,... % date string
'fontsize',par.D.fsize,...
'fontweight',par.D.fweight,...
'fontangle',par.D.fangle,...
'horizontalalignment','center');
xl=get(gca,'xlim');
yl=get(gca,'ylim');
par.v.th=text(xl(1),yl(2),'');
if ~isempty(par.D.fname)
set(par.v.dh,'fontname',par.D.fname);
end
% draw clock frame
line([x x(1)],[y y(1)],...
'linestyle',par.C.mod,...
'linewidth',par.C.wid,...
'color',par.C.col);
% .... clock MIN markers
x=x(1:60:end);
y=y(1:60:end);
line([x x(1)],[y y(1)],...
'marker',par.M.mark,...
'markersize',par.M.size,...
'markerfacecolor',par.M.fcol,...
'markeredgecolor',par.M.ecol,...
'linestyle','none',...
'color',par.M.col);
% .... clock HR markers
x=x(1:5:end);
y=y(1:5:end);
line([x x(1)],[y y(1)],...
'marker',par.H.mark,...
'markersize',par.H.size,...
'markerfacecolor',par.H.fcol,...
'markeredgecolor',par.H.ecol,...
'linestyle','none',...
'color',par.H.col);
% .... clock HR dials
th=text(par.H.frad*cos(par.v.ha(1:end-1)),...
par.H.frad*sin(par.v.ha(1:end-1)),...
num2str([12 1:11].'),...
'fontsize',par.H.fsize,...
'fontweight',par.H.fweight,...
'fontangle',par.H.fangle,...
'horizontalalignment','center');
if ~isempty(par.H.fname)
set(th,'fontname',par.H.fname);
end
return;
%--------------------------------------------------------------------------------
function par=set_clock(par)
c=fix(clock);
hr=rem(c(4)-1,12)+2;
mn=c(5)+1;
sc=c(6)+1;
hra=par.v.ha(hr)-pi*(mn-1)/360;
plot_hand(1,hr,par,par.H.len,hra,par.v.hh);
plot_hand(2,mn,par,par.M.len,par.v.ma(mn),par.v.mh);
plot_hand(3,sc,par,par.S.len,par.v.ma(sc),par.v.sh);
if c(4) ~= par.v.ho
par.v.ho=c(4);
cdat=[datestr(clock,8) ' / ' datestr(clock,1)];
set(par.v.dh,'string',cdat);
end
return;
%--------------------------------------------------------------------------------
function plot_hand(zoff,hr,par,sf,a,hh)
xp=sf*par.C.rad*cos(a);
yp=sf*par.C.rad*sin(a);
set(hh,'xdata',[0 xp],...
'ydata',[0 yp],...
'zdata',[zoff zoff]);
return;
%--------------------------------------------------------------------------------
function par=do_start(par)
if ~isempty(par)
if ~isempty(par.t)
start(par.t);
end
end
return;
%--------------------------------------------------------------------------------
function par=do_stop(par)
if ~isempty(par)
if ~isempty(par.t)
stop(par.t);
end
end
return;
%--------------------------------------------------------------------------------
function par=get_par(par,mode)
hp=406; % help position
he=46; % help entries
hp=sprintf('%d:%d',hp,hp+he);
v='01-Jun-2003 16:42:20';
% common run-time parameters
% do NOT change dynamically
%--------------------------------------------------------------------------------
if mode == 0
par.magic='RTC'; % id
par.ver=v; % ver
par.start=datestr(clock); % date
par.v.com{1}='rtc(0)'; % rtc timer update
par.v.com{2}='rtc s'; % delete clock
par.v.com{3}='rtc U'; % update clock geometry
par.v.ha=[]; % vals computed once only
par.v.ma=[];
par.v.hh=[]; % HR hand handle
par.v.mh=[]; % MIN hand handle
par.v.sh=[]; % SEC hand handle
par.v.dh=[]; % date string handle
par.v.th=[]; % status string handle
par.v.ho=[]; % HR marker
par.v.mo=[]; % MIN marker
par.v.so=[]; % SEC marker
par.v.hp=hp; % help position
par.t=[]; % timer
par.fh=[]; % fig handle
par.warning='only change values below this line';
par.line= '----------------------------------';
elseif mode == 1
par.v.hp=hp; % help position
return;
end
% COMMON CLOCK GEOMETRY PARAMETERS ver 01-Jun-2003 16:42:20
%--------------------------------------------------------------------------------
% figure/axis -----------------------------------------------------------------
par.F.w=[]; % window position
par.F.col=.85*[1 1 1]; % fig bg color
par.F.xfac=1.5; % axix X lim factor
par.F.yfac=1.5; % Y lim factor
% clock frame -----------------------------------------------------------------
par.C.col=[0 0 0]; % clock frame color
par.C.mod='-'; % line mode
par.C.wid=1; % line width
par.C.rad=9; % radius
% date string -----------------------------------------------------------------
par.D.fname=[]; % font name date string
par.D.fsize=14; % size
par.D.fweight='normal'; % weight
par.D.fangle='normal'; % angle
par.D.frad=-14; % radius
% dials/hands -----------------------------------------------------------------
par.H.fname=[]; % HR dial font name
par.H.fsize=12; % size
par.H.fweight='normal'; % weight
par.H.fangle='normal'; % angle
par.H.frad=11; % radius
par.H.mark='square'; % marker style
par.H.size=8; % size
par.H.fcol=[1 1 1]; % face color
par.H.ecol=[0 0 0]; % edge color
par.H.col=[0 0 0]; % hand color
par.H.mod='-'; % line mode
par.H.wid=4; % width
par.H.len=.75; % rel length
% -----------------------------------------------------------------------
par.M.mark='square'; % MIN marker style
par.M.size=4; % size
par.M.fcol=.75*[1 1 1]; % face color
par.M.ecol=[0 0 0]; % edge color
par.M.col=[0 0 0]; % hand color
par.M.mod='-'; % line mode
par.M.wid=2; % width
par.M.len=.8; % rel lenght
% -----------------------------------------------------------------------
par.S.col=[0 0 0]; % SEC hand color
par.S.mod='-'; % line mode
par.S.wid=1; % width
par.S.len=1; % rel length
%--------------------------------------------------------------------------------
return;
%--------------------------------------------------------------------------------