Add 16-bit signed option

- Include an argument to set 16-bit output to signed. Default behavior is unsigned
- Utilizes a new (third) argument in the "hsdaoh_open" function to set a dev variable
- format_convert uses intermediate value to unpack 12-bit data, then ternary operator to store signed/unsigned
This commit is contained in:
montoyatim01 2025-04-25 09:02:42 -07:00
parent 3ea62bda0e
commit 03f618b941
7 changed files with 45 additions and 17 deletions

View file

@ -84,7 +84,7 @@ HSDAOH_API int hsdaoh_get_device_usb_strings(uint32_t index,
*/
HSDAOH_API int hsdaoh_get_index_by_serial(const char *serial);
HSDAOH_API int hsdaoh_open(hsdaoh_dev_t **dev, uint32_t index);
HSDAOH_API int hsdaoh_open(hsdaoh_dev_t **dev, uint32_t index, bool out_signed);
HSDAOH_API int hsdaoh_close(hsdaoh_dev_t *dev);

View file

@ -44,6 +44,7 @@ struct hsdaoh_dev {
unsigned int width, height, fps;
bool output_float;
bool output_signed;
iqconverter_float_t *cnv_f;
/* status */

View file

@ -69,10 +69,15 @@ void hsdaoh_unpack_pio_12bit(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info)
unsigned int j = 0;
for (unsigned int i = 0; i < inlen; i += 3) {
out[j++] = (in[i+2] & 0xf000) >> 4 | (in[i+1] & 0xf000) >> 8 | (in[i] >> 12);
out[j++] = in[i ] & 0x0fff;
out[j++] = in[i+1] & 0x0fff;
out[j++] = in[i+2] & 0x0fff;
uint16_t sample1 = (in[i+2] & 0xf000) >> 4 | (in[i+1] & 0xf000) >> 8 | (in[i] >> 12);
uint16_t sample2 = in[i ] & 0x0fff;
uint16_t sample3 = in[i+1] & 0x0fff;
uint16_t sample4 = in[i+2] & 0x0fff;
out[j++] = dev->output_signed ? (int16_t)((sample1 - 2048) << 4) : sample1;
out[j++] = dev->output_signed ? (int16_t)((sample2 - 2048) << 4) : sample2;
out[j++] = dev->output_signed ? (int16_t)((sample3 - 2048) << 4) : sample3;
out[j++] = dev->output_signed ? (int16_t)((sample4 - 2048) << 4) : sample4;
}
if (dev->output_float) {
@ -107,8 +112,11 @@ void hsdaoh_unpack_pio_12bit_dual(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_in
}
for (i = 0; i < j; i++) {
out16_1[i] = (out[i] >> 12) & 0x0fff;
out16_2[i] = out[i] & 0x0fff;
uint16_t sample1 = (out[i] >> 12) & 0x0fff;
uint16_t sample2 = out[i] & 0x0fff;
out16_1[i] = dev->output_signed ? (int16_t)((sample1 - 2048) << 4) : sample1;
out16_2[i] = dev->output_signed ? (int16_t)((sample2 - 2048) << 4) : sample2;
}
if (dev->output_float) {
@ -238,10 +246,16 @@ void hsdaoh_unpack_fpga_12bit_dual(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_i
/* extract packed 2x12 bit samples */
for (int i = 0; i < inlen; i += 3) {
uint16_t lsbs = in[i+2];
out16_1[j] = ((in[i+0] & 0xff00) >> 4) | ((lsbs >> 0) & 0xf);
out16_2[j++] = ((in[i+0] & 0x00ff) << 4) | ((lsbs >> 4) & 0xf);
out16_1[j] = ((in[i+1] & 0xff00) >> 4) | ((lsbs >> 8) & 0xf);
out16_2[j++] = ((in[i+1] & 0x00ff) << 4) | ((lsbs >> 12) & 0xf);
uint16_t sample1 = ((in[i+0] & 0xff00) >> 4) | ((lsbs >> 0) & 0xf);
uint16_t sample2 = ((in[i+0] & 0x00ff) << 4) | ((lsbs >> 4) & 0xf);
uint16_t sample3 = ((in[i+1] & 0xff00) >> 4) | ((lsbs >> 8) & 0xf);
uint16_t sample4 = ((in[i+1] & 0x00ff) << 4) | ((lsbs >> 12) & 0xf);
out16_1[j] = dev->output_signed ? (int16_t)((sample1 - 2048) << 4) : sample1;
out16_2[j++] = dev->output_signed ? (int16_t)((sample2 - 2048) << 4) : sample2;
out16_1[j] = dev->output_signed ? (int16_t)((sample3 - 2048) << 4) : sample3;
out16_2[j++] = dev->output_signed ? (int16_t)((sample4 - 2048) << 4) : sample4;
}
if (dev->output_float) {

View file

@ -53,6 +53,7 @@ void usage(void)
"Usage:\n"
"\t[-d device_index (default: 0)]\n"
"\t[-b maximum number of buffers (default: 16)]\n"
"\t[-s save 16-bit streams as signed integer]\n"
"\t[-0 to -3 filename of steam 0 to stream 3 (a '-' dumps samples to stdout)]\n"
"\tfilename (of stream 0) (a '-' dumps samples to stdout)\n\n");
exit(1);
@ -121,8 +122,9 @@ int main(int argc, char **argv)
unsigned int num_bufs = 0;
bool fname0_used = false;
bool have_file = false;
bool set_signed = false;
while ((opt = getopt(argc, argv, "0:1:2:3:d:b:")) != -1) {
while ((opt = getopt(argc, argv, "0:1:2:3:d:b:s:")) != -1) {
switch (opt) {
case 'd':
dev_index = (uint32_t)atoi(optarg);
@ -130,6 +132,9 @@ int main(int argc, char **argv)
case 'b':
num_bufs = (unsigned int)atoi(optarg);
break;
case 's':
set_signed = true;
break;
case '0':
fname0_used = true;
have_file = true;
@ -165,7 +170,7 @@ int main(int argc, char **argv)
if (dev_index < 0)
exit(1);
r = hsdaoh_open(&dev, (uint32_t)dev_index);
r = hsdaoh_open(&dev, (uint32_t)dev_index, set_signed);
if (r < 0) {
fprintf(stderr, "Failed to open hsdaoh device #%d.\n", dev_index);
exit(1);

View file

@ -325,6 +325,7 @@ int main(int argc, char **argv)
fd_set readfds;
u_long blockmode = 1;
dongle_info_t dongle_info;
int set_signed = 0;
#ifdef _WIN32
WSADATA wsd;
@ -333,7 +334,7 @@ int main(int argc, char **argv)
struct sigaction sigact, sigign;
#endif
while ((opt = getopt(argc, argv, "a:p:b:n:d")) != -1) {
while ((opt = getopt(argc, argv, "a:p:b:n:d:s")) != -1) {
switch (opt) {
case 'd':
dev_index = (uint32_t)atoi(optarg);
@ -350,6 +351,9 @@ int main(int argc, char **argv)
case 'n':
llbuf_num = atoi(optarg);
break;
case 's':
set_signed = 1;
break;
default:
usage();
break;
@ -363,7 +367,7 @@ int main(int argc, char **argv)
exit(1);
}
hsdaoh_open(&dev, (uint32_t)dev_index);
hsdaoh_open(&dev, (uint32_t)dev_index, set_signed);
if (NULL == dev) {
fprintf(stderr, "Failed to open hsdaoh device #%d.\n", dev_index);
exit(1);

View file

@ -274,7 +274,7 @@ int main(int argc, char **argv)
if (dev_index < 0)
exit(1);
r = hsdaoh_open(&dev, (uint32_t)dev_index);
r = hsdaoh_open(&dev, (uint32_t)dev_index, 0);
if (r < 0) {
fprintf(stderr, "Failed to open hsdaoh device #%d.\n", dev_index);
exit(1);

View file

@ -405,7 +405,7 @@ int _hsdaoh_open_uvc_device(hsdaoh_dev_t *dev)
return (int)r;
}
int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index)
int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index, bool out_signed)
{
int r;
int i;
@ -423,6 +423,10 @@ int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index)
memset(dev, 0, sizeof(hsdaoh_dev_t));
if (out_signed) {
dev->output_signed = 1;
}
r = libusb_init(&dev->ctx);
if(r < 0){
free(dev);