timer.c

Description | Download | Table of Contents | Modules | Compound List | File List | Functions


Overview
Compiler
Documentation
Examples
Misc
Help
IDE & Tools

Download
Install

Links
Projects






00001 /* Timer example for 68HC11
00002    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
00003    Written by Stephane Carrez (stcarrez@worldnet.fr)    
00004 
00005 This file is free software; you can redistribute it and/or modify it
00006 under the terms of the GNU General Public License as published by the
00007 Free Software Foundation; either version 2, or (at your option) any
00008 later version.
00009 
00010 In addition to the permissions in the GNU General Public License, the
00011 Free Software Foundation gives you unlimited permission to link the
00012 compiled version of this file with other programs, and to distribute
00013 those programs without any restriction coming from the use of this
00014 file.  (The General Public License restrictions do apply in other
00015 respects; for example, they cover modification of the file, and
00016 distribution when not linked into another program.)
00017 
00018 This file is distributed in the hope that it will be useful, but
00019 WITHOUT ANY WARRANTY; without even the implied warranty of
00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021 General Public License for more details.
00022 
00023 You should have received a copy of the GNU General Public License
00024 along with this program; see the file COPYING.  If not, write to
00025 the Free Software Foundation, 59 Temple Place - Suite 330,
00026 Boston, MA 02111-1307, USA.  */
00027 
00039 #include "timer.h"
00040 
00041 #define TIMER_DIV  (8192L)
00042 #define TIMER_TICK (M6811_CPU_E_CLOCK / TIMER_DIV)
00043 
00044 unsigned long timer_count;
00045 unsigned long boot_time;
00046 
00047 /* Timer interrupt handler.  */
00048 void __attribute__((interrupt))
00049 timer_interrupt (void)
00050 {
00051   timer_count++;
00052   timer_acknowledge ();
00053 }
00054 
00055 /* Returns the current number of ticks that ellapsed since we started.  */
00056 static inline unsigned long
00057 timer_get_ticks ()
00058 {
00059   unsigned long t;
00060 
00061   lock ();
00062   t = timer_count;
00063   unlock ();
00064   return t;
00065 }
00066 
00067 /* Translate the number of ticks into some seconds.  */
00068 unsigned long
00069 timer_seconds (unsigned long ntime)
00070 {
00071   unsigned long n;
00072 
00073   /* To compute SECS = NTIME * TIMER_DIV / M6811_CPU_E_CLOCK accurately,
00074      use Bezous relation (A = BQ + R).  */
00075   n = ntime * (TIMER_DIV / M6811_CPU_E_CLOCK);
00076   n += (ntime * (TIMER_DIV % M6811_CPU_E_CLOCK)) / M6811_CPU_E_CLOCK;
00077   n += boot_time;
00078   return n;
00079 }
00080 
00081 /* Translate the number of ticks into some microseconds.  */
00082 unsigned long
00083 timer_microseconds (unsigned long ntime)
00084 {
00085   unsigned long n;
00086 
00087   /* To compute SECS = NTIME * TIMER_DIV / M6811_CPU_E_CLOCK accurately,
00088      use Bezous relation (A = BQ + R).  */
00089   n = ntime * (TIMER_DIV / 2);
00090   n += (ntime * (TIMER_DIV % 2)) / 2;
00091   n = n % 1000000L;
00092   return n;
00093 }
00094 
00095 /* Translate the string pointed to by *p into a number.
00096    Update *p to point to the end of that number.  */
00097 unsigned short
00098 get_value (char **p)
00099 {
00100   char *q;
00101   unsigned short val;
00102   
00103   q = *p;
00104   while (*q == ' ')
00105     q++;
00106   
00107   val = 0;
00108   while (1)
00109     {
00110       char c = *q++;
00111       if (c < '0' || c > '9')
00112         break;
00113       val = (val * 10) + (c - '0');
00114     }
00115   q--;
00116   *p = q;
00117   return val;
00118 }
00119 
00120 /* Ask for the boot time.  */
00121 void
00122 get_time ()
00123 {
00124   char buf[32];
00125   int pos;
00126   char c;
00127   unsigned short hours, mins, secs;
00128   char *p;
00129   int error = 0;
00130   
00131   print ("\r\nBoot time ? ");
00132   pos = 0;
00133   while (1)
00134     {
00135       c = serial_recv ();
00136       if (c == '\r' || c == '\n')
00137         break;
00138 
00139       if (c == '\b')
00140         {
00141           print ("\b \b");
00142           pos--;
00143           if (pos < 0)
00144             pos = 0;
00145         }
00146       else if (pos < sizeof (buf) - 1)
00147         {
00148           buf[pos] = c;
00149           buf[pos+1] = 0;
00150           print (&buf[pos]);
00151           pos++;
00152         }
00153     }
00154 
00155   print ("\n");
00156   buf[pos] = 0;
00157   p = buf;
00158   hours = get_value (&p);
00159   if (*p++ != ':')
00160     error = 1;
00161   mins = get_value (&p);
00162   if (*p++ != ':' || mins >= 60)
00163     error = 1;
00164   secs = get_value (&p);
00165   if (*p++ != 0 || secs >= 60)
00166     error = 1;
00167 
00168   if (error == 0)
00169     {
00170       boot_time = (hours * 3600) + (mins * 60) + (secs);
00171       print ("Boot time is set.\r\n");
00172     }
00173   else
00174     {
00175       print ("Invalid boot time.\r\n");
00176       print ("Format is: HH:MM:SS\r\n");
00177     } 
00178 }
00179 
00180 /* Display the current time on the serial line.  */
00181 static void
00182 display_time (unsigned long ntime)
00183 {
00184   unsigned long seconds;
00185   unsigned short hours, mins;
00186   unsigned long nus;
00187   char buf[12];
00188 
00189   static unsigned long last_sec = 0xffffffff;
00190   static unsigned long last_us = 0;
00191 
00192   /* Translate the number of ticks in seconds and milliseconds.  */
00193   seconds = timer_seconds (ntime);
00194   nus = timer_microseconds (ntime);
00195           
00196   nus = nus / 100000L;
00197 
00198   /* If the seconds changed, re-display everything.  */
00199   if (seconds != last_sec)
00200     {
00201       last_sec = seconds;
00202       last_us = nus;
00203       hours = (unsigned short) (seconds / 3600L);
00204       mins = (unsigned short) (seconds % 3600L);
00205       seconds = (unsigned long) (mins % 60);
00206       mins = mins / 60;
00207       buf[0] = '0' + (hours / 10);
00208       buf[1] = '0' + (hours % 10);
00209       buf[2] = ':';
00210       buf[3] = '0' + (mins / 10);
00211       buf[4] = '0' + (mins % 10);
00212       buf[5] = ':';
00213       buf[6] = '0' + (seconds / 10);
00214       buf[7] = '0' + (seconds % 10);
00215       buf[8] = '.';
00216       buf[9] = '0' + nus;
00217       buf[10] = 0;
00218       serial_print ("\r");
00219       serial_print (buf);
00220     }
00221 
00222   /* Only re-display the tens of a second.  */
00223   else if (last_us != nus)
00224     {
00225       last_us = nus;
00226       buf[0] = '0' + nus;
00227       buf[1] = 0;
00228       serial_print ("\b");
00229       serial_print (buf);
00230     }
00231   serial_flush ();
00232 }
00233 
00234 int
00235 main ()
00236 {
00237   unsigned long prev_time;
00238   
00239   lock ();
00240   boot_time = 0;
00241   timer_count = 0;
00242 
00243   /* Set interrupt handler for bootstrap mode.  */
00244   set_interrupt_handler (RTI_VECTOR, timer_interrupt);
00245 
00246   /* Initialize the timer.  */
00247   timer_initialize_rate (M6811_TPR_16);
00248   prev_time = timer_count;
00249 
00250   unlock ();
00251 
00252   /* Ask for the boot time.  */
00253   get_time ();
00254 
00255   /* Loop waiting for the time to change and redisplay it.  */
00256   while (1)
00257     {
00258       unsigned long ntime;
00259 
00260       /* Reset the COP (in case it is active).  */
00261       cop_optional_reset ();
00262 
00263       /* If something is received on the serial line,
00264          ask for the boot time again.  */
00265       if (serial_receive_pending ())
00266         get_time ();
00267 
00268       /* Get current time and see if we must re-display it.  */
00269       ntime = timer_get_ticks ();
00270       if (ntime != prev_time)
00271         {
00272           prev_time = ntime;
00273           display_time (ntime);
00274         }
00275     }
00276 }

Description | Download | Table of Contents | Modules | Compound List | File List | Functions

    Last modified,
    Apr 16, 2001
[ Copying ]     [ Feedback to Stephane.Carrez@worldnet.fr ]