Skip to content
Snippets Groups Projects
Commit 01c6b903 authored by Adrian's avatar Adrian Committed by rahix
Browse files

feat(modules): Add light-sensor module

parent 37f1d36c
No related branches found
No related tags found
No related merge requests found
......@@ -35,6 +35,9 @@ typedef unsigned int size_t;
#define API_STREAM_READ 0x6
#define API_INTERRUPT_ENABLE 0x7
#define API_INTERRUPT_DISABLE 0x8
#define API_LIGHT_SENSOR_RUN 0x9
#define API_LIGHT_SENSOR_GET 0xa
#define API_LIGHT_SENSOR_STOP 0xb
#define API_DISP_OPEN 0x10
#define API_DISP_CLOSE 0x11
......@@ -398,4 +401,42 @@ API(API_DISP_CIRC,
uint16_t pixelsize)
);
/**
* Start continuous readout of the light sensor. Will read light level
* at preconfigured interval and make it available via `epic_light_sensor_get()`.
*
* If the continuous readout was already running, this function will silently pass.
*
*
* :return: `0` if the start was successful or a negative error value
* if an error occured. Possible errors:
*
* - ``-EBUSY``: The timer could not be scheduled.
*/
API(API_LIGHT_SENSOR_RUN, int epic_light_sensor_run());
/**
* Get the last light level measured by the continuous readout.
*
* :param uint16_t* value: where the last light level should be written.
* :return: `0` if the readout was successful or a negative error
* value. Possible errors:
*
* - ``-ENODATA``: Continuous readout not currently running.
*/
API(API_LIGHT_SENSOR_GET, int epic_light_sensor_get(uint16_t* value));
/**
* Stop continuous readout of the light sensor.
*
* If the continuous readout wasn't running, this function will silently pass.
*
* :return: `0` if the stop was sucessful or a negative error value
* if an error occured. Possible errors:
*
* - ``-EBUSY``: The timer stop could not be scheduled.
*/
API(API_LIGHT_SENSOR_STOP, int epic_light_sensor_stop());
#endif /* _EPICARDIUM_H */
#include "FreeRTOS.h"
#include "timers.h"
#include "led.h"
#include "mxc_config.h"
#include "adc.h"
#include "gpio.h"
#include <errno.h>
#define READ_FREQ pdMS_TO_TICKS(100)
static uint16_t last_value;
static TimerHandle_t poll_timer;
static StaticTimer_t poll_timer_buffer;
int epic_light_sensor_init()
{
const sys_cfg_adc_t sys_adc_cfg =
NULL; /* No system specific configuration needed. */
if (ADC_Init(0x9, &sys_adc_cfg) != E_NO_ERROR) {
return -EINVAL;
}
GPIO_Config(&gpio_cfg_adc7);
return 0;
}
void readAdcCallback()
{
ADC_StartConvert(ADC_CH_7, 0, 0);
ADC_GetData(&last_value);
}
int epic_light_sensor_run()
{
epic_light_sensor_init();
if (!poll_timer) {
poll_timer = xTimerCreateStatic(
"light_sensor_adc",
READ_FREQ,
pdTRUE,
NULL,
readAdcCallback,
&poll_timer_buffer
);
// since &poll_timer_buffer is not NULL, xTimerCreateStatic should allways succeed, so
// we don't need to check for poll_timer being NULL.
}
if (xTimerIsTimerActive(poll_timer) == pdFALSE) {
if (xTimerStart(poll_timer, 0) != pdPASS) {
return -EBUSY;
}
}
return 0;
}
int epic_light_sensor_stop()
{
if (!poll_timer || xTimerIsTimerActive(poll_timer) == pdFALSE) {
// timer wasn't running (or never started), just silently pass
return 0;
}
if (xTimerStop(poll_timer, 0) != pdPASS) {
return -EBUSY;
}
return 0;
}
int epic_light_sensor_get(uint16_t *value)
{
if (!poll_timer || !xTimerIsTimerActive(poll_timer)) {
return -ENODATA;
}
*value = last_value;
return 0;
}
......@@ -7,4 +7,5 @@ module_sources = files(
'serial.c',
'stream.c',
'vibra.c',
'light_sensor.c',
)
......@@ -6,6 +6,7 @@ modsrc = files(
'modules/sys_display.c',
'modules/utime.c',
'modules/vibra.c',
'modules/light_sensor.c'
)
#################################
......
#include "py/obj.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "epicardium.h"
STATIC mp_obj_t mp_light_sensor_start()
{
int status = epic_light_sensor_run();
if (status == -EBUSY) {
mp_raise_msg(
&mp_type_RuntimeError, "timer could not be scheduled"
);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(light_sensor_start_obj, mp_light_sensor_start);
STATIC mp_obj_t mp_light_sensor_get_reading()
{
uint16_t last;
int status = epic_light_sensor_get(&last);
if (status == -ENODATA) {
mp_raise_ValueError("sensor not running");
return mp_const_none;
}
return mp_obj_new_int_from_uint(last);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(
light_sensor_get_obj, mp_light_sensor_get_reading
);
STATIC mp_obj_t mp_light_sensor_stop()
{
int status = epic_light_sensor_stop();
if (status == -EBUSY) {
mp_raise_msg(
&mp_type_RuntimeError, "timer could not be stopped"
);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(light_sensor_stop_obj, mp_light_sensor_stop);
STATIC const mp_rom_map_elem_t light_sensor_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_light_sensor) },
{ MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&light_sensor_start_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&light_sensor_stop_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_reading), MP_ROM_PTR(&light_sensor_get_obj) }
};
STATIC MP_DEFINE_CONST_DICT(
light_sensor_module_globals, light_sensor_module_globals_table
);
const mp_obj_module_t light_sensor_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&light_sensor_module_globals,
};
/* clang-format off */
MP_REGISTER_MODULE(MP_QSTR_light_sensor, light_sensor_module, MODULE_LIGHT_SENSOR_ENABLED);
......@@ -40,3 +40,9 @@ Q(line)
Q(rect)
Q(circ)
Q(clear)
/* ambient */
Q(light_sensor)
Q(start)
Q(get_reading)
Q(stop)
......@@ -42,6 +42,7 @@
#define MODULE_VIBRA_ENABLED (1)
#define MODULE_INTERRUPT_ENABLED (1)
#define MODULE_DISPLAY_ENABLED (1)
#define MODULE_LIGHT_SENSOR_ENABLED (1)
/*
* This port is intended to be 32-bit, but unfortunately, int32_t for
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment