Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions components/lifesensor_common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(
INCLUDE_DIRS
include
)
49 changes: 49 additions & 0 deletions components/lifesensor_common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Lifesensor common component
For ease of declaration and definition of groups of tasks and queues the *lifesensor_macros* offer a set of easy to use task and queue creation shortcuts.

## Macros

### Concept
The `LIFESENSOR_TASK()` and `LIFESENSOR_QUEUE()` macro offer an easy interface to descibe the struct for a functional unit of the lifesensor. Each task or queue created with these shortcuts have to be initialized with the `lifesensor_task_init()` and respectively the `lifesensor_queue_init()` function.

`LIFESENSOR_TASK(stacksize)`
Construct a struct for a task. The `stacksize` is given in counts of `StackType_t` not in bytes. You can make use of `MACRO_DEFAULT_STACK_SIZE`. The structs `task` member will be the actual `lifesensor_task_t` which in turn contains the `StaticTask_t`.

`LIFESENSOR_QUEUE(type, itemcount)`
Construct a struct for a queue. The `type` attribute must be a valid datatype and will be used with `sizeof`. `itemcount` is the number of items of `type` which fit in the queue to be constructed. The structs `queue` memver will be the actual `lifesensor_queue_t` variable. Which in turn contains the `StaticQueue_t`.

`lifesensor_task_init(anon_task, name, func, args, prio)`
Initiazes a task created with `LIFESENSOR_TASK()` by passing in a pointer to it as first argument. For the `name` parameter a `const char *` is expected. `func` is expected to be a function pointer with its arguments passed in `args` as a `void *`. You can use `tskIDLE_PRIORITY` for the task priotity in the `prio` argument.

`lifesensor_queue_init(anon_queue)`
Initalizes a queue created with `LIFESENSOR_QUEUE()` by passing in a pointer to it as first argument. Generally this function should be called before passing a queue to i.e. a task as argument.


### Examples
```C
typedef struct {
LIFESENSOR_QUEUE(spo2_adc_sample_t, 16) adc_queue;
LIFESENSOR_TASK(4096) adc_task;
} spo2_t;


spo2_t spo2;
```

```C
void app_main()
{
lifesensor_queue_init(spo2.adc_queue);
lifesensor_task_init(
spo2.adc_task,
"spo2_adc",
spo2_runner,
&spo2.adc_queue.queue,
tskIDLE_PRIORITY
);
}

```

### Related
none
65 changes: 65 additions & 0 deletions components/lifesensor_common/include/macro/queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#ifndef __MACRO_QUEUE__
#define __MACRO_QUEUE__

#include <freertos/queue.h>


/**
* struct lifesensor_queue_t - generic queue struct
* @queue: Holds the FreeRTOS queue.
* @handle: Provides a reference to the queue after initialization.
* @buffer: Points to the subsequent queue buffer.
*
* This struct serves as an abstraction for operating with FreeRTOS queues such
* that it includes necessary fields for managing a queues data. It is intended
* to be used with the LIFESENSOR_QUEUE() macro.
*/
typedef struct {
QueueHandle_t handle;
StaticQueue_t queue;
uint8_t buffer[];
} lifesensor_queue_t;


/**
* LIFESENSOR_QUEUE() - Generic queue struct declaration macro
* @type: The variable type the queue will hold.
* @item_count Provide how many items of `type` fit into the queue..
*
* The macro is used for easier queue struct allocation. The resulting
* queue struct should be initialized through the corresponding
* lifesensor_queue_init() function macro.
*
* NOTE: `queue` houses the actual queue struct of type `lifesensor_queue_t`.
* `lifesensor_queue_t`s buffer attribute of undefined length will
* point to the buffer declared here with size `buffersize`.
*
*/
#define LIFESENSOR_QUEUE(type, item_count) \
struct { \
lifesensor_queue_t queue; \
type buffer[item_count]; \
}


/**
* lifesensor_queue_init() - Initialize a queue generated with LIFESENSOR_QUEUE
* @anon_queue: Pass a pointer to an instacne created with LIFESENSOR_QUEUE.
*
* This is a wrapper for `xTaskCreateStatic()` which initializes several
* internal variables. It provides another layer of abstraction to not bother
* much with the FreeRTOS internals and hides redundant code.
*
* Please consult https://www.freertos.org/xTaskCreateStatic.html
*/
#define lifesensor_queue_init(anon_queue) \
{ \
(*anon_queue).queue.handle = xQueueCreateStatic( \
sizeof((*anon_queue).buffer) / sizeof((*anon_queue).buffer[0]), \
sizeof((*anon_queue).buffer[0]), \
(*anon_queue).queue.buffer, \
&(*anon_queue).queue.queue \
); \
}

#endif
72 changes: 72 additions & 0 deletions components/lifesensor_common/include/macro/task.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef __MACRO_TASK__
#define __MACRO_TASK__

#include <freertos/task.h>

#define MACRO_DEFAULT_STACK_SIZE 0x1000
/**
* struct lifesensor_task_t - generic task struct
* @tcb: Holds the FreeRTOS tcb.
* @handle: Provides a reference to the task.
* @stack: Stores the address of the tasks' stack.
*
* This struct serves as an abstraction for operating with FreeRTOS tasks such
* that it includes necessary fields for managing a tasks data. It is intended
* to be used together with the LIFESENSOR_TASK() macro.
*/
typedef struct {
TaskHandle_t handle;
StaticTask_t tcb;
StackType_t stack[];
} lifesensor_task_t;


/**
* LIFESENSOR_TASK() - Generic task struct declaration macro
* @stacksize: Determines the stack depth used.
*
* The macro is used for easier task struct allocation. The resulting
* task struct should be initialized through the corresponding
* `lifesensor_task_init()` function macro.
*
* NOTE: `task` houses the actual task struct of type `lifesensor_task_t`.
* `lifesensor_task_t`s stack attribute of undefined length will
* point to the stack declared here with size `stacksize`.
*
*/
#define LIFESENSOR_TASK(stacksize) \
struct { \
lifesensor_task_t task; \
StackType_t stack[stacksize]; \
}


/**
* lifesensor_task_init() - Initialize a task generated with LIFESENSOR_TASK
* @anon_task: Pass a pointer to instance created with LIFESENSOR_TASK.
* @name: Name the task to recognize it later.
* @func: Provide a function pointer to execute in task.
* @args: Function arguments that will be fed to `func`.
* @prio: Set the desired task priority.
*
* This is a wrapper for `xTaskCreateStatic()` which initializes several
* internal variables. It provides another layer of abstraction to not bother
* much with the FreeRTOS internals and hides redundant code.
*
* Please consult https://www.freertos.org/xTaskCreateStatic.html
*/

#define lifesensor_task_init(anon_task, name, func, args, prio) \
{ \
(*anon_task).task.handle = xTaskCreateStatic( \
func, \
name, \
sizeof((*anon_task).stack) / sizeof((*anon_task).stack[0]), \
args, \
prio, \
(*anon_task).stack, \
(StaticTask_t*)(&(*anon_task).task.tcb) \
); \
}

#endif
3 changes: 2 additions & 1 deletion components/spo2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ idf_component_register(
include
REQUIRES
ulp_adc
lifesensor_common
)

# COMPONENT COMPILE FLAGS
Expand All @@ -18,4 +19,4 @@ target_compile_options(${COMPONENT_LIB} PRIVATE
# src/counter.c
# PROPERTIES COMPILE_FLAGS
# -Wno-unused-variable
#)
#)
59 changes: 13 additions & 46 deletions components/spo2/include/spo2.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@
#include <freertos/queue.h>

#include "spo2_driver.h"

#define SPO2_TASK_NAME "SpO2"
#define SPO2_TASK_STACK_SIZE 0x1000
#define SPO2_QUEUE_LENGTH 16
#define SPO2_QUEUE_ITEM_SIZE sizeof(_spo2_adc_sample)
#define SPO2_QUEUE_BUFFER_SIZE (SPO2_QUEUE_ITEM_SIZE * SPO2_QUEUE_LENGTH)
#include "macro/task.h"
#include "macro/queue.h"


/**
Expand All @@ -32,56 +28,27 @@ typedef struct {
int32_t red_ac;
int32_t ird_acdc;
int32_t red_acdc;
} _spo2_input_sample;

} spo2_input_sample_t;

/**
* struct _spo2_task - life-sensor task struct
* @tcb: task related data
* @handle: a handle to reference the task
* @stack: the address of the tasks' stack
*
* This struct serves as a shortcut for operating with FreeRTOS tasks such
* that it includes necessary fields for managing threads.
*/
typedef struct {
const char *name;
StaticTask_t tcb;
TaskHandle_t handle;
StackType_t *stack;
UBaseType_t priority;
} _spo2_task;

/**
* struct _spo2_queue - life-sensor queue struct
* @length: task related data
* @item_size: size of a single item
* @buffer: buffer to store the queues data
* @queue: pointer to the queues data structure
* @handle: a handle to reference the queue
* spo2_t - type deffinition of the spo2 unit
*
* This struct serves as a shortcut for operating with FreeRTOS queues such
* that it includes necessary fields for managing queues.
* @adc_queue: Receives ulp adc measurements.
* @adc_task: Processes adc input data from adc_queue.
*/
typedef struct {
UBaseType_t length;
UBaseType_t item_size;
uint8_t *buffer;
StaticQueue_t queue;
QueueHandle_t handle;
} _spo2_queue;
LIFESENSOR_QUEUE(spo2_adc_sample_t, 16) adc_queue;
LIFESENSOR_TASK(4096) adc_task;
} spo2_t;


/**
* spo2_init() - SpO2 (Pulsoxy) meassurement device interface initialization
* @spo2_task: task configuration
* @spo2_queue: queue configuration
* spo2_init() - spo2 initialization
* @spo2: The only parameter necessary is the unit itself.
*
* spo2_init() initializes peripherals (4xADC, 1xPWM, 2xGPIO) that is necessary
* to operate together with the pulsoxy board which does preprocessing of input
* data. After initialization a thread is started which periodically reads in
* input data.
* The function initializes queues and tasks of the spo2 unit.
*/
void spo2_init(_spo2_task *spo2_task, _spo2_queue *spo2_queue);
void lifesensor_spo2_init(spo2_t *spo2, const char *name);

#endif
4 changes: 2 additions & 2 deletions components/spo2/include/spo2_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ typedef struct __attribute__((packed)) {
uint32_t ird_dc;
uint32_t red_ac;
uint32_t ird_ac;
} _spo2_adc_sample;
} spo2_adc_sample_t;


/**
Expand All @@ -61,7 +61,7 @@ void spo2_init_peripherals(void);
* Read all ADC values that are necessary to perform calculations and save
* each of it to data. The data is an average of SPO2_ADC_ROUNDS measurements.
*/
void spo2_read_adc(_spo2_adc_sample *sample);
void spo2_read_adc(spo2_adc_sample_t *sample);

#endif

2 changes: 1 addition & 1 deletion components/spo2/include/spo2_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* This function applies digital filters to the values from `adc_sample` while
* additionally using the old values from the previous filtered `sample`.
*/
void spo2_filter(_spo2_input_sample *sample, _spo2_adc_sample *adc_sample);
void spo2_filter(spo2_input_sample_t *sample, spo2_adc_sample_t *adc_sample);


#endif
Expand Down
38 changes: 14 additions & 24 deletions components/spo2/src/spo2.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "spo2.h"
#include "spo2_driver.h"
#include "spo2_filter.h"
#include "macro/queue.h"


/**
Expand All @@ -22,46 +23,36 @@ static void spo2_runner(void *pvParameters);


void
spo2_init
(_spo2_task *spo2_task, _spo2_queue *spo2_queue)
lifesensor_spo2_init
(spo2_t *spo2, const char *name)
{
spo2_init_peripherals();

spo2_queue->handle = xQueueCreateStatic(
spo2_queue->length,
spo2_queue->item_size,
spo2_queue->buffer,
&spo2_queue->queue
);

spo2_task->handle = xTaskCreateStatic(
lifesensor_queue_init(&spo2->adc_queue);
lifesensor_task_init(
&spo2->adc_task,
name,
spo2_runner,
spo2_task->name,
SPO2_TASK_STACK_SIZE,
(void*)spo2_queue,
spo2_task->priority,
spo2_task->stack,
&spo2_task->tcb
&spo2->adc_queue.queue,
tskIDLE_PRIORITY
);
}


static
void
spo2_runner
(void *pvParameters)
(void *args)
{
static _spo2_input_sample sample = {0};
static _spo2_adc_sample adc_sample;
_spo2_queue *spo2_queue = (_spo2_queue*)pvParameters;
static spo2_input_sample_t sample = {0};
static spo2_adc_sample_t adc_sample;
lifesensor_queue_t *spo2_queue = (lifesensor_queue_t*)args;

for(;;)
{
xQueueReceive(&spo2_queue->queue, &adc_sample, portMAX_DELAY);
spo2_filter(&sample, &adc_sample);

ESP_LOGD(
SPO2_TASK_NAME,
"SpO2",
"RED-DC=%-4d IRD-DC=%-4d RED-AC=%-4d IRD-AC=%-4d"
" RED-ACDC=%-4d IRD-ACDC=%-4d",
sample.red_dc,
Expand All @@ -73,4 +64,3 @@ spo2_runner
);
}
}

Loading