mirror of
https://github.com/steve-m/hsdaoh.git
synced 2025-12-09 23:34:41 +01:00
add support for 12-bit dualchannel ADC (AD9238)
This commit is contained in:
parent
642de0654d
commit
5867fdb15c
4 changed files with 119 additions and 10 deletions
|
|
@ -2,6 +2,7 @@
|
|||
#define __FORMAT_CONVERT_H
|
||||
|
||||
void hsdaoh_unpack_pio_12bit(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info);
|
||||
void hsdaoh_unpack_pio_dualchan_12bit(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info);
|
||||
void hsdaoh_unpack_pio_12bit_dual(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info);
|
||||
void hsdaoh_unpack_pio_10bit_iq(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info);
|
||||
void hsdaoh_unpack_pio_8bit_iq(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct hsdaoh_dev {
|
|||
unsigned int width, height, fps;
|
||||
|
||||
bool output_float;
|
||||
iqconverter_float_t *cnv_f;
|
||||
iqconverter_float_t *cnv_f1, *cnv_f2;
|
||||
|
||||
/* status */
|
||||
int dev_lost;
|
||||
|
|
@ -108,6 +108,29 @@ enum
|
|||
PIO_32BIT,
|
||||
PIO_32BIT_IQ,
|
||||
PIO_PCM1802_AUDIO,
|
||||
PIO_AUDIO_PLACEHOLDER1,
|
||||
PIO_AUDIO_PLACEHOLDER2,
|
||||
PIO_AUDIO_PLACEHOLDER3,
|
||||
PIO_DUALCHAN_1BIT,
|
||||
PIO_DUALCHAN_1BIT_IQ,
|
||||
PIO_DUALCHAN_2BIT,
|
||||
PIO_DUALCHAN_2BIT_IQ,
|
||||
PIO_DUALCHAN_4BIT,
|
||||
PIO_DUALCHAN_4BIT_IQ,
|
||||
PIO_DUALCHAN_8BIT,
|
||||
PIO_DUALCHAN_8BIT_IQ,
|
||||
PIO_DUALCHAN_10BIT,
|
||||
PIO_DUALCHAN_10BIT_IQ,
|
||||
PIO_DUALCHAN_12BIT,
|
||||
PIO_DUALCHAN_12BIT_IQ,
|
||||
PIO_DUALCHAN_14BIT,
|
||||
PIO_DUALCHAN_14BIT_IQ,
|
||||
PIO_DUALCHAN_16BIT,
|
||||
PIO_DUALCHAN_16BIT_IQ,
|
||||
PIO_DUALCHAN_24BIT,
|
||||
PIO_DUALCHAN_24BIT_IQ,
|
||||
PIO_DUALCHAN_32BIT,
|
||||
PIO_DUALCHAN_32BIT_IQ,
|
||||
// Placeholder for internal ADC data from pico
|
||||
FPGA_1BIT = 256,
|
||||
FPGA_2BIT,
|
||||
|
|
|
|||
|
|
@ -32,10 +32,9 @@
|
|||
#include <hsdaoh_private.h>
|
||||
#include <format_convert.h>
|
||||
|
||||
static inline void hsdaoh_16bit_to_float(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info, uint16_t *buf, size_t length, float scale, bool duplicate)
|
||||
static inline void hsdaoh_16bit_to_float(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info, uint16_t *buf, size_t length, float scale, bool conv_iq)
|
||||
{
|
||||
unsigned int i, j = 0;
|
||||
|
||||
float *floats = malloc(sizeof(float) * dev->width * dev->height * 2 * 2);
|
||||
|
||||
if (!floats)
|
||||
|
|
@ -44,12 +43,45 @@ static inline void hsdaoh_16bit_to_float(hsdaoh_dev_t *dev, hsdaoh_data_info_t *
|
|||
for (unsigned int i = 0; i < length; i++) {
|
||||
float sample_i = buf[i];
|
||||
floats[j++] = (sample_i - scale) * (1/scale);
|
||||
|
||||
if (duplicate)
|
||||
floats[j++] = (sample_i - scale) * (1/scale);
|
||||
}
|
||||
|
||||
// iqconverter_float_process(dev->cnv_f, (float *) floats, j);
|
||||
if (conv_iq) {
|
||||
if (data_info->stream_id == 0)
|
||||
iqconverter_float_process(dev->cnv_f1, (float *) floats, j);
|
||||
else
|
||||
iqconverter_float_process(dev->cnv_f2, (float *) floats, j);
|
||||
}
|
||||
|
||||
data_info->buf = (uint8_t *)floats;
|
||||
data_info->len = j * sizeof(float);
|
||||
data_info->bits_per_samp = 32;
|
||||
data_info->nchans = 1;
|
||||
data_info->is_signed = true;
|
||||
data_info->is_float = true;
|
||||
dev->cb(data_info);
|
||||
|
||||
free(floats);
|
||||
}
|
||||
|
||||
static inline void hsdaoh_signed_12bit_to_float(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info, uint16_t *buf, size_t length, float scale, bool conv_iq)
|
||||
{
|
||||
unsigned int i, j = 0;
|
||||
float *floats = malloc(sizeof(float) * dev->width * dev->height * 2 * 2);
|
||||
|
||||
if (!floats)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
int16_t samp = (int16_t)(buf[i] << 4);
|
||||
floats[j++] = (samp >> 4) * (1/scale);
|
||||
}
|
||||
|
||||
if (conv_iq) {
|
||||
if (data_info->stream_id == 0)
|
||||
iqconverter_float_process(dev->cnv_f1, (float *) floats, j);
|
||||
else
|
||||
iqconverter_float_process(dev->cnv_f2, (float *) floats, j);
|
||||
}
|
||||
|
||||
data_info->buf = (uint8_t *)floats;
|
||||
data_info->len = j * sizeof(float);
|
||||
|
|
@ -96,6 +128,53 @@ void hsdaoh_unpack_pio_12bit(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info)
|
|||
free(out);
|
||||
}
|
||||
|
||||
// Same format as PIO 12 bit, but with two interleaved ADC channels
|
||||
void hsdaoh_unpack_pio_dualchan_12bit(hsdaoh_dev_t *dev, hsdaoh_data_info_t *data_info)
|
||||
{
|
||||
uint16_t *in = (uint16_t *)data_info->buf;
|
||||
size_t inlen = data_info->len / sizeof(uint16_t);
|
||||
uint16_t *out16_1 = malloc(sizeof(uint16_t) * dev->width * dev->height);
|
||||
uint16_t *out16_2 = malloc(sizeof(uint16_t) * dev->width * dev->height);
|
||||
unsigned int j = 0;
|
||||
|
||||
for (unsigned int i = 0; i < inlen; i += 3) {
|
||||
out16_1[j ] = (in[i+2] & 0xf000) >> 4 | (in[i+1] & 0xf000) >> 8 | (in[i] >> 12);
|
||||
out16_2[j++] = in[i ] & 0x0fff;
|
||||
out16_1[j ] = in[i+1] & 0x0fff;
|
||||
out16_2[j++] = in[i+2] & 0x0fff;
|
||||
}
|
||||
|
||||
data_info->bits_per_samp = 12;
|
||||
data_info->nchans = 1;
|
||||
|
||||
if (dev->output_float) {
|
||||
hsdaoh_signed_12bit_to_float(dev, data_info, out16_1, j, 2047.5, true);
|
||||
} else {
|
||||
data_info->buf = (uint8_t *)out16_1;
|
||||
data_info->len = j * sizeof(uint16_t);
|
||||
data_info->bits_per_samp = 12;
|
||||
data_info->nchans = 1;
|
||||
data_info->is_signed = true;
|
||||
data_info->is_float = false;
|
||||
|
||||
dev->cb(data_info);
|
||||
}
|
||||
|
||||
data_info->stream_id += 1;
|
||||
|
||||
if (dev->output_float) {
|
||||
hsdaoh_16bit_to_float(dev, data_info, out16_2, j, 2047.5, true);
|
||||
} else {
|
||||
data_info->buf = (uint8_t *)out16_2;
|
||||
|
||||
dev->cb(data_info);
|
||||
}
|
||||
|
||||
free(out16_1);
|
||||
free(out16_2);
|
||||
}
|
||||
|
||||
|
||||
// We receive three 32-bit words containing four 24-bit samples (sample A - D)
|
||||
// First word: A07 A06 A05 A04 A03 A02 A01 A00 B23 B22 B21 B20 B19 B18 B17 B16 B15 B14 B13 B12 B11 B10 B09 B08 B07 B06 B05 B04 B03 B02 B01 B00
|
||||
// Second word: A15 A14 A13 A12 A11 A10 A09 A08 C23 C22 C21 C20 C19 C18 C17 C16 C15 C14 C13 C12 C11 C10 C09 C08 C07 C06 C05 C04 C03 C02 C01 C00
|
||||
|
|
|
|||
|
|
@ -490,7 +490,8 @@ int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index)
|
|||
goto err;
|
||||
|
||||
dev->dev_lost = 0;
|
||||
dev->cnv_f = iqconverter_float_create(HB_KERNEL_FLOAT, HB_KERNEL_FLOAT_LEN);
|
||||
dev->cnv_f1 = iqconverter_float_create(HB_KERNEL_FLOAT, HB_KERNEL_FLOAT_LEN);
|
||||
dev->cnv_f2 = iqconverter_float_create(HB_KERNEL_FLOAT, HB_KERNEL_FLOAT_LEN);
|
||||
|
||||
found:
|
||||
*out_dev = dev;
|
||||
|
|
@ -522,7 +523,8 @@ int hsdaoh_close(hsdaoh_dev_t *dev)
|
|||
uvc_unref_device(dev->uvc_dev);
|
||||
uvc_exit(dev->uvc_ctx);
|
||||
|
||||
iqconverter_float_free(dev->cnv_f);
|
||||
iqconverter_float_free(dev->cnv_f1);
|
||||
iqconverter_float_free(dev->cnv_f2);
|
||||
free(dev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -564,6 +566,9 @@ void hsdaoh_output(hsdaoh_dev_t *dev, uint16_t sid, int format, uint32_t srate,
|
|||
case PIO_12BIT_DUAL:
|
||||
hsdaoh_unpack_pio_12bit_dual(dev, &data_info);
|
||||
break;
|
||||
case PIO_DUALCHAN_12BIT:
|
||||
hsdaoh_unpack_pio_dualchan_12bit(dev, &data_info);
|
||||
break;
|
||||
case PIO_PCM1802_AUDIO:
|
||||
hsdaoh_unpack_pio_pcm1802_audio(dev, &data_info);
|
||||
break;
|
||||
|
|
@ -837,7 +842,8 @@ int hsdaoh_start_stream(hsdaoh_dev_t *dev, hsdaoh_read_cb_t cb, void *ctx, unsig
|
|||
if (HSDAOH_INACTIVE != dev->async_status)
|
||||
return -2;
|
||||
|
||||
iqconverter_float_reset(dev->cnv_f);
|
||||
iqconverter_float_reset(dev->cnv_f1);
|
||||
iqconverter_float_reset(dev->cnv_f2);
|
||||
|
||||
dev->async_status = HSDAOH_RUNNING;
|
||||
dev->async_cancel = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue