Last active
March 21, 2018 20:29
-
-
Save Mictronics/7aff25e832a67d51a5ea9b767419829b to your computer and use it in GitHub Desktop.
Creates sinus and cosinus lookup tables for IQ signal generation for AD9361 (ADALM-Pluto) simulating TX channel settings.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Creates sinus and cosinus lookup tables for IQ signal generation | |
* for AD9361 (ADALM-Pluto) simulating TX channel settings. | |
* | |
* channel_convert_inverse Converts I or Q sample from host format into hardware format. | |
* channel_convert Converts I or Q sample from hardware format into host format. | |
* | |
* See https://github.com/analogdevicesinc/libiio/blob/master/channel.c | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <string.h> | |
#include <iio.h> | |
static void byte_swap(uint8_t *dst, const uint8_t *src, size_t len) { | |
size_t i; | |
for (i = 0; i < len; i++) | |
dst[i] = src[len - i - 1]; | |
} | |
static void shift_bits(uint8_t *dst, size_t shift, size_t len, bool left) { | |
size_t i, shift_bytes = shift / 8; | |
shift %= 8; | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
if (!left) | |
#else | |
if (left) | |
#endif | |
{ | |
if (shift_bytes) { | |
memmove(dst, dst + shift_bytes, len - shift_bytes); | |
memset(dst + len - shift_bytes, 0, shift_bytes); | |
} | |
if (shift) { | |
for (i = 0; i < len; i++) { | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
dst[i] >>= shift; | |
if (i < len - 1) | |
dst[i] |= dst[i + 1] << (8 - shift); | |
#else | |
dst[i] <<= shift; | |
if (i < len - 1) | |
dst[i] |= dst[i + 1] >> (8 - shift); | |
#endif | |
} | |
} | |
} else { | |
if (shift_bytes) { | |
memmove(dst + shift_bytes, dst, len - shift_bytes); | |
memset(dst, 0, shift_bytes); | |
} | |
if (shift) { | |
for (i = len; i > 0; i--) { | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
dst[i - 1] <<= shift; | |
if (i > 1) | |
dst[i - 1] |= dst[i - 2] >> (8 - shift); | |
#else | |
dst[i - 1] >>= shift; | |
if (i > 1) | |
dst[i - 1] |= dst[i - 2] << (8 - shift); | |
#endif | |
} | |
} | |
} | |
} | |
static void sign_extend(uint8_t *dst, size_t bits, size_t len) { | |
size_t upper_bytes = ((len * 8 - bits) / 8); | |
uint8_t msb, msb_bit = 1 << ((bits - 1) % 8); | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
msb = dst[len - 1 - upper_bytes] & msb_bit; | |
if (upper_bytes) | |
memset(dst + len - upper_bytes, msb ? 0xff : 0x00, upper_bytes); | |
if (msb) | |
dst[len - 1 - upper_bytes] |= ~(msb_bit - 1); | |
else | |
dst[len - 1 - upper_bytes] &= (msb_bit - 1); | |
#else | |
/* XXX: untested */ | |
msb = dst[upper_bytes] & msb_bit; | |
if (upper_bytes) | |
memset(dst, msb ? 0xff : 0x00, upper_bytes); | |
if (msb) | |
dst[upper_bytes] |= ~(msb_bit - 1); | |
#endif | |
} | |
static void mask_upper_bits(uint8_t *dst, size_t bits, size_t len) { | |
size_t i; | |
/* Clear upper bits */ | |
if (bits % 8) | |
dst[bits / 8] &= (1 << (bits % 8)) - 1; | |
/* Clear upper bytes */ | |
for (i = (bits + 7) / 8; i < len; i++) | |
dst[i] = 0; | |
} | |
void channel_convert_inverse(void *dst, const void *src) { | |
uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst; | |
unsigned int len = 16 / 8; | |
ptrdiff_t end = len * 1; | |
uintptr_t end_ptr = dst_ptr + end; | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
bool swap = false; | |
#else | |
bool swap = !false; | |
#endif | |
uint8_t buf[1024]; | |
/* Somehow I doubt we will have samples of 8192 bits each. */ | |
if (len > sizeof (buf)) | |
return; | |
for (dst_ptr = (uintptr_t) dst; dst_ptr < end_ptr; | |
src_ptr += len, dst_ptr += len) { | |
memcpy(buf, (const void *) src_ptr, len); | |
mask_upper_bits(buf, 16, len); | |
if (0) | |
shift_bits(buf, 0, len, true); | |
if (len == 1 || !swap) | |
memcpy((void *) dst_ptr, buf, len); | |
else | |
byte_swap((void *) dst_ptr, buf, len); | |
} | |
} | |
void channel_convert(void *dst, const void *src) { | |
uintptr_t src_ptr = (uintptr_t) src, dst_ptr = (uintptr_t) dst; | |
unsigned int len = 16 / 8; | |
ptrdiff_t end = len * 1; | |
uintptr_t end_ptr = src_ptr + end; | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
bool swap = false; | |
#else | |
bool swap = !false; | |
#endif | |
for (src_ptr = (uintptr_t) src; src_ptr < end_ptr; | |
src_ptr += len, dst_ptr += len) { | |
if (len == 1 || !swap) | |
memcpy((void *) dst_ptr, (const void *) src_ptr, len); | |
else | |
byte_swap((void *) dst_ptr, (const void *) src_ptr, | |
len); | |
if (0) | |
shift_bits((void *) dst_ptr, 0, len, false); | |
if (!true) { | |
if (true) | |
sign_extend((void *) dst_ptr, 16, len); | |
else | |
mask_upper_bits((void *) dst_ptr, 16, len); | |
} | |
} | |
} | |
/* | |
* | |
*/ | |
int main(int argc, char** argv) { | |
const int amp = 32767; | |
const double steps = 512.0; | |
const double d2r = M_PI /180; | |
const double rad = (360.0 / steps) * d2r; | |
short in, out; | |
printf("\nconst int sinTable512[] = {\n"); | |
for(int i = 0; i < steps; i++) { | |
in = (short)(sin(i * rad) * amp); | |
channel_convert_inverse(&out, &in); | |
printf("%d, ", (int)out); | |
if(i%16 == 15){ | |
printf("\n"); | |
} | |
} | |
printf("};\n\nconst int cosTable512[] = {\n"); | |
for(int i = 0; i < steps; i++) { | |
in = (short)(cos(i * rad) * amp); | |
channel_convert_inverse(&out, &in); | |
printf("%d, ", (int)out); | |
if(i%16 == 15){ | |
printf("\n"); | |
} | |
} | |
printf("};\n"); | |
return (EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment