commit 17b721e71fff68133ab4adecfeb778e236b1bb5f
parent 74bba63f4f1b1694356b8a693f817376ca80e77b
Author: Brian Swetland <swetland@frotz.net>
Date: Fri, 3 Jul 2015 04:25:44 -0700
add -s option to decode SWO/SWV packet streams
Diffstat:
M | sconsole.c | | | 150 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 150 insertions(+), 0 deletions(-)
diff --git a/sconsole.c b/sconsole.c
@@ -238,6 +238,150 @@ void usage(void) {
);
}
+typedef enum {
+ SWV_SYNC,
+ SWV_1X1,
+ SWV_1X2,
+ SWV_1X4,
+ SWV_2X2,
+ SWV_2X4,
+ SWV_3X4,
+ SWV_4X4,
+ SWV_PROTO,
+ SWV_IDLE,
+} swv_state_t;
+
+typedef struct {
+ swv_state_t state;
+ unsigned zcount;
+ unsigned ccount;
+ unsigned id;
+ unsigned val;
+ unsigned char data[8];
+} swv_t;
+
+static swv_t swv = {
+ .state = SWV_SYNC,
+ .zcount = 0
+};
+
+void handle_swv_src(unsigned id, unsigned val, unsigned n) {
+ printf("SRC %s %02x %08x\n", (id & 0x100) ? "HW" : "SW", id & 0xFF, val);
+}
+
+void handle_swv_proto(unsigned char *data, unsigned len) {
+ switch (len) {
+ case 1:
+ printf("PRO %02x\n", data[0]);
+ break;
+ case 2:
+ printf("PRO %02x %02x\n", data[0], data[1]);
+ break;
+ case 3:
+ printf("PRO %02x %02x %02x\n",
+ data[0], data[1], data[2]);
+ break;
+ case 4:
+ printf("PRO %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3]);
+ break;
+ case 5:
+ printf("PRO %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3], data[4]);;
+ break;
+ case 6:
+ printf("PRO %02x %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3],
+ data[4], data[5]);
+ break;
+ case 7:
+ printf("PRO %02x %02x %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6]);
+ break;
+ }
+}
+
+void handle_swv(swv_t *swv, unsigned x) {
+ //printf("%02x ", x); fflush(stdout);
+ // any sequence ending in 00 00 00 00 00 80 is a re-sync
+ if (x == 0) {
+ swv->zcount++;
+ } else {
+ if ((swv->zcount >= 5) && (x == 0x80)) {
+ swv->state = SWV_IDLE;
+ swv->zcount = 0;
+ printf("SYNC\n");
+ return;
+ }
+ swv->zcount = 0;
+ }
+
+ switch (swv->state) {
+ case SWV_IDLE:
+ if (x & 7) {
+ // AAAAAHSS source packet
+ swv->id = (x >> 3) | ((x & 4) << 6);
+ swv->val = 0;
+ swv->state = (x & 3);
+ } else if (x != 0) {
+ // CXXXXX00 protocol packet
+ swv->data[0] = x;
+ if (x & 0x80) {
+ swv->ccount = 1;
+ swv->state = SWV_PROTO;
+ } else {
+ handle_swv_proto(swv->data, 1);
+ }
+ } else {
+ // 00 packets are for sync, ignore
+ }
+ break;
+ case SWV_PROTO:
+ swv->data[swv->ccount++] = x;
+ // protocol packets end at 7 total bytes or a byte with bit7 clear
+ if ((swv->ccount == 7) || (!(x & 0x80))) {
+ handle_swv_proto(swv->data, swv->ccount);
+ swv->state = SWV_IDLE;
+ }
+ break;
+ case SWV_1X1:
+ handle_swv_src(swv->id, x, 1);
+ swv->state = SWV_IDLE;
+ break;
+ case SWV_1X2:
+ swv->val = x;
+ swv->state = SWV_2X2;
+ break;
+ case SWV_2X2:
+ handle_swv_src(swv->id, swv->val | (x << 8), 2);
+ swv->state = SWV_IDLE;
+ break;
+ case SWV_1X4:
+ swv->val = x;
+ swv->state = SWV_2X4;
+ break;
+ case SWV_2X4:
+ swv->val |= (x << 8);
+ swv->state = SWV_3X4;
+ break;
+ case SWV_3X4:
+ swv->val |= (x << 16);
+ swv->state = SWV_4X4;
+ break;
+ case SWV_4X4:
+ handle_swv_src(swv->id, swv->val | (x << 24), 4);
+ swv->state = SWV_IDLE;
+ break;
+ case SWV_SYNC:
+ break;
+ default:
+ // impossible
+ printf("fatal error, bad state %d\n", swv->state);
+ exit(1);
+ }
+}
+
int main(int argc, char *argv[])
{
struct pollfd fds[2];
@@ -254,6 +398,7 @@ int main(int argc, char *argv[])
int logfd = -1;
int hexmode = 0;
unsigned char ESC = 27;
+ int decode_swv = 0;
for (n = ' '; n < 127; n++)
valid[n] = 1;
@@ -287,6 +432,9 @@ int main(int argc, char *argv[])
case 'h':
usage();
return 0;
+ case 's':
+ decode_swv = 1;
+ break;
default:
fprintf(stderr, "error: unknown option %s\n\n", argv[1]);
usage();
@@ -390,6 +538,8 @@ int main(int argc, char *argv[])
char hex[4];
sprintf(hex, "%02x ", x);
write(1, hex, 3);
+ } else if (decode_swv) {
+ handle_swv(&swv, x);
} else {
unsigned char c = x;
if (!valid[x])