2 * This file is part of the libsigrok project.
4 * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libsigrok.h"
24 #include "libsigrok-internal.h"
26 #define LOG_PREFIX "output/hex"
28 #define DEFAULT_SAMPLES_PER_LINE 192
31 unsigned int num_enabled_channels
;
45 static int init(struct sr_output
*o
)
48 struct sr_channel
*ch
;
58 spl
= DEFAULT_SAMPLES_PER_LINE
;
59 g_hash_table_iter_init(&iter
, o
->params
);
60 while (g_hash_table_iter_next(&iter
, &key
, &value
)) {
61 if (!strcmp(key
, "width")) {
62 if ((spl
= strtoul(value
, NULL
, 10)) < 1) {
63 sr_err("Invalid width.");
67 sr_err("Unknown parameter '%s'.", key
);
72 ctx
= g_malloc0(sizeof(struct context
));
75 ctx
->samples_per_line
= spl
;
77 for (l
= o
->sdi
->channels
; l
; l
= l
->next
) {
79 if (ch
->type
!= SR_CHANNEL_LOGIC
)
83 ctx
->num_enabled_channels
++;
85 ctx
->channel_index
= g_malloc(sizeof(int) * ctx
->num_enabled_channels
);
86 ctx
->channel_names
= g_malloc(sizeof(char *) * ctx
->num_enabled_channels
);
87 ctx
->lines
= g_malloc(sizeof(GString
*) * ctx
->num_enabled_channels
);
88 ctx
->sample_buf
= g_malloc(ctx
->num_enabled_channels
);
91 for (i
= 0, l
= o
->sdi
->channels
; l
; l
= l
->next
, i
++) {
93 if (ch
->type
!= SR_CHANNEL_LOGIC
)
97 ctx
->channel_index
[j
] = ch
->index
;
98 ctx
->channel_names
[j
] = ch
->name
;
99 ctx
->lines
[j
] = g_string_sized_new(80);
100 ctx
->sample_buf
[j
] = 0;
101 g_string_printf(ctx
->lines
[j
], "%s:", ch
->name
);
108 static GString
*gen_header(struct sr_output
*o
)
117 if (ctx
->samplerate
== 0) {
118 if (sr_config_get(o
->sdi
->driver
, o
->sdi
, NULL
, SR_CONF_SAMPLERATE
,
120 ctx
->samplerate
= g_variant_get_uint64(gvar
);
121 g_variant_unref(gvar
);
125 header
= g_string_sized_new(512);
126 g_string_printf(header
, "%s\n", PACKAGE_STRING
);
127 num_channels
= g_slist_length(o
->sdi
->channels
);
128 g_string_append_printf(header
, "Acquisition with %d/%d channels",
129 ctx
->num_enabled_channels
, num_channels
);
130 if (ctx
->samplerate
!= 0) {
131 samplerate_s
= sr_samplerate_string(ctx
->samplerate
);
132 g_string_append_printf(header
, " at %s", samplerate_s
);
133 g_free(samplerate_s
);
135 g_string_append_printf(header
, "\n");
140 static int receive(struct sr_output
*o
, const struct sr_datafeed_packet
*packet
,
143 const struct sr_datafeed_meta
*meta
;
144 const struct sr_datafeed_logic
*logic
;
145 const struct sr_config
*src
;
148 int idx
, pos
, offset
;
155 if (!(ctx
= o
->internal
))
158 switch (packet
->type
) {
160 meta
= packet
->payload
;
161 for (l
= meta
->config
; l
; l
= l
->next
) {
163 if (src
->key
!= SR_CONF_SAMPLERATE
)
165 ctx
->samplerate
= g_variant_get_uint64(src
->data
);
169 ctx
->trigger
= ctx
->spl_cnt
;
172 if (!ctx
->header_done
) {
173 *out
= gen_header(o
);
174 ctx
->header_done
= TRUE
;
176 *out
= g_string_sized_new(512);
178 logic
= packet
->payload
;
179 for (i
= 0; i
<= logic
->length
- logic
->unitsize
; i
+= logic
->unitsize
) {
181 pos
= ctx
->spl_cnt
& 7;
182 for (j
= 0; j
< ctx
->num_enabled_channels
; j
++) {
183 idx
= ctx
->channel_index
[j
];
184 p
= logic
->data
+ i
+ idx
/ 8;
185 ctx
->sample_buf
[j
] <<= 1;
186 if (*p
& (1 << (idx
% 8)))
187 ctx
->sample_buf
[j
] |= 1;
188 if (ctx
->spl_cnt
&& pos
== 0) {
189 /* Buffered a byte's worth, output hex. */
190 g_string_append_printf(ctx
->lines
[j
], "%.2x ",
192 ctx
->sample_buf
[j
] = 0;
195 if (ctx
->spl_cnt
== ctx
->samples_per_line
) {
196 /* Flush line buffers. */
197 g_string_append_len(*out
, ctx
->lines
[j
]->str
, ctx
->lines
[j
]->len
);
198 g_string_append_c(*out
, '\n');
199 if (j
== ctx
->num_enabled_channels
- 1 && ctx
->trigger
> -1) {
200 offset
= ctx
->trigger
+ ctx
->trigger
/ 8;
201 g_string_append_printf(*out
, "T:%*s^ %d\n", offset
, "", ctx
->trigger
);
204 g_string_printf(ctx
->lines
[j
], "%s:", ctx
->channel_names
[j
]);
207 if (ctx
->spl_cnt
== ctx
->samples_per_line
)
208 /* Line buffers were already flushed. */
214 /* Line buffers need flushing. */
215 *out
= g_string_sized_new(512);
216 for (i
= 0; i
< ctx
->num_enabled_channels
; i
++) {
217 if (ctx
->spl_cnt
& 7)
218 g_string_append_printf(ctx
->lines
[i
], "%.2x ",
219 ctx
->sample_buf
[i
] << (8 - (ctx
->spl_cnt
& 7)));
220 g_string_append_len(*out
, ctx
->lines
[i
]->str
, ctx
->lines
[i
]->len
);
221 g_string_append_c(*out
, '\n');
230 static int cleanup(struct sr_output
*o
)
238 if (!(ctx
= o
->internal
))
241 g_free(ctx
->channel_index
);
242 g_free(ctx
->sample_buf
);
243 g_free(ctx
->channel_names
);
244 for (i
= 0; i
< ctx
->num_enabled_channels
; i
++)
245 g_string_free(ctx
->lines
[i
], TRUE
);
253 SR_PRIV
struct sr_output_format output_hex
= {
255 .description
= "Hexadecimal",