Log
Dependents: oldheating gps motorhome heating
log.c@19:14376c221aec, 2019-08-20 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Aug 20 14:50:12 2019 +0000
- Revision:
- 19:14376c221aec
- Parent:
- 18:617791ed3d8e
- Child:
- 20:5b5284c60d3c
Changed log bytes from char to const uint8_t
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 12:19c2d4943124 | 1 | #include <stdlib.h> |
andrewboyson | 12:19c2d4943124 | 2 | #include <stdarg.h> |
andrewboyson | 12:19c2d4943124 | 3 | #include <stdio.h> |
andrewboyson | 12:19c2d4943124 | 4 | #include <time.h> |
andrewboyson | 12:19c2d4943124 | 5 | #include <stdbool.h> |
andrewboyson | 19:14376c221aec | 6 | #include <stdint.h> |
andrewboyson | 15:e490fce9b6ef | 7 | #include "serialpc.h" |
andrewboyson | 0:9907e344c82a | 8 | |
andrewboyson | 12:19c2d4943124 | 9 | #define BUFFER_LENGTH 0x4000 |
andrewboyson | 12:19c2d4943124 | 10 | |
andrewboyson | 12:19c2d4943124 | 11 | __attribute__((section("AHBSRAM0"))) static char buffer[BUFFER_LENGTH]; //Pop the buffer into the USB area |
andrewboyson | 0:9907e344c82a | 12 | static char* pPush; //Initialised in init |
andrewboyson | 0:9907e344c82a | 13 | static char* pPull; //Initialised in init |
andrewboyson | 12:19c2d4943124 | 14 | static char *pUart; //Initialised in init |
andrewboyson | 6:b98aa0ec75a1 | 15 | |
andrewboyson | 12:19c2d4943124 | 16 | static bool enable = true; |
andrewboyson | 13:fb7f40c2e446 | 17 | static void (*tmFunction)(struct tm* ptm); |
andrewboyson | 13:fb7f40c2e446 | 18 | static bool useUart = false; //This is set during initialisation |
andrewboyson | 13:fb7f40c2e446 | 19 | bool LogUart = true; //Always start off with the uart running |
andrewboyson | 13:fb7f40c2e446 | 20 | |
andrewboyson | 0:9907e344c82a | 21 | static char* incrementPushPullPointer(char* p, char* buffer, int bufferLength) |
andrewboyson | 0:9907e344c82a | 22 | { |
andrewboyson | 0:9907e344c82a | 23 | p++; //increment the pointer by one |
andrewboyson | 0:9907e344c82a | 24 | if (p == buffer + bufferLength) p = buffer; //if the pointer is now beyond the end then point it back to the start |
andrewboyson | 0:9907e344c82a | 25 | return p; |
andrewboyson | 0:9907e344c82a | 26 | } |
andrewboyson | 16:5c41b457c7f3 | 27 | static void push(const char c) |
andrewboyson | 6:b98aa0ec75a1 | 28 | { |
andrewboyson | 6:b98aa0ec75a1 | 29 | //Move the pull position if about to run into it |
andrewboyson | 6:b98aa0ec75a1 | 30 | char* pNext = incrementPushPullPointer(pPush, buffer, BUFFER_LENGTH); |
andrewboyson | 6:b98aa0ec75a1 | 31 | if (pNext == pPull) pPull = incrementPushPullPointer(pPull, buffer, BUFFER_LENGTH); |
andrewboyson | 6:b98aa0ec75a1 | 32 | |
andrewboyson | 6:b98aa0ec75a1 | 33 | //Add the character at the push position |
andrewboyson | 6:b98aa0ec75a1 | 34 | *pPush = c; |
andrewboyson | 6:b98aa0ec75a1 | 35 | pPush = incrementPushPullPointer(pPush, buffer, BUFFER_LENGTH); |
andrewboyson | 6:b98aa0ec75a1 | 36 | } |
andrewboyson | 16:5c41b457c7f3 | 37 | void LogChar(const char c) |
andrewboyson | 0:9907e344c82a | 38 | { |
andrewboyson | 0:9907e344c82a | 39 | //Only add if allowed |
andrewboyson | 0:9907e344c82a | 40 | if (!enable) return; |
andrewboyson | 0:9907e344c82a | 41 | |
andrewboyson | 6:b98aa0ec75a1 | 42 | //Work out if the character needs to be delimited |
andrewboyson | 2:ee4ec2d72525 | 43 | bool delimited = false; |
andrewboyson | 2:ee4ec2d72525 | 44 | if (c < ' ' && c != '\r' && c != '\n') delimited = true; |
andrewboyson | 12:19c2d4943124 | 45 | if (c > 126) delimited = false; |
andrewboyson | 2:ee4ec2d72525 | 46 | |
andrewboyson | 6:b98aa0ec75a1 | 47 | //Push the delimiter or the character |
andrewboyson | 6:b98aa0ec75a1 | 48 | if (delimited) push('^'); |
andrewboyson | 6:b98aa0ec75a1 | 49 | else push(c); |
andrewboyson | 2:ee4ec2d72525 | 50 | |
andrewboyson | 6:b98aa0ec75a1 | 51 | //Stop if its not delimited |
andrewboyson | 2:ee4ec2d72525 | 52 | if (!delimited) return; |
andrewboyson | 2:ee4ec2d72525 | 53 | |
andrewboyson | 6:b98aa0ec75a1 | 54 | //Push the first digit |
andrewboyson | 2:ee4ec2d72525 | 55 | char h = c >> 4; |
andrewboyson | 2:ee4ec2d72525 | 56 | if (h < 10) h += '0'; |
andrewboyson | 2:ee4ec2d72525 | 57 | else h += 'A' - 10; |
andrewboyson | 6:b98aa0ec75a1 | 58 | push(h); |
andrewboyson | 6:b98aa0ec75a1 | 59 | |
andrewboyson | 6:b98aa0ec75a1 | 60 | //Push the second digit |
andrewboyson | 2:ee4ec2d72525 | 61 | h = c & 0x0F; |
andrewboyson | 2:ee4ec2d72525 | 62 | if (h < 10) h += '0'; |
andrewboyson | 2:ee4ec2d72525 | 63 | else h += 'A' - 10; |
andrewboyson | 6:b98aa0ec75a1 | 64 | push(h); |
andrewboyson | 2:ee4ec2d72525 | 65 | |
andrewboyson | 0:9907e344c82a | 66 | } |
andrewboyson | 0:9907e344c82a | 67 | static char *pEnumerate; |
andrewboyson | 0:9907e344c82a | 68 | void LogEnumerateStart() |
andrewboyson | 0:9907e344c82a | 69 | { |
andrewboyson | 0:9907e344c82a | 70 | pEnumerate = pPull; |
andrewboyson | 0:9907e344c82a | 71 | } |
andrewboyson | 0:9907e344c82a | 72 | int LogEnumerate() |
andrewboyson | 0:9907e344c82a | 73 | { |
andrewboyson | 12:19c2d4943124 | 74 | if (pEnumerate == pPush) return -1; |
andrewboyson | 0:9907e344c82a | 75 | char c = *pEnumerate; |
andrewboyson | 0:9907e344c82a | 76 | pEnumerate = incrementPushPullPointer(pEnumerate, buffer, BUFFER_LENGTH); |
andrewboyson | 2:ee4ec2d72525 | 77 | return c; |
andrewboyson | 0:9907e344c82a | 78 | } |
andrewboyson | 12:19c2d4943124 | 79 | void LogEnable(bool value) |
andrewboyson | 0:9907e344c82a | 80 | { |
andrewboyson | 12:19c2d4943124 | 81 | enable = value; |
andrewboyson | 0:9907e344c82a | 82 | } |
andrewboyson | 13:fb7f40c2e446 | 83 | void LogClear() |
andrewboyson | 0:9907e344c82a | 84 | { |
andrewboyson | 0:9907e344c82a | 85 | pPush = buffer; |
andrewboyson | 0:9907e344c82a | 86 | pPull = buffer; |
andrewboyson | 12:19c2d4943124 | 87 | pUart = buffer; |
andrewboyson | 12:19c2d4943124 | 88 | } |
andrewboyson | 13:fb7f40c2e446 | 89 | void LogInit(void (*tmFunctionParam)(struct tm* ptm), int baud) |
andrewboyson | 13:fb7f40c2e446 | 90 | { |
andrewboyson | 13:fb7f40c2e446 | 91 | useUart = baud; |
andrewboyson | 15:e490fce9b6ef | 92 | if (useUart) SerialPcInit(baud); |
andrewboyson | 13:fb7f40c2e446 | 93 | tmFunction = tmFunctionParam; |
andrewboyson | 13:fb7f40c2e446 | 94 | LogClear(); |
andrewboyson | 13:fb7f40c2e446 | 95 | } |
andrewboyson | 12:19c2d4943124 | 96 | void LogMain() |
andrewboyson | 12:19c2d4943124 | 97 | { |
andrewboyson | 13:fb7f40c2e446 | 98 | if (!useUart) return; |
andrewboyson | 13:fb7f40c2e446 | 99 | if (!LogUart) return; //Do nothing if uart is not enabled |
andrewboyson | 13:fb7f40c2e446 | 100 | if (pUart == pPush) return; //Do nothing if all characters have been sent |
andrewboyson | 15:e490fce9b6ef | 101 | int result = SerialPcPutC(*pUart); //Attempt to write the character |
andrewboyson | 12:19c2d4943124 | 102 | if (result == 0) pUart = incrementPushPullPointer(pUart, buffer, BUFFER_LENGTH); //If the character was written to the uart then move to the next |
andrewboyson | 0:9907e344c82a | 103 | } |
andrewboyson | 16:5c41b457c7f3 | 104 | int Log(const char* snd) |
andrewboyson | 8:e793e9005f89 | 105 | { |
andrewboyson | 16:5c41b457c7f3 | 106 | const char* ptr = snd; |
andrewboyson | 16:5c41b457c7f3 | 107 | while (*ptr) LogChar(*ptr++); //Send the string to the log buffer |
andrewboyson | 10:cf815db8ed57 | 108 | return ptr - snd; |
andrewboyson | 8:e793e9005f89 | 109 | } |
andrewboyson | 16:5c41b457c7f3 | 110 | int LogV(const char *fmt, va_list argptr) |
andrewboyson | 0:9907e344c82a | 111 | { |
andrewboyson | 8:e793e9005f89 | 112 | int size = vsnprintf(NULL, 0, fmt, argptr); //Find the size required |
andrewboyson | 8:e793e9005f89 | 113 | char snd[size + 1]; //Allocate enough memory for the size required with an extra byte for the terminating null |
andrewboyson | 8:e793e9005f89 | 114 | vsprintf(snd, fmt, argptr); //Fill the new buffer |
andrewboyson | 10:cf815db8ed57 | 115 | return Log(snd); //Send the string to the log buffer |
andrewboyson | 0:9907e344c82a | 116 | } |
andrewboyson | 16:5c41b457c7f3 | 117 | int LogF(const char *fmt, ...) |
andrewboyson | 0:9907e344c82a | 118 | { |
andrewboyson | 0:9907e344c82a | 119 | va_list argptr; |
andrewboyson | 0:9907e344c82a | 120 | va_start(argptr, fmt); |
andrewboyson | 10:cf815db8ed57 | 121 | int size = LogV(fmt, argptr); |
andrewboyson | 0:9907e344c82a | 122 | va_end(argptr); |
andrewboyson | 10:cf815db8ed57 | 123 | return size; |
andrewboyson | 0:9907e344c82a | 124 | } |
andrewboyson | 0:9907e344c82a | 125 | static void pushuint4(int value) |
andrewboyson | 0:9907e344c82a | 126 | { |
andrewboyson | 16:5c41b457c7f3 | 127 | if (value > 9999) { LogChar('+'); LogChar('+'); LogChar('+'); LogChar('+'); } |
andrewboyson | 16:5c41b457c7f3 | 128 | else if (value < 0) { LogChar('-'); LogChar('-'); LogChar('-'); LogChar('-'); } |
andrewboyson | 0:9907e344c82a | 129 | else |
andrewboyson | 0:9907e344c82a | 130 | { |
andrewboyson | 0:9907e344c82a | 131 | div_t divres; |
andrewboyson | 0:9907e344c82a | 132 | int k, c, t, u; |
andrewboyson | 0:9907e344c82a | 133 | divres = div(value , 10); u = divres.rem; |
andrewboyson | 0:9907e344c82a | 134 | divres = div(divres.quot, 10); t = divres.rem; |
andrewboyson | 0:9907e344c82a | 135 | divres = div(divres.quot, 10); c = divres.rem; |
andrewboyson | 0:9907e344c82a | 136 | k = divres.quot; |
andrewboyson | 16:5c41b457c7f3 | 137 | LogChar(k + '0'); LogChar(c + '0'); LogChar(t + '0'); LogChar(u + '0'); |
andrewboyson | 0:9907e344c82a | 138 | } |
andrewboyson | 0:9907e344c82a | 139 | } |
andrewboyson | 0:9907e344c82a | 140 | static void pushuint3(int value) |
andrewboyson | 0:9907e344c82a | 141 | { |
andrewboyson | 16:5c41b457c7f3 | 142 | if (value > 999) { LogChar('+'); LogChar('+'); LogChar('+'); } |
andrewboyson | 16:5c41b457c7f3 | 143 | else if (value < 0) { LogChar('-'); LogChar('-'); LogChar('-'); } |
andrewboyson | 0:9907e344c82a | 144 | else |
andrewboyson | 0:9907e344c82a | 145 | { |
andrewboyson | 0:9907e344c82a | 146 | div_t divres; |
andrewboyson | 0:9907e344c82a | 147 | int c, t, u; |
andrewboyson | 0:9907e344c82a | 148 | divres = div(value , 10); u = divres.rem; |
andrewboyson | 0:9907e344c82a | 149 | divres = div(divres.quot, 10); t = divres.rem; |
andrewboyson | 0:9907e344c82a | 150 | c = divres.quot; |
andrewboyson | 16:5c41b457c7f3 | 151 | LogChar(c + '0'); LogChar(t + '0'); LogChar(u + '0'); |
andrewboyson | 0:9907e344c82a | 152 | } |
andrewboyson | 0:9907e344c82a | 153 | } |
andrewboyson | 0:9907e344c82a | 154 | static void pushuint2(int value) |
andrewboyson | 0:9907e344c82a | 155 | { |
andrewboyson | 16:5c41b457c7f3 | 156 | if (value > 99) { LogChar('+'); LogChar('+'); } |
andrewboyson | 16:5c41b457c7f3 | 157 | else if (value < 0) { LogChar('-'); LogChar('-'); } |
andrewboyson | 0:9907e344c82a | 158 | else |
andrewboyson | 0:9907e344c82a | 159 | { |
andrewboyson | 0:9907e344c82a | 160 | div_t divres; |
andrewboyson | 0:9907e344c82a | 161 | int t, u; |
andrewboyson | 0:9907e344c82a | 162 | divres = div(value , 10); u = divres.rem; |
andrewboyson | 0:9907e344c82a | 163 | t = divres.quot; |
andrewboyson | 16:5c41b457c7f3 | 164 | LogChar(t + '0'); LogChar(u + '0'); |
andrewboyson | 0:9907e344c82a | 165 | } |
andrewboyson | 0:9907e344c82a | 166 | } |
andrewboyson | 12:19c2d4943124 | 167 | |
andrewboyson | 10:cf815db8ed57 | 168 | static int logTimeOnly() |
andrewboyson | 0:9907e344c82a | 169 | { |
andrewboyson | 13:fb7f40c2e446 | 170 | if (!tmFunction) return 0; |
andrewboyson | 12:19c2d4943124 | 171 | |
andrewboyson | 0:9907e344c82a | 172 | struct tm tm; |
andrewboyson | 13:fb7f40c2e446 | 173 | tmFunction(&tm); |
andrewboyson | 0:9907e344c82a | 174 | |
andrewboyson | 0:9907e344c82a | 175 | pushuint4(tm.tm_year + 1900); |
andrewboyson | 16:5c41b457c7f3 | 176 | LogChar('-'); |
andrewboyson | 0:9907e344c82a | 177 | pushuint3(tm.tm_yday + 1); |
andrewboyson | 16:5c41b457c7f3 | 178 | LogChar(' '); |
andrewboyson | 0:9907e344c82a | 179 | pushuint2(tm.tm_hour); |
andrewboyson | 16:5c41b457c7f3 | 180 | LogChar(':'); |
andrewboyson | 0:9907e344c82a | 181 | pushuint2(tm.tm_min); |
andrewboyson | 16:5c41b457c7f3 | 182 | LogChar(':'); |
andrewboyson | 0:9907e344c82a | 183 | pushuint2(tm.tm_sec); |
andrewboyson | 10:cf815db8ed57 | 184 | return 17; |
andrewboyson | 0:9907e344c82a | 185 | } |
andrewboyson | 16:5c41b457c7f3 | 186 | int LogTime(const char *snd) |
andrewboyson | 0:9907e344c82a | 187 | { |
andrewboyson | 10:cf815db8ed57 | 188 | int size = 0; |
andrewboyson | 10:cf815db8ed57 | 189 | size += logTimeOnly(); |
andrewboyson | 16:5c41b457c7f3 | 190 | size++; LogChar(' '); |
andrewboyson | 10:cf815db8ed57 | 191 | size += Log(snd); |
andrewboyson | 10:cf815db8ed57 | 192 | return size; |
andrewboyson | 0:9907e344c82a | 193 | } |
andrewboyson | 16:5c41b457c7f3 | 194 | int LogTimeF(const char *fmt, ...) |
andrewboyson | 0:9907e344c82a | 195 | { |
andrewboyson | 10:cf815db8ed57 | 196 | int size = 0; |
andrewboyson | 0:9907e344c82a | 197 | va_list argptr; |
andrewboyson | 0:9907e344c82a | 198 | va_start(argptr, fmt); |
andrewboyson | 10:cf815db8ed57 | 199 | size == logTimeOnly(); |
andrewboyson | 16:5c41b457c7f3 | 200 | size++; LogChar(' '); |
andrewboyson | 10:cf815db8ed57 | 201 | size += LogV(fmt, argptr); |
andrewboyson | 0:9907e344c82a | 202 | va_end(argptr); |
andrewboyson | 10:cf815db8ed57 | 203 | return size; |
andrewboyson | 0:9907e344c82a | 204 | } |
andrewboyson | 17:7acb89d71f48 | 205 | |
andrewboyson | 17:7acb89d71f48 | 206 | void LogNibbleAsHex(int nibble) |
andrewboyson | 17:7acb89d71f48 | 207 | { |
andrewboyson | 17:7acb89d71f48 | 208 | nibble &= 0x0F; |
andrewboyson | 17:7acb89d71f48 | 209 | char c; |
andrewboyson | 17:7acb89d71f48 | 210 | if (nibble < 0x0A) c = nibble + '0'; |
andrewboyson | 17:7acb89d71f48 | 211 | else if (nibble < 0x10) c = nibble - 0xA + 'A'; |
andrewboyson | 17:7acb89d71f48 | 212 | else c = '0'; |
andrewboyson | 17:7acb89d71f48 | 213 | LogChar(c); |
andrewboyson | 17:7acb89d71f48 | 214 | } |
andrewboyson | 17:7acb89d71f48 | 215 | |
andrewboyson | 17:7acb89d71f48 | 216 | void LogByteAsHex(int value) |
andrewboyson | 17:7acb89d71f48 | 217 | { |
andrewboyson | 17:7acb89d71f48 | 218 | LogNibbleAsHex(value >> 4); |
andrewboyson | 17:7acb89d71f48 | 219 | LogNibbleAsHex(value >> 0); |
andrewboyson | 17:7acb89d71f48 | 220 | } |
andrewboyson | 19:14376c221aec | 221 | void LogBytesAsHex(const uint8_t* bytes, int size) |
andrewboyson | 17:7acb89d71f48 | 222 | { |
andrewboyson | 17:7acb89d71f48 | 223 | int i = 0; |
andrewboyson | 17:7acb89d71f48 | 224 | while(true) |
andrewboyson | 17:7acb89d71f48 | 225 | { |
andrewboyson | 19:14376c221aec | 226 | LogByteAsHex(bytes[i]); |
andrewboyson | 17:7acb89d71f48 | 227 | i++; |
andrewboyson | 17:7acb89d71f48 | 228 | if (i >= size) break; |
andrewboyson | 18:617791ed3d8e | 229 | if (i % 16 == 0) Log("\r\n"); |
andrewboyson | 17:7acb89d71f48 | 230 | else LogChar(' '); |
andrewboyson | 17:7acb89d71f48 | 231 | } |
andrewboyson | 17:7acb89d71f48 | 232 | } |