00001 /* 00002 * Copyright Droids Corporation, Microb Technology, Eirbot (2005) 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Revision : $Id: time.c,v 1.5 2008-01-08 20:05:02 zer0 Exp $ 00019 * 00020 */ 00021 00022 /* Droids-corp, Eirbot, Microb Technology 2005 - Zer0 00023 * Implementation of the time module 00024 */ 00025 00036 /**********************************************************/ 00037 00038 #include <stdlib.h> 00039 #include <scheduler.h> 00040 00041 #include <time.h> 00042 #include <time_config.h> 00043 00044 /**********************************************************/ 00045 00046 #define NB_SCHEDULER_UNIT ( ((float)(TIME_PRECISION)) / SCHEDULER_UNIT_FLOAT ) 00047 #define NB_SCHEDULER_UNIT_NOT_NULL (NB_SCHEDULER_UNIT == 0 ? 1.0 : NB_SCHEDULER_UNIT) 00048 00049 static volatile time_h t; 00050 00051 static volatile microseconds us2; // this one overflows naturally 00052 00053 00054 void time_increment(void * dummy); 00055 00056 /**********************************************************/ 00057 00058 void time_init(uint8_t priority) 00059 { 00060 time_reset(); 00061 scheduler_add_periodical_event_priority(time_increment,NULL, 00062 (int)NB_SCHEDULER_UNIT_NOT_NULL, priority); 00063 } 00064 00065 /**********************************************************/ 00066 00067 seconds time_get_s(void) 00068 { 00069 uint16_t tmp; 00070 uint8_t flags; 00071 IRQ_LOCK(flags); 00072 tmp = t.s; 00073 IRQ_UNLOCK(flags); 00074 return tmp; 00075 } 00076 00077 /**********************************************************/ 00078 00079 microseconds time_get_us(void) 00080 { 00081 microseconds tmp; 00082 uint8_t flags; 00083 IRQ_LOCK(flags); 00084 tmp = t.us; 00085 IRQ_UNLOCK(flags); 00086 return tmp; 00087 } 00088 00089 /**********************************************************/ 00090 00091 microseconds time_get_us2(void) 00092 { 00093 microseconds tmp; 00094 uint8_t flags; 00095 IRQ_LOCK(flags); 00096 tmp = us2; 00097 IRQ_UNLOCK(flags); 00098 return tmp; 00099 } 00100 00101 /**********************************************************/ 00102 00103 time_h time_get_time(void) 00104 { 00105 time_h tmp; 00106 uint8_t flags; 00107 IRQ_LOCK(flags); 00108 tmp = t; 00109 IRQ_UNLOCK(flags); 00110 return tmp; 00111 } 00112 00113 /**********************************************************/ 00114 00115 void time_reset(void) 00116 { 00117 uint8_t flags; 00118 IRQ_LOCK(flags); 00119 t.us = 0; 00120 t.s = 0; 00121 IRQ_UNLOCK(flags); 00122 } 00123 00124 /**********************************************************/ 00125 00126 void time_set(seconds s, microseconds us) 00127 { 00128 uint8_t flags; 00129 IRQ_LOCK(flags); 00130 t.us = us; 00131 t.s = s; 00132 IRQ_UNLOCK(flags); 00133 } 00134 00135 /**********************************************************/ 00136 00137 void time_wait_ms(uint16_t ms) 00138 { 00139 microseconds old = time_get_us2(); 00140 while(time_get_us2() - old < ((uint32_t)ms*1000)); 00141 } 00142 00143 /**********************************************************/ 00144 /* private */ 00145 /**********************************************************/ 00146 00147 void time_increment(void * dummy) 00148 { 00149 uint8_t flags; 00150 /* XXX we should lock only when writing */ 00151 IRQ_LOCK(flags); // for reading correct time inside an interrupt 00152 00153 us2 += ((int)NB_SCHEDULER_UNIT_NOT_NULL * SCHEDULER_UNIT); 00154 t.us += ((int)NB_SCHEDULER_UNIT_NOT_NULL * SCHEDULER_UNIT); 00155 while (t.us > 1000000) { 00156 t.s ++; 00157 t.us -= 1000000; 00158 } 00159 00160 IRQ_UNLOCK(flags); 00161 }