Skip to content

Commit

Permalink
more resolution in mix2.c
Browse files Browse the repository at this point in the history
  • Loading branch information
twatorowski committed Feb 8, 2020
1 parent 8bd9e60 commit 0d7dbce
Show file tree
Hide file tree
Showing 14 changed files with 594 additions and 131 deletions.
9 changes: 6 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ OPT_LEVEL = -Os

# -------------------------- VERSION NUMBER -------------------------
# software version
SW_VER_MAJOR = 0
SW_VER_MAJOR = 1
SW_VER_MINOR = 0
SW_VER_BUILD = 1
SW_VER_BUILD = 0

# hardware version
HW_VER_MAJOR = 1
Expand All @@ -35,7 +35,10 @@ SRC += ./at/src/ntf.c
SRC += ./at/cmd/src/gen.c ./at/cmd/src/radio.c

# at protocol notification submodules
SRC += ./at/ntf/src/debug.c
SRC += ./at/ntf/src/debug.c ./at/ntf/src/radio.c

# base64 encoder-decoder
SRC += ./base64/src/base64.c

# device drivers
SRC += ./dev/src/usart2.c ./dev/src/watchdog.c
Expand Down
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
# stm32l476-radio-receiver

All on-board digital AM radio receiver implemented on the stm32l4discovery board. No external components needed. Well maybe besides the looooong antenna wire.
All digital AM radio receiver implemented on the stm32l4-discovery board. All the information is here:
https://mightydevices.com/index.php/2020/02/stm32l4-discovery-radio-receiver/

## Principle of operation

TODO

## Makefile

This project can be build using gcc or llvm (clang). This is how the Makefile and the linker script was prepared. Makefile is GNUMake compatible. You can configure all the tools used for building, add sources, libraries, etc..

## How to build

This project can be build using arm-none-eabi-gcc. This is how the Makefile and the linker script were prepared for. Makefile is GNUMake compatible.

Two things are needed:

* Toolchain that contains C compiler, linker and supporting tools (like objcopy, objdump, nm, size) may be gcc arm embedded toolchain or clang/llvm equivalents with libraries such as libc, libg, libm or whatever you may require
* Toolchain that contains C compiler, like the one from developer.arm.com
* GNUMake to 'execute' the Makefile

Building using GCC:
```
make TOOLCHAIN=gcc all
If you into dockerization then please read: https://mightydevices.com/index.php/2019/09/stm32-development-env-for-windows-vscode-arm-gcc-toolchain-openocd/


Building command:
```
Builing using LLVM:
make all
```
make TOOLCHAIN=llvm all
```

The firmware will be put into `./outs` directory
11 changes: 2 additions & 9 deletions at/ntf.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
/** @{ */
/** @brief debug notifications */
#define AT_NTF_MASK_DEBUG (0x00000001)
/** @brief radio data notifications */
#define AT_NTF_MASK_RADIO_DATA (0x00000002)
/** @brief radio iq samples */
#define AT_NTF_MASK_RADIO_IQ (0x00000002)
/** @} */
/** @} */

Expand All @@ -37,13 +37,6 @@ int ATNtf_Init(void);
*/
void ATNtf_Poll(void);

/**
* @brief This function shall invoke the notification data drainage, which will in
* turn produce notification strings and try to put them within the output buffer. To
* be called by the ATRxTx drivers at the end of transmission.
*/
void ATNtf_DrainData(void);

/**
* @brief Sets the notification mask, enabling or disabling the notifications on
* selected interface.
Expand Down
21 changes: 21 additions & 0 deletions at/ntf/radio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @file radio.h
*
* @date 2020-02-05
* @author twatorowski
*
* @brief AT Notifications: Radio.
*/

#ifndef AT_NTF_RADIO_H
#define AT_NTF_RADIO_H


/* initialize radio notifications submodule */
int ATNtfRadio_Init(void);
/* poll radio notifications submodule */
void ATNtfRadio_Poll(void);
/* store the iq data samples in at notifications buffer */
int ATNtfRadio_PutIQSamples(const float *i, const float *q, int num);

#endif /* AT_NTF_RADIO_H */
105 changes: 92 additions & 13 deletions at/ntf/src/radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,126 @@
#include <stdint.h>
#include <stddef.h>

#include "compiler.h"
#include "config.h"
#include "err.h"
#include "at/ntfy.h"
#include "at/ntf.h"
#include "at/rxtx.h"
#include "base64/base64.h"
#include "util/elems.h"
#include "util/minmax.h"
#include "util/string.h"

/* iqdata buffer */
static struct iqdata {
/* samples buffer */
float buf[128];
struct iqdata_iq { float i, q; } PACKED ALIGNED(8) buf[128];
/* pointers */
uint32_t head, tail;
} iqdata;

/* polling for the iq samples */
static void ATNtfRadio_IQSamplesPoll(void)
{
/* data sent? */
int sent = 0;
/* response buffer */
char buf[AT_RES_MAX_LINE_LEN] = "+RADIO_IQ: ";
/* current len of the response */
int len = sizeof("+RADIO_IQ: ") - 1;

/* notification mask */
uint32_t mask;
/* get mask for all notifications */
ATNtf_GetNotificationORMask(&mask);
/* notification is disabled? */
if (!(mask & AT_NTF_MASK_RADIO_IQ))
iqdata.tail = iqdata.head;
/* no samples are stored */
if (iqdata.head - iqdata.tail < 16)
return;

/* get the number data characters that can be put into the response */
int max_chars = sizeof(buf) - len - sizeof(AT_LINE_END);
/* convert to maximal number of representable bytes when base64 is used */
int max_bytes = (max_chars / 4) * 3;
/* get tail index */
int t = iqdata.tail % elems(iqdata.buf);
/* limit the number of iq pairs to be sent in current line while not
* wrapping within the circular buffer */
int max_iqs = min(iqdata.head - iqdata.tail,
min(elems(iqdata.buf) - t, max_bytes / sizeof(struct iqdata_iq)));

/* encode data in base64 */
int b64_len = Base64_Encode(iqdata.buf + t,
sizeof(struct iqdata_iq) * max_iqs, buf + len, max_chars);
/* append the line ending sequence */
memcpy(buf + len + b64_len, AT_LINE_END, sizeof(AT_LINE_END));

/* send response */
for (int iface = 0; iface < ATRXTX_IFACENUM; iface++) {
/* get notification mask for given interface */
ATNtf_GetNotificationMask(iface, &mask);
/* notifications enabled for given interface? */
if ((mask & AT_NTF_MASK_RADIO_IQ)) {
/* send the actual data */
sent |= ATRxTx_SendResponse(iface, 1, buf, len + b64_len +
sizeof(AT_LINE_END) - 1) == EOK;
}
}

/* data was sent, update the buffer */
if (sent)
iqdata.tail += max_iqs;
}

/* initialize radio notifications submodule */
int ATNtfyRadio_Init(void)
int ATNtfRadio_Init(void)
{
/* report status */
return EOK;
}

/* poll radio notifications submodule */
void ATNtfyRadio_Poll(void)
void ATNtfRadio_Poll(void)
{

/* polling for the iq samples */
ATNtfRadio_IQSamplesPoll();
}

/* store the iq data samples in at notifications buffer */
int ATRadio_PutIQsamples(const float *i, const float *q, int num)
int ATNtfRadio_PutIQSamples(const float *i, const float *q, int num)
{
/* data stored? */
int sent = 0;
/* notification mask placeholder */
uint32_t mask;

/* get mask for all notifications */
ATNtfy_GetNotificationORMask(&mask);
/* this is to avoid stalling debugs when no interface has enabled
* debug logic */
if (!(mask & AT_NTFY_MASK_RADIO_DATA))
ATNtf_GetNotificationORMask(&mask);
/* radio data notifications enabled? */
if (!(mask & AT_NTF_MASK_RADIO_IQ))
return EOK;
/* no space in buffer */
if (num > elems(iqdata.buf) - (iqdata.head - iqdata.tail))
return EFATAL;

/* head element index */
int h = iqdata.head % elems(iqdata.buf);
/* number of elements to be stored before wrapping */
int bwrap = min(num, elems(iqdata.buf) - h);
/* number of elements to be stored after wrapping */
int awrap = num - bwrap;

/* store before wrapping */
for (; bwrap ; bwrap--, h++) {
iqdata.buf[h].i = *i++; iqdata.buf[h].q = *q++;
}
/* store after wrapping */
for (h = 0; awrap; awrap--, h++) {
iqdata.buf[h].i = *i++; iqdata.buf[h].q = *q++;
}

/* update the head pointer */
iqdata.head += num;
/* report status */
return sent ? EOK : EFATAL;
return EOK;
}
3 changes: 3 additions & 0 deletions at/src/ntf.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

/* submodules */
#include "at/ntf/debug.h"
#include "at/ntf/radio.h"

/* notification mask */
static uint32_t ntf_mask[ATRXTX_IFACENUM] = {
Expand All @@ -34,6 +35,7 @@ int ATNtf_Init(void)

/* initialize all notification submodules */
rc |= ATNtfDebug_Init();
rc |= ATNtfRadio_Init();

/* report status */
return EOK;
Expand All @@ -45,6 +47,7 @@ void ATNtf_Poll(void)
/* poll all notification submodules */
/* debug */
ATNtfDebug_Poll();
ATNtfRadio_Poll();
}

/* set notification mask */
Expand Down
8 changes: 4 additions & 4 deletions at/src/rxtx_usart2.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static volatile uint32_t rx_buf_offs, tx_head, tx_head_alloc, tx_tail;
static uint8_t rx_buf[512 + 32], tx_buf[2048];

/* usart transmission complete callback */
static int ATRxTxUSART2_USART1TxCallback(void *ptr)
static int ATRxTxUSART2_USART2TxCallback(void *ptr)
{
/* callback argument */
usart2_cbarg_t *arg = ptr;
Expand All @@ -53,7 +53,7 @@ static int ATRxTxUSART2_USART1TxCallback(void *ptr)
/* limit to the number of bytes buffered */
bytes_wrap = min(bytes_wrap, bytes_buffered);
/* send the data */
USART2_Send(tx_buf + tail, bytes_wrap, ATRxTxUSART2_USART1TxCallback);
USART2_Send(tx_buf + tail, bytes_wrap, ATRxTxUSART2_USART2TxCallback);
}

/* report status */
Expand Down Expand Up @@ -109,7 +109,7 @@ int ATRxTxUSART2_Init(void)
{
/* lock the reception semaphore and start reception */
Sem_Lock(&usart2rx_sem, ATRxTxUSART2_USART1RxCallback);
Sem_Lock(&usart2tx_sem, ATRxTxUSART2_USART1TxCallback);
Sem_Lock(&usart2tx_sem, ATRxTxUSART2_USART2TxCallback);
/* report status */
return EOK;
}
Expand Down Expand Up @@ -159,7 +159,7 @@ int ATRxTxUSART2_SendResponse(int is_notify, const char *str, size_t len)
Atomic_MOV32(&tx_head, &tx_head_alloc);
/* restart transmission */
if (Sem_Lock(&usart2tx_sem, CB_NONE) == EOK)
ATRxTxUSART2_USART1TxCallback(0);
ATRxTxUSART2_USART2TxCallback(0);
}

/* report success */
Expand Down
43 changes: 43 additions & 0 deletions base64/base64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @file base64.h
*
* @date 2019-11-27
* @author twatorowski
*
* @brief Base64 encoding/decoding functions.
*/

#ifndef BASE64_BASE64_H_
#define BASE64_BASE64_H_

#include <stddef.h>

/* encode with base64 */

/**
* @brief Encode the input data with Base64 encoding. The algorithm works
* backwards to make the in-situ operation possible if needed.
*
* @param in input data pointer
* @param in_size size of the input data
* @param out output data pointer
* @param out_size maximal size of the output buffer
*
* @return int actual encoded data size
*/
int Base64_Encode(const void *in, size_t in_size, void *out, size_t out_size);
/* decode base64 string */

/**
* @brief Decode the provided Base64 string. Can work in-situ.
*
* @param in pointer to Base64 encoded data
* @param in_size size of the input data
* @param out
* @param out_size
*
* @return int
*/
int Base64_Decode(const void *in, size_t in_size, void *out, size_t out_size);

#endif /* BASE64_BASE64_H_ */
Loading

0 comments on commit 0d7dbce

Please sign in to comment.