diff --git a/EmbeddedMode.txt b/EmbeddedMode.txt index 45e7217..51fad41 100644 --- a/EmbeddedMode.txt +++ b/EmbeddedMode.txt @@ -45,6 +45,15 @@ character. These sigil characters are: ! Error messages \ Shell messages +Another feature of output processing in embedded mode is that when +colourized output is enabled (``opt color true``), colourization is +always implemented by including ANSI escape codes in the output, even on +Windows. Normally, colourized output on Windows is implemented by +changing console text attributes. + +Shell messages +-------------- + Shell messages are emitted only when in embedded mode. They provide additional information to the front-end and consist of a type identifier string immediately following the sigil, then optionally a space and @@ -58,11 +67,18 @@ arguments. Currently, the following shell messages may be emitted: ~ The command process has accepted a command and is now executing it. -Another feature of output processing in embedded mode is that when -colourized output is enabled (``opt color true``), colourization is -always implemented by including ANSI escape codes in the output, even on -Windows. Normally, colourized output on Windows is implemented by -changing console text attributes. +\power-sample-us + + ~ Indicates that power profiling is enabled. The period argument is a + decimal number giving the sample period in microseconds. + +\power-samples + + ~ Power data captured from the running device. The data argument is a + Base64-encoded string. When decoded, it consists of a sequence of + 32-bit little-endian unsigned integers. Integers with bit 31 set are + MAB values, and those without bit 31 set are current consumption + readings, in microamps. Input processing and interruption ================================= diff --git a/drivers/fet_core.c b/drivers/fet_core.c index d4e13ed..86d6351 100644 --- a/drivers/fet_core.c +++ b/drivers/fet_core.c @@ -404,6 +404,7 @@ static void power_init(struct fet_device *dev) printc("Power profiling enabled: bufsize = %d bytes, %d us/sample\n", dev->proto.argv[1], dev->proto.argv[0]); + printc_shell("power-sample-us %d\n", dev->proto.argv[0]); dev->base.power_buf = powerbuf_new(POWERBUF_DEFAULT_SAMPLES, dev->proto.argv[0]); @@ -447,6 +448,23 @@ static int power_end(struct fet_device *dev) return 0; } +static void shell_power(const uint8_t *data, int len) +{ + while (len > 0) { + int plen = 128; + char text[256]; + + if (plen > len) + plen = len; + + base64_encode(data, plen, text, sizeof(text)); + printc_shell("power-samples %s\n", text); + + len -= plen; + data += plen; + } +} + static int power_poll(struct fet_device *dev) { address_t mab; @@ -467,6 +485,8 @@ static int power_poll(struct fet_device *dev) return -1; } + shell_power(dev->proto.data, dev->proto.datalen); + mab = powerbuf_last_mab(dev->base.power_buf); for (i = 0; i + 3 < dev->proto.datalen; i += 4) { uint32_t s = LE_LONG(dev->proto.data, i); diff --git a/util/util.c b/util/util.c index 0d59c2b..3c9c8bf 100644 --- a/util/util.c +++ b/util/util.c @@ -296,3 +296,41 @@ int delay_ms(unsigned int s) return nanosleep(&ts, NULL); } #endif + +int base64_encode(const uint8_t *src, int len, char *dst, int max_len) +{ + static const char basis[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + int i = 0; + int k = 0; + + while ((i < len) && (k + 4) < max_len) { + int a = src[i++]; + + dst[k++] = basis[a >> 2]; + + if (i < len) { + int b = src[i++]; + + dst[k++] = basis[((a & 3) << 4) | (b & 0xf0) >> 4]; + if (i < len) { + int c = src[i++]; + + dst[k++] = basis[((b & 0xf) << 2) | + ((c & 0xc0) >> 6)]; + dst[k++] = basis[c & 0x3f]; + } else { + dst[k++] = basis[(b & 0xf) << 2]; + dst[k++] = '='; + } + } else { + dst[k++] = basis[(a & 3) << 4]; + dst[k++] = '='; + dst[k++] = '='; + } + } + + dst[k] = 0; + return i; +} diff --git a/util/util.h b/util/util.h index 97460ea..42a5ccb 100644 --- a/util/util.h +++ b/util/util.h @@ -61,6 +61,16 @@ char *expand_tilde(const char *path); int delay_s(unsigned int s); int delay_ms(unsigned int s); +/* Base64 encode a block without breaking into lines. Returns the number + * of source bytes encoded. The output is nul-terminated. + */ +static inline int base64_encoded_size(int decoded_size) +{ + return ((decoded_size + 2) / 3) * 4; +} + +int base64_encode(const uint8_t *src, int len, char *dst, int max_len); + /* printf format for long long args */ #ifdef __MINGW32__ #define LLFMT "I64d"