• Main Page
  • Modules
  • Classes
  • Files
  • File List

rtclock.cpp

00001 /*  Time Based Text - Real Time Clock for Linux
00002  *
00003  *  (C) Copyright 2006 - 2007 Denis Rojo <jaromil@dyne.org>
00004  *
00005  * This source code is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Public License as published 
00007  * by the Free Software Foundation; either version 2 of the License,
00008  * or (at your option) any later version.
00009  *
00010  * This source code is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013  * Please refer to the GNU Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Public License along with
00016  * this source code; if not, write to:
00017  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  *
00019  */
00020 
00021 #ifdef linux
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <errno.h>
00027 #include <string>
00028 
00029 #include <string.h>
00030 #include <errno.h>
00031 
00032 #ifdef linux
00033 /* we try to use the realtime linux clock on /dev/rtc */
00034 #include <linux/rtc.h>
00035 #include <sys/ioctl.h>
00036 #include <sys/time.h>
00037 #include <sys/select.h>
00038 #include <fcntl.h>
00039 #include <sys/stat.h>
00040 #include <sys/types.h>
00041 #endif
00042 
00043 #include <inttypes.h>
00044 
00045 #include <rtclock.h>
00046 
00047 #include <jutils.h>
00048 
00049 // threading stuff
00050 typedef void* (kickoff)(void*);
00051 
00052 
00053 RTClock::RTClock() {  
00054   rtcfd = 0;
00055   quit = false;
00056   msec = 0;
00057   _thread = 0x0;
00058   sleeping = false;
00059 }
00060 
00061 
00062 RTClock::~RTClock() {
00063 
00064   if(_thread) {
00065     quit = true;
00066     pthread_join(_thread, NULL);
00067   }
00068 
00069   // close rtc
00070   if(rtcfd>0) {
00071     ioctl(rtcfd, RTC_UIE_OFF, 0);
00072     //  ioctl(rtcfd,RTC_PIE_OFF,0);
00073     ::close(rtcfd);
00074   }
00075   
00076   // close posix threads
00077   if(pthread_mutex_destroy(&_mutex) == -1)
00078     error("error destroying POSIX thread mutex");
00079   if(pthread_cond_destroy(&_cond) == -1)
00080     error("error destroying POSIX thread condition");
00081   if(pthread_attr_destroy(&_attr) == -1)
00082     error("error destroying POSIX thread attribute");
00083 
00084 }
00085 
00086 int RTClock::init() {
00087   int res;
00088 
00089   // open RTC device
00090   rtcfd = ::open("/dev/rtc",O_RDONLY);
00091   if(rtcfd<0) {
00092     warning("couldn't open real time clock device: %s", strerror(errno));
00093     warning("reverting to POSIX.1 time handling");
00094     return 0;
00095   }
00096   /* set the alarm event to 1 second */
00097   res = ioctl(rtcfd, RTC_UIE_ON, 0);
00098   if(res<0) {
00099     error("couldn't set real time clock device tick: %s", strerror(errno));
00100     return 0;
00101   }
00102 
00103   // initialize thread and rtc
00104   if(pthread_attr_init (&_attr) == -1)
00105     error("error initializing POSIX thread attribute");
00106   if(pthread_mutex_init (&_mutex,NULL) == -1)
00107     error("error initializing POSIX thread mutex");
00108   if(pthread_cond_init (&_cond, NULL) == -1)
00109     error("error initializing POSIX thread condtition"); 
00110   
00111   /* sets the thread as detached
00112      see: man pthread_attr_init(3) */
00113   //  pthread_attr_setdetachstate(&_attr,PTHREAD_CREATE_DETACHED);
00114   pthread_attr_setdetachstate(&_attr,PTHREAD_CREATE_JOINABLE);
00115 
00116 
00117   notice("real time clock succesfully initialized");
00118   
00119   return 1;
00120 }
00121 
00122 int RTClock::set_freq(unsigned long freq) {
00123   int res;
00124 
00125   if(rtcfd<0) {
00126     error("can't set clock frequency: real time clock device is not open");
00127     return -1;
00128   }
00129   
00130   res = ioctl(rtcfd,RTC_IRQP_SET,freq);
00131 
00132   if(res<0)
00133     error("RTC_IRQP_SET failed: %s", strerror(errno));
00134 
00135   else {
00136 
00137     res = ioctl(rtcfd,RTC_IRQP_READ,&freq);
00138 
00139     if(res<0)
00140       error("RTC_IRQP_READ failed: %s", strerror(errno));
00141 
00142     else {
00143       // enable periodic interrupts
00144       res = ioctl(rtcfd,RTC_PIE_ON,0);
00145       if(res<0)
00146         error("RTC_PIE_ON failed: %s", strerror(errno));
00147       else
00148         act("realtime clock frequency set to %lu",freq);
00149     }
00150   }
00151 
00152   // reset clock
00153   quit = false;
00154   msec = 0;
00155 
00156   return res;
00157 }
00158 
00159 int RTClock::tick() {
00160   int res;
00161 
00162   // blocking read on /dev/rtc
00163   res = read(rtcfd, &rtctime, sizeof(unsigned long));
00164   if(res < 0)
00165     error("problem catching real time clock interrupt: %s", strerror(errno));
00166 
00167   // update clock counter
00168   msec++;
00169   
00170   return res;
00171 }
00172 
00173 void RTClock::run() {
00174 
00175   // run the clock
00176   while(!quit) {
00177 
00178     if(sleeping) wait();
00179     
00180     tick(); // blocking
00181     
00182   }
00183 
00184 }
00185 
00186 
00187 
00188 int RTClock::start() {
00189   int res;
00190 
00191   if(rtcfd<0) {
00192     error("can't start clock: real time clock device is not open");
00193     return -1;
00194   }
00195 
00196   if(_thread) {
00197     quit = true;
00198     pthread_join(_thread, NULL);
00199   }
00200 
00201   // reset clock
00202   quit = false;
00203   msec = 0;
00204 
00205   res = pthread_create(&_thread, &_attr, &kickoff, this);
00206   if(res != 0) {
00207     error("can't create thread: %s",strerror(errno));
00208     return 0;
00209   }
00210   return 1;
00211 }
00212 
00213 int RTClock::sleep(uint64_t msec) {
00214   register uint64_t elap_msec;
00215 
00216   if(rtcfd<0) {
00217     error("tbt::clock::sleep - real time clock device is not open");
00218     return -1;
00219   }
00220 
00221   // tell main thread to wait()
00222   sleeping = true;
00223 
00224   // microseconds loop
00225   for(elap_msec = msec; elap_msec >0; elap_msec--)
00226     tick(); // blocking
00227 
00228   sleeping = false;
00229   signal(); // main thread can run
00230 
00231   return 1;
00232 }
00233 
00234 #endif

Generated on Mon Apr 9 2012 15:29:22 for TimeBasedText_code_doc by  doxygen 1.7.1