Code covered by the BSD License  

Highlights from
rtc: a pedestrian real-time clock figure

image thumbnail
from rtc: a pedestrian real-time clock figure by us
creates a versatilely configurable real-time clock in a figure

opar=rtc(id,npar)
% 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;
%--------------------------------------------------------------------------------

Contact us at files@mathworks.com