Big refactoring and cleanup by removing sensors initialization code from the gfx_task.c file and moving it to the watch_peripherals.c source file. This is way more logical IMO. This change also allows to enable or disable the wrist tilt wakeup with a function call

This commit is contained in:
Th3maz1ng 2023-04-10 21:15:47 +02:00
parent b8a11a8a79
commit 92d3279eb9
2 changed files with 367 additions and 6 deletions

View File

@ -5,6 +5,10 @@
#include "wm_adc.h"
#include "wm_timer.h"
#include "wm_pwm.h"
#include "i2c.h"
#include "BMP280.h"
#include "FreeRTOS.h" // <---- Only needed for the pdMS_TO_TICKS macro, to be removed
#include "bma456w.h"
#define INTERRUPT_POLICY (0)
#define POLL_POLICY (1)
@ -21,6 +25,23 @@ static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
static BatteryControllerStatusChangeCb_t _BatteryControllerStatusChangeCb = NULL;
/* BMA456 strcture */
struct
{
uint8_t dev_addr;
struct bma4_dev bma;
struct bma4_accel_config accel_conf;
struct bma456w_wrist_wear_wakeup_params setting;
struct bma4_int_pin_config pin_config;
bool wrist_wakeup_enable;
bool step_counter_enable;
} _bma456 =
{
.dev_addr = BMA4_I2C_ADDR_SECONDARY,
.wrist_wakeup_enable = false,
};
static void vibration_motor_timer_irq_cb(void *p)
{
(void)p;
@ -29,7 +50,7 @@ static void vibration_motor_timer_irq_cb(void *p)
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
}
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY && HARDWARE_PLATFORM == SMART_WATCH_PCB
static uint8_t _battery_status_timer_id = WM_TIMER_ID_INVALID;
static void battery_status_timer_irq_cb(void *p)
@ -58,7 +79,7 @@ static void battery_status_timer_irq_cb(void *p)
if(_BatteryControllerStatusChangeCb) _BatteryControllerStatusChangeCb(old_battery_status, _battery_fsm);
}
}
#elif BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
#elif BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY && HARDWARE_PLATFORM == SMART_WATCH_PCB
static void battery_controller_irq_cb(void *p)
{
enum tls_io_name gpio_pin = (enum tls_io_name)p;
@ -122,7 +143,7 @@ static void watch_peripherals_io_init(void)
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY && HARDWARE_PLATFORM == SMART_WATCH_PCB
tls_gpio_isr_register(BATTERY_CONTROLLER_CHARGED_STATUS, &(battery_controller_irq_cb), (int*) BATTERY_CONTROLLER_CHARGED_STATUS);
tls_gpio_irq_enable(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE); // Enabled when level is changing edge
@ -171,7 +192,7 @@ void watch_peripherals_init(int8_t adcOffset)
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
APP_LOG_ERROR("Failed to create vibration motor timer");
}
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY && HARDWARE_PLATFORM == SMART_WATCH_PCB
if(WM_TIMER_ID_INVALID == _battery_status_timer_id)
{
struct tls_timer_cfg battery_status_timer_cfg =
@ -190,6 +211,9 @@ void watch_peripherals_init(int8_t adcOffset)
tls_timer_start(_battery_status_timer_id);
}
#endif
/* Let's init the I2C interface */
i2c_init(I2C_SDA, I2C_SCL, I2C_CLOCK_SPEED);
}
void watch_peripherals_register_battery_controller_status_change_cb(BatteryControllerStatusChangeCb_t BatteryControllerStatusChangeCb)
@ -264,3 +288,309 @@ void watch_peripherals_set_orientation(LCDOrientation_e orientation)
extern LCDConfig_t LCDConfig;
lcd_orientation(&LCDConfig, orientation);
}
bool watch_peripherals_magnetometer_init(void)
{
/* Init the magnetometer */
if(!QMC5883L_init())
{
APP_LOG_ERROR("Failed to init QMC5883L");
return false;
}
else
APP_LOG_INFO("Inited QMC5883L");
/* Needed but UGLY */
tls_os_time_delay(2);
if(!QMC5883L_set_power_mode(QMC5883L_Mode_Control_Continuous))
{
APP_LOG_ERROR("Failed to set QMC5883L mode");
return false;
}
else
APP_LOG_INFO("QMC5883L Mode set");
/* Needed but UGLY */
tls_os_time_delay(2);
if(!QMC5883L_configure_1(ODR_10HZ, FS_2G, OSR_512))
{
APP_LOG_ERROR("Failed to configure 1 QMC5883L");
return false;
}
else
APP_LOG_INFO("QMC5883L configured");
return true;
}
void watch_peripherals_magnetometer_calibration_data_set(
int16_t x_min, int16_t x_max,
int16_t y_min, int16_t y_max,
int16_t z_min, int16_t z_max, float temperature_offset
)
{
QMC5883L_set_calibration_data(x_min, x_max, y_min, y_max, z_min, z_max, temperature_offset);
}
uint16_t watch_peripherals_magnetometer_azimuth_read(bool *is_data_available)
{
bool data_ready = QMC5883L_is_data_available();
if(is_data_available) *is_data_available = data_ready;
if(!data_ready) return 0;
QMC5883L_MData_calibrated_t MData = QMC5883L_get_MFields_calibrated();
return QMC5883L_get_azimuth(MData);
}
QMC5883L_MData_t watch_peripherals_magnetometer_raw_data_read(void)
{
return QMC5883L_get_MFields_raw();
}
bool watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_e mode_control)
{
return QMC5883L_set_power_mode(mode_control);
}
bool watch_peripherals_pressure_sensor_init(void)
{
/* Init the BMP280 */
if(!BMP280_init())
{
APP_LOG_ERROR("Failed to init BMP280");
return false;
}
else
APP_LOG_INFO("Inited BMP280");
if(!BMP280_configure(BMP280_Forced, BMP280_Oversampling_x16, BMP280_Oversampling_x16, BMP280_Filter_x16, BMP280_Standby_4000MS))
{
APP_LOG_ERROR("Failed to configure BMP280");
return false;
}
else
APP_LOG_INFO("BMP280 configured");
return true;
}
float watch_peripherals_pressure_sensor_get_pressure(float * const temperature)
{
BMP280_trigger_measurement();
while(BMP280_is_measuring());
return BMP280_get_pressure(temperature);
}
static BMA4_INTF_RET_TYPE _bma4_i2c_read(uint8_t reg_addr, uint8_t *read_data, uint32_t len, void *intf_ptr)
{
uint8_t dev_address = *(uint8_t*)intf_ptr;
return !i2c_read(dev_address, reg_addr, read_data, len);
}
static BMA4_INTF_RET_TYPE _bma4_i2c_write(uint8_t reg_addr, const uint8_t *read_data, uint32_t len, void *intf_ptr)
{
uint8_t dev_address = *(uint8_t*)intf_ptr;
return !i2c_write(dev_address, reg_addr, read_data, len);
}
// TODO: Rework the delay_us function to rather use a timer and have real µs resolution and not ms ...
static void _bma4_delay_us(uint32_t period, void *intf_ptr)
{
(void) intf_ptr;
if(period < 1000)
tls_os_time_delay(1);
else
tls_os_time_delay(pdMS_TO_TICKS(period / 1000));
}
bool watch_peripherals_accelerometer_init(void)
{
/* Init the BMA456 */
_bma456.bma.intf = BMA4_I2C_INTF;
_bma456.bma.intf_ptr = &_bma456.dev_addr;
_bma456.bma.bus_read = &(_bma4_i2c_read);
_bma456.bma.bus_write = &(_bma4_i2c_write);
_bma456.bma.variant = BMA45X_VARIANT;
_bma456.bma.delay_us = &(_bma4_delay_us);
_bma456.bma.read_write_len = 46;
_bma456.bma.perf_mode_status = BMA4_DISABLE;
if(bma456w_init(&_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 init");
else
{
APP_LOG_ERROR("Failed to init BMA456");
return false;
}
if(bma4_soft_reset(&_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 soft reset");
else
{
APP_LOG_ERROR("Failed to soft reset BMA456");
return false;
}
tls_os_time_delay(2);
if(bma456w_write_config_file(&_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 config ok");
else
{
APP_LOG_ERROR("BMA456 config failed");
return false;
}
_bma456.accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
_bma456.accel_conf.range = BMA4_ACCEL_RANGE_2G;
_bma456.accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
_bma456.accel_conf.perf_mode = BMA4_CIC_AVG_MODE;
if(bma4_set_accel_config(&_bma456.accel_conf, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 accel conf ok");
else
{
APP_LOG_ERROR("BMA456 accel conf failed");
return false;
}
if(bma4_set_accel_enable(1, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 accel en ok");
else
{
APP_LOG_ERROR("BMA456 accel en failed");
return false;
}
return true;
}
bool watch_peripherals_accelerometer_wrist_wakeup_enable(bool enable)
{
if(_bma456.wrist_wakeup_enable == enable) return true;
_bma456.wrist_wakeup_enable = enable;
if(bma456w_feature_enable(BMA456W_WRIST_WEAR_WAKEUP, enable, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 feature enable ok");
else
{
APP_LOG_ERROR("BMA456 feature enable failed");
return false;
}
if(bma456w_get_wrist_wear_wakeup_param_config(&_bma456.setting, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 get wrist param ok");
else
{
APP_LOG_ERROR("BMA456 get wrist param failed");
return false;
}
APP_LOG_DEBUG("%d %d %d %d %d %d %d %d",
_bma456.setting.min_angle_focus,
_bma456.setting.min_angle_non_focus,
_bma456.setting.angle_landscape_right,
_bma456.setting.angle_landscape_left,
_bma456.setting.angle_portrait_up,
_bma456.setting.angle_portrait_down,
_bma456.setting.min_dur_moved,
_bma456.setting.min_dur_quite);
if(bma4_get_int_pin_config(&_bma456.pin_config, BMA4_INTR1_MAP, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 get pin conf ok");
else
{
APP_LOG_ERROR("BMA456 get pin conf failed");
return false;
}
if(bma456w_map_interrupt(BMA4_INTR1_MAP, BMA456W_WRIST_WEAR_WAKEUP_INT, enable, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 map int ok");
else
{
APP_LOG_ERROR("BMA456 map int failed");
return false;
}
_bma456.pin_config.edge_ctrl = BMA4_EDGE_TRIGGER;
_bma456.pin_config.output_en = BMA4_OUTPUT_ENABLE;
_bma456.pin_config.lvl = BMA4_ACTIVE_LOW;
_bma456.pin_config.od = BMA4_PUSH_PULL;
_bma456.pin_config.input_en = BMA4_INPUT_DISABLE;
if(bma4_set_int_pin_config(&_bma456.pin_config, BMA4_INTR1_MAP, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 set pin conf ok");
else
{
APP_LOG_ERROR("BMA456 set pin conf failed");
return false;
}
return true;
}
bool watch_peripherals_accelerometer_wrist_wakeup_interrupt(void)
{
uint16_t bma456_int_status;
uint8_t rslt = bma456w_read_int_status(&bma456_int_status, &_bma456.bma);
if(rslt != BMA4_OK)
{
APP_LOG_ERROR("Failed to read int status");
return false;
}
if((BMA4_OK == rslt) && (bma456_int_status & BMA456W_WRIST_WEAR_WAKEUP_INT))
return true;
return false;
}
bool watch_peripherals_accelerometer_step_counter_enable(bool enable)
{
if(_bma456.step_counter_enable == enable) return true;
_bma456.step_counter_enable = enable;
if(bma456w_feature_enable(BMA456W_STEP_CNTR, BMA4_ENABLE, &_bma456.bma) == BMA4_OK)
APP_LOG_INFO("BMA456 step cnter feature enable ok");
else
{
APP_LOG_ERROR("BMA456 step cnter feature enable failed");
return false;
}
return true;
}
bool watch_peripherals_accelerometer_step_count_read(uint32_t *step_count)
{
if(!step_count) return false;
if(bma456w_step_counter_output(step_count, &_bma456.bma) != BMA4_OK)
{
APP_LOG_ERROR("Failed to read step counts");
return false;
}
return true;
}
bool watch_peripherals_accelerometer_step_count_reset(void)
{
if(bma456w_reset_step_counter(&_bma456.bma) != BMA4_OK)
{
APP_LOG_ERROR("Failed to reset step counts");
return false;
}
return true;
}

View File

@ -6,6 +6,7 @@
#define WATCH_PERIPHERALS_H
#include "lcd.h"
#include "wm_type_def.h"
#include "QMC5883L.h"
typedef enum battery_unit
{
@ -32,8 +33,8 @@ typedef void (*BatteryControllerStatusChangeCb_t)(battery_controller_status_e ol
const char *battery_controller_status_2_str(battery_controller_status_e status);
/**
* @brief Inits the watch peripherals driver.
* This must be called before using the API.
* @brief Inits the watch peripherals drivers and sets battery sensing ADC offset.
* This must be called before using the watch peripherals API.
*
* @param adcOffset an offset in mV to apply to the battery voltage reading.
*/
@ -100,4 +101,34 @@ void watch_peripherals_set_brightness(uint8_t brightness);
*/
void watch_peripherals_set_orientation(LCDOrientation_e orientation);
bool watch_peripherals_magnetometer_init(void);
void watch_peripherals_magnetometer_calibration_data_set(
int16_t x_min, int16_t x_max,
int16_t y_min, int16_t y_max,
int16_t z_min, int16_t z_max, float temperature_offset
);
uint16_t watch_peripherals_magnetometer_azimuth_read(bool *is_data_available);
QMC5883L_MData_t watch_peripherals_magnetometer_raw_data_read(void);
bool watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_e mode_control);
bool watch_peripherals_pressure_sensor_init(void);
float watch_peripherals_pressure_sensor_get_pressure(float * const temperature);
bool watch_peripherals_accelerometer_init(void);
bool watch_peripherals_accelerometer_wrist_wakeup_enable(bool enable);
bool watch_peripherals_accelerometer_wrist_wakeup_interrupt(void);
bool watch_peripherals_accelerometer_step_counter_enable(bool enable);
bool watch_peripherals_accelerometer_step_count_read(uint32_t *step_count);
bool watch_peripherals_accelerometer_step_count_reset(void);
#endif //WATCH_PERIPHERALS_H