Andrew Boyson / log

Dependents:   oldheating gps motorhome heating

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers log.c Source File

log.c

00001 #include <stdlib.h>
00002 #include <stdarg.h>
00003 #include <stdio.h>
00004 #include <time.h>
00005 #include <stdbool.h>
00006 #include <stdint.h>
00007 #include "serialpc.h"
00008 
00009 #define BUFFER_LENGTH 0x4000
00010 
00011 __attribute__((section("AHBSRAM0"))) static char buffer[BUFFER_LENGTH]; //Pop the buffer into the USB area
00012 static char* pPush; //Initialised in init
00013 static char* pPull; //Initialised in init
00014 static char *pUart; //Initialised in init
00015 
00016 static bool enable = true;
00017 static void (*tmFunction)(struct tm* ptm);
00018 static bool useUart = false; //This is set during initialisation
00019        bool LogUart = true;  //Always start off with the uart running
00020        
00021 static char* incrementPushPullPointer(char* p, char* buffer, int bufferLength)
00022 {
00023     p++; //increment the pointer by one
00024     if (p == buffer + bufferLength) p = buffer; //if the pointer is now beyond the end then point it back to the start
00025     return p;
00026 }
00027 static void push(const char c)
00028 {
00029     //Move the pull position if about to run into it
00030     char* pNext = incrementPushPullPointer(pPush, buffer, BUFFER_LENGTH);
00031     if (pNext == pPull) pPull = incrementPushPullPointer(pPull, buffer, BUFFER_LENGTH);
00032     
00033     //Add the character at the push position
00034     *pPush = c;
00035     pPush = incrementPushPullPointer(pPush, buffer, BUFFER_LENGTH);
00036 }
00037 void LogChar(const char c)
00038 {
00039     //Only add if allowed
00040     if (!enable) return;
00041     
00042     //Work out if the character needs to be delimited
00043     bool delimited = false;
00044     if (c < ' ' && c != '\r' && c != '\n') delimited = true;
00045     if (c > 126) delimited = false;
00046     
00047     //Push the delimiter or the character
00048     if (delimited) push('^');
00049     else           push(c);
00050     
00051     //Stop if its not delimited
00052     if (!delimited) return;
00053     
00054     //Push the first digit
00055     char h = c >> 4;
00056     if (h < 10) h += '0';
00057     else        h += 'A' - 10;
00058     push(h);
00059         
00060     //Push the second digit
00061     h = c & 0x0F;
00062     if (h < 10) h += '0';
00063     else        h += 'A' - 10;
00064     push(h);
00065     
00066 }
00067 static char *pEnumerate;
00068 void LogEnumerateStart()
00069 {
00070     pEnumerate = pPull;
00071 }
00072 int LogEnumerate()
00073 {
00074     if (pEnumerate == pPush) return -1;
00075     char c = *pEnumerate;
00076     pEnumerate = incrementPushPullPointer(pEnumerate, buffer, BUFFER_LENGTH); 
00077     return c;
00078 }
00079 void LogEnable(bool value)
00080 {
00081     enable = value;
00082 }
00083 void LogClear()
00084 {
00085     pPush = buffer;
00086     pPull = buffer;
00087     pUart = buffer;
00088 }
00089 void LogInit(void (*tmFunctionParam)(struct tm* ptm), int baud)
00090 {
00091     useUart = baud;
00092     if (useUart) SerialPcInit(baud);
00093     tmFunction = tmFunctionParam;
00094     LogClear();
00095 }
00096 void LogMain()
00097 {
00098     if (!useUart)       return;
00099     if (!LogUart)       return;     //Do nothing if uart is not enabled
00100     if (pUart == pPush) return;     //Do nothing if all characters have been sent
00101     int result = SerialPcPutC(*pUart); //Attempt to write the character
00102     if (result == 0) pUart = incrementPushPullPointer(pUart, buffer, BUFFER_LENGTH); //If the character was written to the uart then move to the next
00103 }
00104 int Log(const char* snd)
00105 {
00106     const char* ptr = snd;
00107     while (*ptr) LogChar(*ptr++); //Send the string to the log buffer
00108     return ptr - snd;
00109 }
00110 int LogV(const char *fmt, va_list argptr)
00111 {
00112     int size  = vsnprintf(NULL, 0, fmt, argptr);  //Find the size required
00113     char snd[size + 1];                           //Allocate enough memory for the size required with an extra byte for the terminating null
00114     vsprintf(snd, fmt, argptr);                   //Fill the new buffer
00115     return Log(snd);                              //Send the string to the log buffer
00116 }
00117 int LogF(const char *fmt, ...)
00118 {
00119     va_list argptr;
00120     va_start(argptr, fmt);
00121     int size = LogV(fmt, argptr);
00122     va_end(argptr);
00123     return size;
00124 }
00125 static void pushuint4(int value)
00126 {    
00127     if      (value > 9999) { LogChar('+'); LogChar('+'); LogChar('+'); LogChar('+'); }
00128     else if (value <    0) { LogChar('-'); LogChar('-'); LogChar('-'); LogChar('-'); }
00129     else
00130     {
00131         div_t divres;
00132         int k, c, t, u;
00133         divres = div(value      , 10); u = divres.rem;
00134         divres = div(divres.quot, 10); t = divres.rem;
00135         divres = div(divres.quot, 10); c = divres.rem;
00136                                        k = divres.quot;                           
00137         LogChar(k + '0'); LogChar(c + '0'); LogChar(t + '0'); LogChar(u + '0');
00138     }
00139 }
00140 static void pushuint3(int value)
00141 {
00142     if      (value > 999) { LogChar('+'); LogChar('+'); LogChar('+'); }
00143     else if (value <   0) { LogChar('-'); LogChar('-'); LogChar('-'); }
00144     else
00145     {
00146         div_t divres;
00147         int c, t, u;
00148         divres = div(value      , 10); u = divres.rem;
00149         divres = div(divres.quot, 10); t = divres.rem;
00150                                        c = divres.quot;
00151         LogChar(c + '0'); LogChar(t + '0'); LogChar(u + '0');
00152     }
00153 }
00154 static void pushuint2(int value)
00155 {
00156     if      (value > 99) { LogChar('+'); LogChar('+'); }
00157     else if (value <  0) { LogChar('-'); LogChar('-'); }
00158     else
00159     {
00160         div_t divres;
00161         int t, u;
00162         divres = div(value      , 10); u = divres.rem;
00163                                        t = divres.quot;
00164         LogChar(t + '0'); LogChar(u + '0');
00165     }
00166 }
00167 
00168 static int logTimeOnly()
00169 {
00170     if (!tmFunction) return 0;
00171     
00172     struct tm tm;
00173     tmFunction(&tm);
00174     
00175     pushuint4(tm.tm_year + 1900);
00176     LogChar('-');
00177     pushuint3(tm.tm_yday + 1);
00178     LogChar(' ');
00179     pushuint2(tm.tm_hour);
00180     LogChar(':');
00181     pushuint2(tm.tm_min);
00182     LogChar(':');
00183     pushuint2(tm.tm_sec);
00184     return 17;
00185 }
00186 int LogTime(const char *snd)
00187 {
00188     int size = 0;
00189     size += logTimeOnly();
00190     size++; LogChar(' ');
00191     size += Log(snd);
00192     return size;
00193 }
00194 int LogTimeF(const char *fmt, ...)
00195 {
00196     int size = 0;
00197     va_list argptr;
00198     va_start(argptr, fmt);
00199     size = logTimeOnly();
00200     size++; LogChar(' ');
00201     size += LogV(fmt, argptr);
00202     va_end(argptr);
00203     return size;
00204 }
00205 
00206 void LogNibbleAsHex(int nibble)
00207 {
00208     nibble &= 0x0F;
00209     char c;
00210     if      (nibble < 0x0A) c = nibble + '0';
00211     else if (nibble < 0x10) c = nibble - 0xA + 'A';
00212     else                    c = '0';
00213     LogChar(c);
00214 }
00215 
00216 void LogByteAsHex(int value)
00217 {
00218     LogNibbleAsHex(value >> 4);
00219     LogNibbleAsHex(value >> 0);
00220 }
00221 void LogBytesAsHex(const uint8_t* bytes, int size)
00222 {
00223     int i = 0;
00224     while(true)
00225     {
00226         LogByteAsHex(bytes[i]);
00227         i++;
00228         if (i >= size) break;
00229         if (i % 16 == 0) Log("\r\n");
00230         else             LogChar(' ');
00231     }
00232 }