Compare commits
4 Commits
111188ddb3
...
ba9342e249
Author | SHA1 | Date | |
---|---|---|---|
ba9342e249 | |||
1c51fc9710 | |||
90aac63257 | |||
15c4486967 |
@ -130,7 +130,7 @@ using a magnetic 4 pin plug.
|
|||||||
* Design and test the :
|
* Design and test the :
|
||||||
* [X] vibration motor circuit
|
* [X] vibration motor circuit
|
||||||
* [X] Draw the schematic, the first revision of the schematic is available [here](design/Kicad/W800_Smart_Watch/W800_Smart_Watch.pdf).
|
* [X] Draw the schematic, the first revision of the schematic is available [here](design/Kicad/W800_Smart_Watch/W800_Smart_Watch.pdf).
|
||||||
* [X] Design the PCB (routing, placement etc..) on a 2 layer PCB (might need 4 though) - In progress.
|
* [X] Design the PCB (routing, placement etc..) on a 2 layer PCB - done.
|
||||||
|
|
||||||
## Achieved power consumption recap:
|
## Achieved power consumption recap:
|
||||||
(Need to work on sleep current :-( )
|
(Need to work on sleep current :-( )
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "wm_gpio.h"
|
#include "wm_gpio.h"
|
||||||
|
#include "wm_osal.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "app_log.h"
|
#include "app_log.h"
|
||||||
#include "CST816D.h"
|
#include "CST816D.h"
|
||||||
@ -26,19 +27,19 @@ bool CST816D_read_touch_event(CST816D_Touch_Data_t * const touch_data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CST816D_set_power_mode(void)
|
void CST816D_hardware_reset(void)
|
||||||
{
|
{
|
||||||
tls_gpio_cfg(WM_IO_PA_00, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(LCD_TOUCH_PANEL_RESET, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
|
||||||
tls_gpio_write(WM_IO_PA_00, 0);
|
tls_gpio_write(LCD_TOUCH_PANEL_RESET, 0);
|
||||||
tls_os_time_delay(pdMS_TO_TICKS(5));
|
tls_os_time_delay(pdMS_TO_TICKS(5));
|
||||||
tls_gpio_write(WM_IO_PA_00, 1);
|
tls_gpio_write(LCD_TOUCH_PANEL_RESET, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CST816D_sleep(void)
|
||||||
|
{
|
||||||
|
CST816D_hardware_reset();
|
||||||
tls_os_time_delay(pdMS_TO_TICKS(50));
|
tls_os_time_delay(pdMS_TO_TICKS(50));
|
||||||
|
|
||||||
uint8_t data;
|
return i2c_write_reg(CST816D_I2C_ADDR, 0xA5, 0x03);
|
||||||
|
|
||||||
i2c_read_reg(CST816D_I2C_ADDR, 0xA5, &data);
|
|
||||||
|
|
||||||
i2c_write_reg(CST816D_I2C_ADDR, 0xA5, 0x03);
|
|
||||||
APP_LOG_DEBUG("CST 0xA5 : %u", data);
|
|
||||||
}
|
}
|
||||||
|
@ -57,10 +57,18 @@ typedef struct CST816D_Touch_Data
|
|||||||
bool CST816D_read_touch_event(CST816D_Touch_Data_t * const touch_data);
|
bool CST816D_read_touch_event(CST816D_Touch_Data_t * const touch_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Issues a hardware reset of the touch panel.
|
* @brief Issues a physical hardware reset of the touch panel IC using the reset pin.
|
||||||
*/
|
*/
|
||||||
void CST816D_hardware_reset(void);
|
void CST816D_hardware_reset(void);
|
||||||
|
|
||||||
bool CST816D_set_power_mode(void);
|
/**
|
||||||
|
* @brief Sets the touch panel in sleep mode.
|
||||||
|
* A call to this function does not seem to have any effect on power consumption even though the touch IC
|
||||||
|
* acknowledges the command ... strange !
|
||||||
|
*
|
||||||
|
* @return true if the IC acknowledged the command
|
||||||
|
* @return false otherwise
|
||||||
|
*/
|
||||||
|
bool CST816D_sleep(void);
|
||||||
|
|
||||||
#endif //CST816D_H
|
#endif //CST816D_H
|
@ -16,7 +16,7 @@
|
|||||||
void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency);
|
void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief Writes multiple bytes in one I2C transfer to the slave device.
|
||||||
*
|
*
|
||||||
* @param address the 7 bit address of the slave device
|
* @param address the 7 bit address of the slave device
|
||||||
* @param reg the address of the register from where the write will start (the device should have write with autoincrement register functionality)
|
* @param reg the address of the register from where the write will start (the device should have write with autoincrement register functionality)
|
||||||
@ -28,7 +28,7 @@ void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequen
|
|||||||
bool i2c_write(uint8_t address, uint8_t reg, const uint8_t * const data, size_t length);
|
bool i2c_write(uint8_t address, uint8_t reg, const uint8_t * const data, size_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes the given data to the provided register of the slave device.
|
* @brief Writes the given byte to the provided register of the slave device.
|
||||||
*
|
*
|
||||||
* @param address the 7 bit address of the slave device
|
* @param address the 7 bit address of the slave device
|
||||||
* @param reg the address of the register
|
* @param reg the address of the register
|
||||||
@ -39,7 +39,7 @@ bool i2c_write(uint8_t address, uint8_t reg, const uint8_t * const data, size_t
|
|||||||
bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data);
|
bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads multiple data in one I2C transaction from the slave device.
|
* @brief Reads multiple data in one I2C transfer from the slave device.
|
||||||
*
|
*
|
||||||
* @param address the 7 bit address of the slave device
|
* @param address the 7 bit address of the slave device
|
||||||
* @param reg the address of the register from where the read will start (the device should have read with autoincrement register functionality)
|
* @param reg the address of the register from where the read will start (the device should have read with autoincrement register functionality)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "wm_pwm.h"
|
#include "wm_pwm.h"
|
||||||
|
|
||||||
|
|
||||||
static uint8_t _adc_offset = 0;
|
static int8_t _adc_offset = 0;
|
||||||
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
||||||
|
|
||||||
static void vibration_motor_timer_irq_cb(void *p)
|
static void vibration_motor_timer_irq_cb(void *p)
|
||||||
@ -20,7 +20,7 @@ static void vibration_motor_timer_irq_cb(void *p)
|
|||||||
APP_LOG_DEBUG("Vibration stopped");
|
APP_LOG_DEBUG("Vibration stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_io_init(void)
|
static void watch_peripherals_io_init(void)
|
||||||
{
|
{
|
||||||
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
||||||
wm_adc_config(BATTERY_VOLTAGE_ADC_CHANNEL);
|
wm_adc_config(BATTERY_VOLTAGE_ADC_CHANNEL);
|
||||||
@ -28,11 +28,11 @@ void watch_peripherals_io_init(void)
|
|||||||
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 0);
|
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 0);
|
||||||
|
|
||||||
/* We initialize the output pin for the vibration motor enable pin */
|
/* We initialize the output pin for the vibration motor enable pin */
|
||||||
/*tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);*/
|
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_init(uint8_t adcOffset)
|
void watch_peripherals_init(int8_t adcOffset)
|
||||||
{
|
{
|
||||||
watch_peripherals_io_init();
|
watch_peripherals_io_init();
|
||||||
_adc_offset = adcOffset;
|
_adc_offset = adcOffset;
|
||||||
@ -56,12 +56,43 @@ void watch_peripherals_init(uint8_t adcOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t watch_peripherals_get_battery_voltage(void)
|
uint16_t watch_peripherals_get_battery_voltage(Battery_Unit_e unit)
|
||||||
{
|
{
|
||||||
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 1);
|
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 1);
|
||||||
int batteryVoltage = adc_get_inputVolt(BATTERY_VOLTAGE_ADC_CHANNEL, 1, 1) * 2 + _adc_offset;
|
int batteryVoltage = adc_get_inputVolt(BATTERY_VOLTAGE_ADC_CHANNEL, 1, 1) * 2 + _adc_offset;
|
||||||
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 0);
|
tls_gpio_write(BATTERY_VOLTAGE_DIVIDER_ENABLE, 0);
|
||||||
return batteryVoltage < 0 ? 0 : batteryVoltage;
|
|
||||||
|
switch (unit)
|
||||||
|
{
|
||||||
|
case Battery_Unit_mV:
|
||||||
|
return batteryVoltage < 0 ? 0 : batteryVoltage;
|
||||||
|
break;
|
||||||
|
case Battery_Unit_percent:
|
||||||
|
return battery_voltage_to_percentage(batteryVoltage < 0 ? 0 : batteryVoltage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV)
|
||||||
|
{
|
||||||
|
const uint16_t BATTERY_VOLTAGE_MV_TABLE[20] =
|
||||||
|
{
|
||||||
|
3270, 3610, 3690, 3710, 3730, 3750, 3770, 3790, 3800, 3820,
|
||||||
|
3840, 3850, 3870, 3910, 3950, 3980, 4020, 4080, 4110, 4150,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t i = 19;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(voltage_in_mV > BATTERY_VOLTAGE_MV_TABLE[i])
|
||||||
|
break;
|
||||||
|
}while(i-- > 0);
|
||||||
|
|
||||||
|
return (i+1) * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
||||||
|
@ -6,14 +6,45 @@
|
|||||||
#define WATCH_PERIPHERALS_H
|
#define WATCH_PERIPHERALS_H
|
||||||
#include "wm_type_def.h"
|
#include "wm_type_def.h"
|
||||||
|
|
||||||
void watch_peripherals_io_init(void);
|
typedef enum Battery_Unit
|
||||||
|
{
|
||||||
|
Battery_Unit_mV = 0,
|
||||||
|
Battery_Unit_percent
|
||||||
|
} Battery_Unit_e;
|
||||||
|
|
||||||
void watch_peripherals_init(uint8_t adcOffset);
|
/**
|
||||||
|
* @brief Inits the watch peripherals driver.
|
||||||
|
* This must be called before using the API.
|
||||||
|
*
|
||||||
|
* @param adcOffset an offset in mV to apply to the battery voltage reading.
|
||||||
|
*/
|
||||||
|
void watch_peripherals_init(int8_t adcOffset);
|
||||||
|
|
||||||
uint16_t watch_peripherals_get_battery_voltage(void);
|
/**
|
||||||
|
* @brief Reads and returns the current battery voltage in mV or it's corresponding capacity in percentage.
|
||||||
|
* This function takes into account the adcOffset parameter provided in the @ref watch_peripherals_init
|
||||||
|
* function.
|
||||||
|
* /!\ The capacity in % returned is for a single cell battery LiPo only.
|
||||||
|
*
|
||||||
|
* @param unit the unit of the data to be returned : mV or corresponding capacity in percentage
|
||||||
|
* @return uint16_t the voltage in mV or the battery left capacity in %
|
||||||
|
*/
|
||||||
|
uint16_t watch_peripherals_get_battery_voltage(Battery_Unit_e unit);
|
||||||
|
|
||||||
uint8_t watch_peripherals_battery_voltage_to_level(uint16_t voltage);
|
/**
|
||||||
|
* @brief Converts the given battery voltage to the corresponding battery capacity for a single cell LiPo only (4.2V to 3.2V)
|
||||||
|
*
|
||||||
|
* @param voltage_in_mV the voltage to convert in mV
|
||||||
|
* @return uint8_t the corresponding capacity in %
|
||||||
|
*/
|
||||||
|
uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Triggers the vibration motor to vibrate at the provided strength for the set duration in ms.
|
||||||
|
*
|
||||||
|
* @param strength the vibration strength from 0 to 255
|
||||||
|
* @param durationMs the vibration duration in ms
|
||||||
|
*/
|
||||||
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs);
|
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs);
|
||||||
|
|
||||||
#endif //WATCH_PERIPHERALS_H
|
#endif //WATCH_PERIPHERALS_H
|
@ -148,6 +148,9 @@ void gfx_task(void *param)
|
|||||||
|
|
||||||
lv_scr_load(watchFace.display);
|
lv_scr_load(watchFace.display);
|
||||||
|
|
||||||
|
/* Let's init the watch peripherals driver (vibration motor + battery voltage sense) */
|
||||||
|
watch_peripherals_init(27);
|
||||||
|
|
||||||
/* Let's init the I2C interface */
|
/* Let's init the I2C interface */
|
||||||
i2c_init(I2C_SDA, I2C_SCL, 100000);
|
i2c_init(I2C_SDA, I2C_SCL, 100000);
|
||||||
|
|
||||||
@ -251,8 +254,6 @@ void gfx_task(void *param)
|
|||||||
else
|
else
|
||||||
APP_LOG_INFO("BMA456 set pin conf failed");
|
APP_LOG_INFO("BMA456 set pin conf failed");
|
||||||
|
|
||||||
watch_peripherals_init(27);
|
|
||||||
|
|
||||||
/* Once we are done with the initializing steps we
|
/* Once we are done with the initializing steps we
|
||||||
don't forget to turn the backlight on ! */
|
don't forget to turn the backlight on ! */
|
||||||
setBrightness(persistency_get_settings()->display.brightness);
|
setBrightness(persistency_get_settings()->display.brightness);
|
||||||
@ -260,6 +261,7 @@ void gfx_task(void *param)
|
|||||||
extern LCDConfig_t LCDConfig;
|
extern LCDConfig_t LCDConfig;
|
||||||
float temperature = 0;
|
float temperature = 0;
|
||||||
float pressure = 0;
|
float pressure = 0;
|
||||||
|
uint16_t battery_voltage = 0;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@ -296,10 +298,11 @@ void gfx_task(void *param)
|
|||||||
{
|
{
|
||||||
pressure = BMP280_get_pressure(&temperature);
|
pressure = BMP280_get_pressure(&temperature);
|
||||||
BMP280_trigger_measurement();
|
BMP280_trigger_measurement();
|
||||||
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, bat : %u mV",
|
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, bat : %u mV <-> %u %%",
|
||||||
temperature,
|
temperature,
|
||||||
pressure/100,
|
pressure/100,
|
||||||
watch_peripherals_get_battery_voltage());
|
battery_voltage = watch_peripherals_get_battery_voltage(Battery_Unit_mV),
|
||||||
|
battery_voltage_to_percentage(battery_voltage));
|
||||||
aliveCounter = 0;
|
aliveCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +315,10 @@ void gfx_task(void *param)
|
|||||||
//lcd_on(&LCDConfig, false);
|
//lcd_on(&LCDConfig, false);
|
||||||
lcd_sleep(&LCDConfig, true);
|
lcd_sleep(&LCDConfig, true);
|
||||||
QMC5883L_set_power_mode(Standby);
|
QMC5883L_set_power_mode(Standby);
|
||||||
CST816D_set_power_mode();
|
if(CST816D_set_power_mode())
|
||||||
|
APP_LOG_DEBUG("CST816D Sleep cmd ok");
|
||||||
|
else
|
||||||
|
APP_LOG_DEBUG("CST816D Sleep cmd fail");
|
||||||
// Let's sleep
|
// Let's sleep
|
||||||
tls_pmu_sleep_start();
|
tls_pmu_sleep_start();
|
||||||
// On wake up, we force the watch face to sync up with the rtc /!\ RTC update delay WTF ?
|
// On wake up, we force the watch face to sync up with the rtc /!\ RTC update delay WTF ?
|
||||||
@ -334,8 +340,7 @@ void gfx_task(void *param)
|
|||||||
{
|
{
|
||||||
tls_sys_clk_set(CPU_CLK_40M);
|
tls_sys_clk_set(CPU_CLK_40M);
|
||||||
APP_LOG_DEBUG("CPU 40Mhz");
|
APP_LOG_DEBUG("CPU 40Mhz");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -344,7 +349,6 @@ void gfx_task(void *param)
|
|||||||
tls_sys_clk_set(CPU_CLK_160M);
|
tls_sys_clk_set(CPU_CLK_160M);
|
||||||
APP_LOG_DEBUG("CPU 160Mhz");
|
APP_LOG_DEBUG("CPU 160Mhz");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -115,6 +115,11 @@ typedef unsigned long ULONG;
|
|||||||
#endif
|
#endif
|
||||||
typedef unsigned char u8_t;
|
typedef unsigned char u8_t;
|
||||||
|
|
||||||
|
#ifdef int8_t
|
||||||
|
#undef int8_t
|
||||||
|
#endif
|
||||||
|
typedef signed char int8_t;
|
||||||
|
|
||||||
#ifdef uint8_t
|
#ifdef uint8_t
|
||||||
#undef uint8_t
|
#undef uint8_t
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user