updated interface, added M5Stick (PLUS) support

This commit is contained in:
Lurkars 2020-12-12 14:26:08 +01:00
parent 559ed3762a
commit 0d3fd854f8
43 changed files with 2832 additions and 313 deletions

View File

@ -23,6 +23,8 @@ The following acronyms will be used in code and comments:
* Upload of own Exposure keys to proxy server
Additional features for full ENA device
#### Custom device
* RTC support with DS3231 (for correct system time)
* display support with SSD1306
* interface with a 7 button control (joystick up,down,left,right,enter,cancel,ok) to
@ -34,6 +36,15 @@ Additional features for full ENA device
* enter tan and uploading own exposure keys
* battery support with ESP32 dev-boards with integrated LiPo support
#### M5StickC and M5StickC PLUS
* RTC support
* PMU support
* display support
* interface with 2 buttons and accelometer control
* ok/cancel with button 1 and button 2 (depending on screen orientation)
* up, down, left, right with tilting device
* long press button 1 for changing character set on input
### Features in development
* 3d print case
@ -78,30 +89,46 @@ For base functionality just an ESP32 is required. DS3231 RTC, SSD1306 Display an
idf.py menuconfig
```
required
**required**
* enable bluetooth (BLE)
> Component config -> Bluetooth -> [*] Bluetooth
* add partition-table for storage (currently hardcoded name "ena")
> Partition Table -> Partition table -> (x) Custom partition table CSV
* mbedTLS enable HKDF
> Component config -> mbedTLS -> [*] HKDF algorithm (RFC 5869)
* flash size > 3.9GB
> Serial flasher config -> Flash size -> (x) 4MB
* choose interface device (custom, M5StickC or M5StickC PLUS)
> ENA Interface -> ENA Interface device
recommended
**recommended**
* BLE *Scan Duplicate* (By Device Address and Advertising Data)
> Component config -> Bluetooth -> Bluetooth controller -> Scan Duplicate Type -> (X) Scan Duplicate By Device Address And Advertising Data
debug options
**debug options**
* Log output set to Debug
* Exposure Notification API / Storage enable *Dump storage*
> Component config -> Log output -> Default log verbosity -> (X) Debug
* Exposure Notification API / Storage enable *Dump storage*
> Exposure Notification API -> Storage -> [X] Dump storage
#### Configure device manually!
Select required device drivers manually, because config get not applied in interface's CmakeLists.txt (I don't know why!):
> comment in/out line in *components/interface/CmakeLists.txt* with matching interface
### Build and Flash
May flash partition table:
```
idf.py partition_table-flash
idf.py partition_table-flash -b 1500000
```
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
idf.py -p PORT flash -b 1500000 monitor
```
(Replace PORT with the name of the serial port to use.)
@ -155,19 +182,43 @@ General module for set/get time from RTC.
### i2c-main
Just start I2C driver for display and RTC.
Just start I²C driver for display and RTC.
### interface-input-buttons
Interface with 7 button input
### interface-input-m5
Interface with input for M5StickC (PLUS) with 2 button input and accelometer as axis input
### rtc-ds3231
I2C driver for a DS3231 RTC, implementation of [rtc](#-rtc) module
I²C driver for a DS3231 RTC, implementation of [rtc](#-rtc) module
### rtc-bm8563
I²C driver for BM8563 of M5StickC (PLUS), implementation of [rtc](#-rtc) module
### display-ssd1306
I2C driver for a SSD1306 display, implementation of [display](#-display) module
I²C driver for a SSD1306 display, implementation of [display](#-display) module
### display-st7735s
SPI driver for a ST7735s display of M5StickC, implementation of [display](#-display) module
### display-st7789
SPI driver for a ST7789 display of M5StickC PLUS, implementation of [display](#-display) module
### imu-mpu6886
I²C driver for MPU6886 6-Axis IMU of M5StickC (PLUS)
### pmu-axp192
I²C driver for AXP192 PMU of M5StickC (PLUS)
### ena-binary-export \[deprecared\]

View File

@ -3,6 +3,6 @@ idf_component_register(
"ssd1306.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
display
i2c-main
"display"
"i2c-main"
)

View File

@ -221,117 +221,27 @@ void display_data(uint8_t *data, size_t length, uint8_t line, uint8_t offset, bo
i2c_cmd_link_delete(cmd);
}
void display_text_line_column(char *text, uint8_t line, uint8_t offset, bool invert)
void display_flipped(bool flipped)
{
display_chars(text, strlen(text), line, offset, invert);
}
void display_text_line(char *text, uint8_t line, bool invert)
{
display_text_line_column(text, line, 0, invert);
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
// Begin the I2C comm with SSD1306's address (SLA+Write)
i2c_master_write_byte(cmd, (SSD1306_ADDRESS << 1) | I2C_MASTER_WRITE, true);
// Tell the SSD1306 that a command stream is incoming
i2c_master_write_byte(cmd, SSD1306_CONTROL_CMD_STREAM, true);
i2c_master_write_byte(cmd, SSD1306_CMD_SEGMENT_HIGH, true);
void display_text_input(char *text, uint8_t position)
{
size_t start = 0;
if (position > 13)
if (flipped)
{
position = 13;
start = position - 13;
}
uint8_t cur_char = (uint8_t)text[start + position] - 32;
// arrow
display_data(display_gfx_arrow_left, 8, 2, 0, false);
// bounday
display_text_line_column("______________", 2, 1, false);
// arrow
display_data(display_gfx_arrow_right, 8, 2, 15 * 8, false);
// text
size_t text_length = strlen(text);
if (strlen(text) > 14)
{
text_length = 14;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
display_data(textdata, length, 2, 8, true);
free(textdata);
// arrow
display_data(display_gfx_arrow_up, 8, 0, (position + 1) * 8, false);
// upper char
display_data(display_gfx_font[cur_char - 1], 8, 1, (position + 1) * 8, false);
// sel char
display_data(display_gfx_font[cur_char], 8, 2, (position + 1) * 8, false);
// lower char
display_data(display_gfx_font[cur_char + 1], 8, 3, (position + 1) * 8, false);
// arrow
display_data(display_gfx_arrow_down, 8, 4, (position + 1) * 8, false);
}
void display_set_button(char *text, bool selected, bool primary)
{
uint8_t start = 0;
if (primary)
{
start = 64;
}
if (selected)
{
display_data(display_gfx_button_sel[0], 64, 5, start, false);
display_data(display_gfx_button_sel[1], 64, 6, start, false);
display_data(display_gfx_button_sel[2], 64, 7, start, false);
i2c_master_write_byte(cmd, SSD1306_CMD_SCAN_DIRECTION_NORMAL, true);
}
else
{
display_data(display_gfx_button[0], 64, 5, start, false);
display_data(display_gfx_button[1], 64, 6, start, false);
display_data(display_gfx_button[2], 64, 7, start, false);
}
// text
size_t text_length = strlen(text);
if (strlen(text) > 6)
{
text_length = 6;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 6)
{
offset = (6 - text_length) / 2 * 8;
i2c_master_write_byte(cmd, SSD1306_CMD_SCAN_DIRECTION_REMAPPED, true);
}
display_data(textdata, length, 6, start + 8 + offset, selected);
free(textdata);
}
void display_menu_headline(char *text, bool arrows, uint8_t line)
{
if (arrows)
{
display_data(display_gfx_arrow_left, 8, line, 0, false);
display_data(display_gfx_arrow_right, 8, line, 15 * 8, false);
}
// bounday
display_data(display_gfx_menu_head, 112, line, 8, false);
// text
size_t text_length = strlen(text);
if (strlen(text) > 10)
{
text_length = 10;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 10)
{
offset = (10 - text_length) / 2 * 8;
}
display_data(textdata, length, line, 24 + offset, true);
free(textdata);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}

View File

@ -0,0 +1,9 @@
idf_component_register(
SRCS
"st7735s.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
"display"
"spi_flash"
"pmu-axp192"
)

View File

@ -0,0 +1,340 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include "esp_log.h"
#include "display.h"
#include "display-gfx.h"
#include "axp192.h"
#include "st7735s.h"
static spi_device_handle_t st7735s_handle;
bool spi_master_write(uint8_t *data, size_t len, uint8_t dc)
{
spi_transaction_t spi_trans;
esp_err_t ret;
gpio_set_level(M5_ST7735S_DC_GPIO, dc);
memset(&spi_trans, 0, sizeof(spi_transaction_t));
spi_trans.length = len * 8;
spi_trans.tx_buffer = data;
ret = spi_device_transmit(st7735s_handle, &spi_trans);
assert(ret == ESP_OK);
return true;
}
bool spi_master_write_command(uint8_t cmd)
{
return spi_master_write(&cmd, 1, SPI_COMMAND_MODE);
}
bool spi_master_write_data_byte(uint8_t data)
{
return spi_master_write(&data, 1, SPI_DATA_MODE);
}
bool spi_master_write_data(uint8_t *data, size_t len)
{
return spi_master_write(data, len, SPI_DATA_MODE);
}
bool spi_master_write_addr(uint16_t addr1, uint16_t addr2)
{
uint8_t data[4];
data[0] = (addr1 >> 8) & 0xFF;
data[1] = addr1 & 0xFF;
data[2] = (addr2 >> 8) & 0xFF;
data[3] = addr2 & 0xFF;
return spi_master_write_data(data, 4);
}
bool spi_master_write_color(uint16_t color, size_t size)
{
uint8_t data[size * 2];
int index = 0;
uint8_t msbColor = (color >> 8) & 0xFF;
uint8_t lsbColor = color & 0xFF;
for (int i = 0; i < size; i++)
{
data[index++] = msbColor;
data[index++] = lsbColor;
}
return spi_master_write_data(data, size * 2);
}
bool spi_master_write_colors(uint16_t *colors, size_t size)
{
uint8_t data[size * 2];
int index = 0;
for (int i = 0; i < size; i++)
{
data[index++] = (colors[i] >> 8) & 0xFF;
data[index++] = colors[i] & 0xFF;
}
return spi_master_write_data(data, size * 2);
}
void display_start(void)
{
axp192_start();
axp192_screen_breath(0);
esp_err_t ret;
gpio_set_direction(M5_ST7735S_CS_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7735S_CS_GPIO, 0);
gpio_set_direction(M5_ST7735S_DC_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7735S_DC_GPIO, 0);
gpio_set_direction(M5_ST7735S_RESET_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7735S_RESET_GPIO, 0);
vTaskDelay(100 / portTICK_PERIOD_MS);
gpio_set_level(M5_ST7735S_RESET_GPIO, 1);
spi_bus_config_t buscfg = {
.sclk_io_num = M5_ST7735S_SCLK_GPIO,
.mosi_io_num = M5_ST7735S_MOSI_GPIO,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1};
ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1);
assert(ret == ESP_OK);
spi_device_interface_config_t devcfg = {
.clock_speed_hz = SPI_MASTER_FREQ_20M,
.spics_io_num = M5_ST7735S_CS_GPIO,
.queue_size = 7,
.flags = SPI_DEVICE_NO_DUMMY,
};
ret = spi_bus_add_device(HSPI_HOST, &devcfg, &st7735s_handle);
assert(ret == ESP_OK);
spi_master_write_command(0x01); //Software Reset
vTaskDelay(150 / portTICK_PERIOD_MS);
spi_master_write_command(0x11); //Sleep Out
vTaskDelay(255 / portTICK_PERIOD_MS);
spi_master_write_command(0xB1); //Frame Rate Control (In normal mode/ Full colors)
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x2C);
spi_master_write_data_byte(0x2D);
spi_master_write_command(0xB2); //Frame Rate Control (In Idle mode/ 8-colors)
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x2C);
spi_master_write_data_byte(0x2D);
spi_master_write_command(0xB3); //Frame Rate Control (In Partial mode/ full colors)
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x2C);
spi_master_write_data_byte(0x2D);
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x2C);
spi_master_write_data_byte(0x2D);
spi_master_write_command(0xB4); //Display Inversion Control
spi_master_write_data_byte(0x07);
spi_master_write_command(0xC0); //Power Control 1
spi_master_write_data_byte(0xA2);
spi_master_write_data_byte(0x02);
spi_master_write_data_byte(0x84);
spi_master_write_command(0xC1); //Power Control 2
spi_master_write_data_byte(0xC5);
spi_master_write_command(0xC2); //Power Control 3 (in Normal mode/ Full colors)
spi_master_write_data_byte(0x0A);
spi_master_write_data_byte(0x00);
spi_master_write_command(0xC3); //Power Control 4 (in Idle mode/ 8-colors)
spi_master_write_data_byte(0x8A);
spi_master_write_data_byte(0x2A);
spi_master_write_command(0xC4); //Power Control 5 (in Partial mode/ full-colors)
spi_master_write_data_byte(0x8A);
spi_master_write_data_byte(0xEE);
spi_master_write_command(0xC5); //VCOM Control 1
spi_master_write_data_byte(0x0E);
spi_master_write_command(0x20); //Display Inversion Off
spi_master_write_command(0x36); //Memory Data Access Control
spi_master_write_data_byte(M5_ST7735S_LANDSCAPE); // landscape + RGB color
spi_master_write_command(0x3A); //Interface Pixel Format
spi_master_write_data_byte(0x05); //16-bit/pixel 65K-Colors(RGB 5-6-5-bit Input)
spi_master_write_command(0x2A); //Column Address Set
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x02);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x81);
spi_master_write_command(0x2B); //Row Address Set
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0xA0);
spi_master_write_command(0x21); //Display Inversion On
spi_master_write_command(0xE0); //Gamma (+polarity) Correction Characteristics Setting
spi_master_write_data_byte(0x02);
spi_master_write_data_byte(0x1C);
spi_master_write_data_byte(0x07);
spi_master_write_data_byte(0x12);
spi_master_write_data_byte(0x37);
spi_master_write_data_byte(0x32);
spi_master_write_data_byte(0x29);
spi_master_write_data_byte(0x2D);
spi_master_write_data_byte(0x29);
spi_master_write_data_byte(0x25);
spi_master_write_data_byte(0x2B);
spi_master_write_data_byte(0x39);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x01);
spi_master_write_data_byte(0x03);
spi_master_write_data_byte(0x10);
spi_master_write_command(0xE1); //Gamma -polarity Correction Characteristics Setting
spi_master_write_data_byte(0x03);
spi_master_write_data_byte(0x1D);
spi_master_write_data_byte(0x07);
spi_master_write_data_byte(0x06);
spi_master_write_data_byte(0x2E);
spi_master_write_data_byte(0x2C);
spi_master_write_data_byte(0x29);
spi_master_write_data_byte(0x2D);
spi_master_write_data_byte(0x2E);
spi_master_write_data_byte(0x2E);
spi_master_write_data_byte(0x37);
spi_master_write_data_byte(0x3F);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x02);
spi_master_write_data_byte(0x10);
spi_master_write_command(0x13); //Normal Display Mode On
vTaskDelay(10 / portTICK_PERIOD_MS);
spi_master_write_command(0x29); //Display On
vTaskDelay(100 / portTICK_PERIOD_MS);
axp192_screen_breath(10);
}
void display_rect(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2, uint16_t color)
{
uint16_t _x1 = x1 + M5_ST7735S_OFFSETX;
uint16_t _x2 = x2 + M5_ST7735S_OFFSETX - 1;
uint16_t _y1 = y1 + M5_ST7735S_OFFSETY;
uint16_t _y2 = y2 + M5_ST7735S_OFFSETY - 1;
spi_master_write_command(0x2A); // set column(x) address
spi_master_write_addr(_x1, _x2);
spi_master_write_command(0x2B); // set Page(y) address
spi_master_write_addr(_y1, _y2);
spi_master_write_command(0x2C); // Memory Write
for (int i = _x1; i <= _x2; i++)
{
uint16_t size = _y2 - _y1 + 1;
spi_master_write_color(color, size);
}
}
void display_clear_line(uint8_t line, bool invert)
{
display_rect(0, M5_ST7735S_WIDTH, line * 8, line * 8 + 8, invert ? display_get_color() : BLACK);
}
void display_clear(void)
{
display_rect(0, M5_ST7735S_WIDTH, 0, M5_ST7735S_HEIGHT, BLACK);
}
void display_on(bool on)
{
axp192_screen_breath(on ? 10 : 0);
}
void display_data(uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert)
{
uint16_t _x1 = offset + M5_ST7735S_OFFSETX + M5_ST7735S_INTERFACE_OFFSETX;
uint16_t _x2 = offset + length + M5_ST7735S_OFFSETX - 1 + M5_ST7735S_INTERFACE_OFFSETX;
uint16_t _y1 = line * 8 + M5_ST7735S_OFFSETY + M5_ST7735S_INTERFACE_OFFSETY;
uint16_t _y2 = line * 8 + 8 + M5_ST7735S_OFFSETY - 1 + M5_ST7735S_INTERFACE_OFFSETY;
spi_master_write_command(0x2A); // set column(x) address
spi_master_write_addr(_x1, _x2);
spi_master_write_command(0x2B); // set Page(y) address
spi_master_write_addr(_y1, _y2);
spi_master_write_command(0x2C); //Memory Write
uint8_t msbColor = (display_get_color() >> 8) & 0xFF;
uint8_t lsbColor = display_get_color() & 0xFF;
for (int j = 0; j < 8; j++)
{
uint8_t color[length * 2];
int index = 0;
for (int i = 0; i < length; i++)
{
bool bit = (data[i] & (1 << j));
if (invert)
{
bit = !bit;
}
color[index++] = bit ? msbColor : 0x00;
color[index++] = bit ? lsbColor : 0x00;
}
spi_master_write_data(color, length * 2);
}
}
void display_flipped(bool flipped)
{
spi_master_write_command(0x36); //Memory Data Access Control
if (flipped)
{
spi_master_write_data_byte(M5_ST7735S_LANDSCAPE_FLIPPED);
}
else
{
spi_master_write_data_byte(M5_ST7735S_LANDSCAPE);
}
}

View File

@ -0,0 +1,27 @@
#ifndef DISPLAY_ST7735S_H_
#define DISPLAY_ST7735S_H_
#include "driver/spi_master.h"
// M5stickC
#define M5_ST7735S_WIDTH 160
#define M5_ST7735S_HEIGHT 80
#define M5_ST7735S_MOSI_GPIO 15
#define M5_ST7735S_SCLK_GPIO 13
#define M5_ST7735S_CS_GPIO 5
#define M5_ST7735S_DC_GPIO 23
#define M5_ST7735S_RESET_GPIO 18
#define M5_ST7735S_OFFSETX 1
#define M5_ST7735S_OFFSETY 26
#define M5_ST7735S_INTERFACE_OFFSETX 16
#define M5_ST7735S_INTERFACE_OFFSETY 8
#define M5_ST7735S_LANDSCAPE_FLIPPED 0x60
#define M5_ST7735S_LANDSCAPE 0xA0
#define SPI_COMMAND_MODE 0
#define SPI_DATA_MODE 1
#endif

View File

@ -0,0 +1,9 @@
idf_component_register(
SRCS
"st7789.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
"display"
"spi_flash"
"pmu-axp192"
)

View File

@ -0,0 +1,281 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include "esp_log.h"
#include "display.h"
#include "display-gfx.h"
#include "axp192.h"
#include "st7789.h"
static spi_device_handle_t st7789_handle;
bool spi_master_write(uint8_t *data, size_t len, uint8_t dc)
{
spi_transaction_t spi_trans;
gpio_set_level(M5_ST7789_DC_GPIO, dc);
memset(&spi_trans, 0, sizeof(spi_transaction_t));
spi_trans.length = len * 8;
spi_trans.tx_buffer = data;
spi_device_transmit(st7789_handle, &spi_trans);
return true;
}
bool spi_master_write_command(uint8_t cmd)
{
return spi_master_write(&cmd, 1, SPI_COMMAND_MODE);
}
bool spi_master_write_data_byte(uint8_t data)
{
return spi_master_write(&data, 1, SPI_DATA_MODE);
}
bool spi_master_write_data(uint8_t *data, size_t len)
{
return spi_master_write(data, len, SPI_DATA_MODE);
}
bool spi_master_write_addr(uint16_t addr1, uint16_t addr2)
{
uint8_t data[4];
data[0] = (addr1 >> 8) & 0xFF;
data[1] = addr1 & 0xFF;
data[2] = (addr2 >> 8) & 0xFF;
data[3] = addr2 & 0xFF;
return spi_master_write_data(data, 4);
}
bool spi_master_write_color(uint16_t color, size_t size)
{
uint8_t data[size * 2];
int index = 0;
uint8_t msbColor = (color >> 8) & 0xFF;
uint8_t lsbColor = color & 0xFF;
for (int i = 0; i < size; i++)
{
data[index++] = msbColor;
data[index++] = lsbColor;
}
return spi_master_write_data(data, size * 2);
}
bool spi_master_write_colors(uint16_t *colors, size_t size)
{
uint8_t data[size * 2];
int index = 0;
for (int i = 0; i < size; i++)
{
data[index++] = (colors[i] >> 8) & 0xFF;
data[index++] = colors[i] & 0xFF;
}
return spi_master_write_data(data, size * 2);
}
void display_start(void)
{
axp192_start();
axp192_screen_breath(0);
esp_err_t ret;
gpio_pad_select_gpio(M5_ST7789_CS_GPIO);
gpio_set_direction(M5_ST7789_CS_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7789_CS_GPIO, 0);
gpio_pad_select_gpio(M5_ST7789_DC_GPIO);
gpio_set_direction(M5_ST7789_DC_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7789_DC_GPIO, 0);
gpio_pad_select_gpio(M5_ST7789_RESET_GPIO);
gpio_set_direction(M5_ST7789_RESET_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7789_RESET_GPIO, 1);
vTaskDelay(50 / portTICK_PERIOD_MS);
gpio_set_level(M5_ST7789_RESET_GPIO, 0);
vTaskDelay(50 / portTICK_PERIOD_MS);
gpio_set_level(M5_ST7789_RESET_GPIO, 1);
vTaskDelay(50 / portTICK_PERIOD_MS);
gpio_pad_select_gpio(M5_ST7789_BL_GPIO);
gpio_set_direction(M5_ST7789_BL_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(M5_ST7789_BL_GPIO, 0);
spi_bus_config_t buscfg = {
.sclk_io_num = M5_ST7789_SCLK_GPIO,
.mosi_io_num = M5_ST7789_MOSI_GPIO,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1};
ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1);
assert(ret == ESP_OK);
spi_device_interface_config_t devcfg = {
.clock_speed_hz = SPI_MASTER_FREQ_20M,
.queue_size = 7,
.mode = 2,
.flags = SPI_DEVICE_NO_DUMMY,
};
devcfg.spics_io_num = M5_ST7789_CS_GPIO;
ret = spi_bus_add_device(HSPI_HOST, &devcfg, &st7789_handle);
assert(ret == ESP_OK);
spi_master_write_command(0x01); //Software Reset
vTaskDelay(150 / portTICK_PERIOD_MS);
spi_master_write_command(0x11); //Sleep Out
vTaskDelay(255 / portTICK_PERIOD_MS);
spi_master_write_command(0x3A); //Interface Pixel Format
spi_master_write_data_byte(0x55);
vTaskDelay(10 / portTICK_PERIOD_MS);
// landscape RGB
spi_master_write_command(0x36); //Memory Data Access Control
spi_master_write_data_byte(M5_ST7789_LANDSCAPE);
spi_master_write_command(0x2A); //Column Address Set
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0xF0);
spi_master_write_command(0x2B); //Row Address Set
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0x00);
spi_master_write_data_byte(0xF0);
spi_master_write_command(0x21); //Display Inversion On
vTaskDelay(10 / portTICK_PERIOD_MS);
spi_master_write_command(0x13); //Normal Display Mode On
vTaskDelay(10 / portTICK_PERIOD_MS);
spi_master_write_command(0x29); //Display ON
vTaskDelay(255 / portTICK_PERIOD_MS);
gpio_set_level(M5_ST7789_BL_GPIO, 1);
axp192_screen_breath(10);
}
void display_flipped(bool flipped)
{
spi_master_write_command(0x36); //Memory Data Access Control
if (flipped)
{
spi_master_write_data_byte(M5_ST7789_LANDSCAPE_FLIPPED);
}
else
{
spi_master_write_data_byte(M5_ST7789_LANDSCAPE);
}
}
void display_clear_line(uint8_t line, bool invert)
{
uint16_t _x1 = 0 + M5_ST7789_OFFSETX;
uint16_t _x2 = M5_ST7789_WIDTH + M5_ST7789_OFFSETX - 1;
uint16_t _y1 = line * 8 + M5_ST7789_OFFSETY + M5_ST7789_INTERFACE_OFFSETY;
uint16_t _y2 = line * 8 + 8 + M5_ST7789_OFFSETY - 1 + M5_ST7789_INTERFACE_OFFSETY;
spi_master_write_command(0x2A); // set column(x) address
spi_master_write_addr(_x1, _x2);
spi_master_write_command(0x2B); // set Page(y) address
spi_master_write_addr(_y1, _y2);
spi_master_write_command(0x2C); // Memory Write
for (int i = _x1; i <= _x2; i++)
{
uint16_t size = _y2 - _y1 + 1;
spi_master_write_color(invert ? display_get_color() : BLACK, size);
}
}
void display_clear(void)
{
uint16_t _x1 = 0 + M5_ST7789_OFFSETX;
uint16_t _x2 = M5_ST7789_WIDTH + M5_ST7789_OFFSETX - 1;
uint16_t _y1 = 0 + M5_ST7789_OFFSETY;
uint16_t _y2 = M5_ST7789_HEIGHT + M5_ST7789_OFFSETY - 1;
spi_master_write_command(0x2A); // set column(x) address
spi_master_write_addr(_x1, _x2);
spi_master_write_command(0x2B); // set Page(y) address
spi_master_write_addr(_y1, _y2);
spi_master_write_command(0x2C); // Memory Write
for (int i = _x1; i <= _x2; i++)
{
uint16_t size = _y2 - _y1 + 1;
spi_master_write_color(BLACK, size);
}
}
void display_on(bool on)
{
axp192_screen_breath(on ? 10 : 0);
}
void display_data(uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert)
{
uint16_t _x1 = offset + M5_ST7789_OFFSETX + M5_ST7789_INTERFACE_OFFSETX;
uint16_t _x2 = offset + length + M5_ST7789_OFFSETX - 1 + M5_ST7789_INTERFACE_OFFSETX;
uint16_t _y1 = line * 8 + M5_ST7789_OFFSETY + M5_ST7789_INTERFACE_OFFSETY;
uint16_t _y2 = line * 8 + 8 + M5_ST7789_OFFSETY - 1 + M5_ST7789_INTERFACE_OFFSETY;
spi_master_write_command(0x2A); // set column(x) address
spi_master_write_addr(_x1, _x2);
spi_master_write_command(0x2B); // set Page(y) address
spi_master_write_addr(_y1, _y2);
spi_master_write_command(0x2C); //Memory Write
uint8_t msbColor = (display_get_color() >> 8) & 0xFF;
uint8_t lsbColor = display_get_color() & 0xFF;
for (int j = 0; j < 8; j++)
{
uint8_t color[length * 2];
int index = 0;
for (int i = 0; i < length; i++)
{
bool bit = (data[i] & (1 << j));
if (invert)
{
bit = !bit;
}
color[index++] = bit ? msbColor : 0x00;
color[index++] = bit ? lsbColor : 0x00;
}
spi_master_write_data(color, length * 2);
}
}

View File

@ -0,0 +1,30 @@
#ifndef DISPLAY_ST7789_H_
#define DISPLAY_ST7789_H_
#include "driver/spi_master.h"
// M5stickC PLUS
#define M5_ST7789_WIDTH 240
#define M5_ST7789_HEIGHT 135
#define M5_ST7789_MOSI_GPIO 15
#define M5_ST7789_SCLK_GPIO 13
#define M5_ST7789_CS_GPIO 5
#define M5_ST7789_DC_GPIO 23
#define M5_ST7789_RESET_GPIO 18
#define M5_ST7789_BL_GPIO 32
#define M5_ST7789_OFFSETX 40
#define M5_ST7789_OFFSETY 52
#define M5_ST7789_LANDSCAPE 0x60
#define M5_ST7789_LANDSCAPE_FLIPPED 0xA0
#define M5_ST7789_INTERFACE_OFFSETX 56
#define M5_ST7789_INTERFACE_OFFSETY 35
#define SPI_COMMAND_MODE 0
#define SPI_DATA_MODE 1
#endif

View File

@ -16,6 +16,8 @@
#include "display.h"
#include "display-gfx.h"
static uint16_t current_color = WHITE;
uint8_t display_utf8_to_ascii_char(uint8_t ascii)
{
static uint8_t c1;
@ -87,4 +89,129 @@ void display_chars(char *text, size_t length, uint8_t line, uint8_t offset, bool
display_data(textdata, res_length, line, offset * font_width, invert);
free(textdata);
}
}
void display_text_line_column(char *text, uint8_t line, uint8_t offset, bool invert)
{
display_chars(text, strlen(text), line, offset, invert);
}
void display_text_line(char *text, uint8_t line, bool invert)
{
display_text_line_column(text, line, 0, invert);
}
void display_text_input(char *text, uint8_t position)
{
size_t start = 0;
if (position > 13)
{
position = 13;
start = position - 13;
}
uint8_t cur_char = (uint8_t)text[start + position] - 32;
// arrow
display_data(display_gfx_arrow_left, 8, 2, 0, false);
// bounday
display_text_line_column("______________", 2, 1, false);
// arrow
display_data(display_gfx_arrow_right, 8, 2, 15 * 8, false);
// text
size_t text_length = strlen(text);
if (strlen(text) > 14)
{
text_length = 14;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
display_data(textdata, length, 2, 8, true);
free(textdata);
// arrow
display_data(display_gfx_arrow_up, 8, 0, (position + 1) * 8, false);
// upper char
display_data(display_gfx_font[cur_char - 1], 8, 1, (position + 1) * 8, false);
// sel char
display_data(display_gfx_font[cur_char], 8, 2, (position + 1) * 8, false);
// lower char
display_data(display_gfx_font[cur_char + 1], 8, 3, (position + 1) * 8, false);
// arrow
display_data(display_gfx_arrow_down, 8, 4, (position + 1) * 8, false);
}
void display_set_button(char *text, bool selected, bool primary)
{
uint8_t start = 0;
if (primary)
{
start = 64;
}
if (selected)
{
display_data(display_gfx_button_sel[0], 64, 5, start, false);
display_data(display_gfx_button_sel[1], 64, 6, start, false);
display_data(display_gfx_button_sel[2], 64, 7, start, false);
}
else
{
display_data(display_gfx_button[0], 64, 5, start, false);
display_data(display_gfx_button[1], 64, 6, start, false);
display_data(display_gfx_button[2], 64, 7, start, false);
}
// text
size_t text_length = strlen(text);
if (strlen(text) > 6)
{
text_length = 6;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 6)
{
offset = (6 - text_length) / 2 * 8;
}
display_data(textdata, length, 6, start + 8 + offset, selected);
free(textdata);
}
void display_menu_headline(char *text, bool arrows, uint8_t line)
{
if (arrows)
{
display_data(display_gfx_arrow_left, 8, line, 0, false);
display_data(display_gfx_arrow_right, 8, line, 15 * 8, false);
}
// bounday
display_data(display_gfx_menu_head, 112, line, 8, false);
// text
size_t text_length = strlen(text);
if (strlen(text) > 10)
{
text_length = 10;
}
size_t length = 0;
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 10)
{
offset = (10 - text_length) / 2 * 8;
}
display_data(textdata, length, line, 24 + offset, true);
free(textdata);
}
void display_set_color(uint16_t color)
{
current_color = color;
}
uint16_t display_get_color(void)
{
return current_color;
}

View File

@ -22,6 +22,18 @@
#include "esp_system.h"
#define DISPLAY_COLUMNS 8
#define BLACK 0x0000
#define WHITE 0xffff
#define RED 0xf800
#define GREEN 0x07e0
#define BLUE 0x001f
#define GRAY 0x8c51
#define YELLOW 0xFFE0
#define CYAN 0x07FF
#define PURPLE 0xF81F
/**
*
*/
@ -43,7 +55,7 @@ void display_start(void);
* @param[in] line the line to clear
* @param[in] invert if true, image is inverted
*/
void display_clear_line( uint8_t line, bool invert);
void display_clear_line(uint8_t line, bool invert);
/**
* @brief clear the display
@ -52,12 +64,19 @@ void display_clear_line( uint8_t line, bool invert);
void display_clear(void);
/**
* @brief set display on or offf
* @brief set display on or off
*
* @param[in] on true if display on, false if display off
*/
void display_on(bool on);
/**
* @brief set display flipped or not
*
* @param[in] on true display is flipped
*/
void display_flipped(bool flipped);
/**
*
*/
@ -122,4 +141,18 @@ void display_set_button(char *text, bool selected, bool primary);
*/
void display_menu_headline(char *text, bool arrows, uint8_t line);
/**
* @brief set current color for colored displays
*
* @param[in] color the color to set
*/
void display_set_color(uint16_t color);
/**
* @brief set current color for colored displays
*
* @return the current color
*/
uint16_t display_get_color(void);
#endif

View File

@ -38,6 +38,23 @@ static time_t request_sleep = 0;
static uint32_t request_sleep_waiting = 30;
static time_t last_check = 0;
static bool wait_for_request = false;
static bool request_pause = false;
void ena_eke_proxy_pause(void)
{
while (wait_for_request || request_pause)
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "waiting for other requests to finish...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
request_pause = true;
}
void ena_eke_proxy_resume(void)
{
request_pause = false;
}
esp_err_t ena_eke_proxy_fetch_event_handler(esp_http_client_event_t *evt)
{
@ -256,7 +273,7 @@ void ena_eke_proxy_run(void)
last_check = (time_t)ena_storage_read_last_exposure_date();
check_diff = difftime(current_time, last_check);
if (check_diff > HOUR_IN_SECONDS && !wait_for_request && current_time > request_sleep)
if (check_diff > HOUR_IN_SECONDS && !wait_for_request && !request_pause && current_time > request_sleep)
{
if (wifi_controller_connection() == NULL && current_time > wifi_reconnect && wifi_reconnect_waiting < 86400)
{
@ -323,6 +340,7 @@ esp_err_t ena_eke_proxy_fetch_upload_handler(esp_http_client_event_t *evt)
case HTTP_EVENT_ON_DATA:
break;
case HTTP_EVENT_ON_FINISH:
ena_eke_proxy_resume();
break;
default:
break;
@ -333,6 +351,8 @@ esp_err_t ena_eke_proxy_fetch_upload_handler(esp_http_client_event_t *evt)
esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptoms)
{
ena_eke_proxy_pause();
ESP_LOGD(ENA_EKE_PROXY_LOG, "try to upload keys:");
esp_http_client_config_t config = {
.url = ENA_EKE_PROXY_KEYFILES_UPLOAD_URL,
@ -380,7 +400,7 @@ esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptom
if (status == 200)
{
ESP_LOGI(ENA_EKE_PROXY_LOG, "successfully uploaded keys : url = %s, status = %d, content_length = %d", ENA_EKE_PROXY_KEYFILES_UPLOAD_URL, status, content_length);
err = ESP_OK;
err = ESP_OK;
}
else
{
@ -391,6 +411,7 @@ esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptom
else
{
ESP_LOGW(ENA_EKE_PROXY_LOG, "Keyupload failed!");
ena_eke_proxy_resume();
}
free(output_buffer);

View File

@ -85,4 +85,16 @@ void ena_eke_proxy_run(void);
*/
esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptoms);
/**
* @brief pause requests
*
*/
void ena_eke_proxy_pause(void);
/**
* @brief resume requests
*
*/
void ena_eke_proxy_resume(void);
#endif

View File

@ -2,11 +2,11 @@ menu "I²C"
config I2C_SDA_PIN
int "I²C sda pin"
default 22
default 21
config I2C_SCL_PIN
int "I²C scl pin"
default 23
default 22
config I2C_CLOCKSPEED
int "I²C clock speed"

View File

@ -0,0 +1,7 @@
idf_component_register(
SRCS
"mpu6886.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
i2c-main
)

View File

@ -0,0 +1,260 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <time.h>
#include "driver/i2c.h"
#include "esp_log.h"
#include "i2c-main.h"
#include "mpu6886.h"
int Gyscale = GFS_2000DPS;
int Acscale = AFS_8G;
float aRes, gRes;
void mpu6886_i2c_read_bytes(uint8_t driver_addr, uint8_t start_addr, uint8_t number_Bytes, uint8_t *read_buffer)
{
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (driver_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, start_addr, true);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (driver_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, read_buffer, number_Bytes, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}
void mpu6886_i2c_write_bytes(uint8_t driver_addr, uint8_t start_addr, uint8_t number_Bytes, uint8_t *write_buffer)
{
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (driver_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, start_addr, true);
i2c_master_write(cmd, write_buffer, number_Bytes, true);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}
void mpu6886_getGres()
{
switch (Gyscale)
{
// Possible gyro scales (and their register bit settings) are:
case GFS_250DPS:
gRes = 250.0 / 32768.0;
break;
case GFS_500DPS:
gRes = 500.0 / 32768.0;
break;
case GFS_1000DPS:
gRes = 1000.0 / 32768.0;
break;
case GFS_2000DPS:
gRes = 2000.0 / 32768.0;
break;
}
}
void mpu6886_getAres()
{
switch (Acscale)
{
// Possible accelerometer scales (and their register bit settings) are:
// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
case AFS_2G:
aRes = 2.0 / 32768.0;
break;
case AFS_4G:
aRes = 4.0 / 32768.0;
break;
case AFS_8G:
aRes = 8.0 / 32768.0;
break;
case AFS_16G:
aRes = 16.0 / 32768.0;
break;
}
}
int mpu6886_start(void)
{
unsigned char tempdata[1];
unsigned char regdata;
if (!i2c_is_initialized())
{
i2c_main_init();
}
mpu6886_i2c_read_bytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
if (tempdata[0] != 0x19)
return -1;
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x00;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
vTaskDelay(10 / portTICK_PERIOD_MS);;
regdata = (0x01 << 7);
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
vTaskDelay(10 / portTICK_PERIOD_MS);;
regdata = (0x01 << 0);
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, &regdata);
vTaskDelay(10 / portTICK_PERIOD_MS);;
regdata = 0x10;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x18;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x01;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x05;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x00;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x00;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG2, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x00;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x00;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x22;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_INT_PIN_CFG, 1, &regdata);
vTaskDelay(1 / portTICK_PERIOD_MS);;
regdata = 0x01;
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, &regdata);
vTaskDelay(100 / portTICK_PERIOD_MS);;
mpu6886_getGres();
mpu6886_getAres();
return 0;
}
void mpu6886_get_accel_adc(int16_t *ax, int16_t *ay, int16_t *az)
{
uint8_t buf[6];
mpu6886_i2c_read_bytes(MPU6886_ADDRESS, MPU6886_ACCEL_XOUT_H, 6, buf);
*ax = ((int16_t)buf[0] << 8) | buf[1];
*ay = ((int16_t)buf[2] << 8) | buf[3];
*az = ((int16_t)buf[4] << 8) | buf[5];
}
void mpu6886_get_gyro_adc(int16_t *gx, int16_t *gy, int16_t *gz)
{
uint8_t buf[6];
mpu6886_i2c_read_bytes(MPU6886_ADDRESS, MPU6886_GYRO_XOUT_H, 6, buf);
*gx = ((uint16_t)buf[0] << 8) | buf[1];
*gy = ((uint16_t)buf[2] << 8) | buf[3];
*gz = ((uint16_t)buf[4] << 8) | buf[5];
}
void mpu6886_get_temp_adc(int16_t *t)
{
uint8_t buf[2];
mpu6886_i2c_read_bytes(MPU6886_ADDRESS, MPU6886_TEMP_OUT_H, 2, buf);
*t = ((uint16_t)buf[0] << 8) | buf[1];
}
void mpu6886_set_gyro_fsr(int scale)
{
//return IIC_Write_Byte(MPU_GYRO_CFG_REG,scale<<3);//设置陀螺仪满量程范围
unsigned char regdata;
regdata = (scale << 3);
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, &regdata);
vTaskDelay(10 / portTICK_PERIOD_MS);;
Gyscale = scale;
mpu6886_getGres();
}
void mpu6886_set_accel_fsr(int scale)
{
unsigned char regdata;
regdata = (scale << 3);
mpu6886_i2c_write_bytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, &regdata);
vTaskDelay(10 / portTICK_PERIOD_MS);;
Acscale = scale;
mpu6886_getAres();
}
void mpu6886_get_accel_data(float *ax, float *ay, float *az)
{
int16_t accX = 0;
int16_t accY = 0;
int16_t accZ = 0;
mpu6886_get_accel_adc(&accX, &accY, &accZ);
*ax = (float)accX * aRes;
*ay = (float)accY * aRes;
*az = (float)accZ * aRes;
}
void mpu6886_get_gyro_data(float *gx, float *gy, float *gz)
{
int16_t gyroX = 0;
int16_t gyroY = 0;
int16_t gyroZ = 0;
mpu6886_get_gyro_adc(&gyroX, &gyroY, &gyroZ);
*gx = (float)gyroX * gRes;
*gy = (float)gyroY * gRes;
*gz = (float)gyroZ * gRes;
}
void mpu6886_get_temp_data(float *t)
{
int16_t temp = 0;
mpu6886_get_temp_adc(&temp);
*t = (float)temp / 326.8 + 25.0;
}

View File

@ -0,0 +1,78 @@
/*
Note: The MPU6886 is an I2C sensor and uses the Arduino Wire library.
Because the sensor is not 5V tolerant, we are using a 3.3 V 8 MHz Pro Mini or
a 3.3 V Teensy 3.1. We have disabled the internal pull-ups used by the Wire
library in the Wire.h/twi.c utility file. We are also using the 400 kHz fast
I2C mode by setting the TWI_FREQ to 400000L /twi.h utility file.
*/
#ifndef _IMU_MPU6886_H_
#define _IMU_MPU6886_H_
#include "stdio.h"
#define MPU6886_ADDRESS 0x68
#define MPU6886_WHOAMI 0x75
#define MPU6886_ACCEL_INTEL_CTRL 0x69
#define MPU6886_SMPLRT_DIV 0x19
#define MPU6886_INT_PIN_CFG 0x37
#define MPU6886_INT_ENABLE 0x38
#define MPU6886_ACCEL_XOUT_H 0x3B
#define MPU6886_ACCEL_XOUT_L 0x3C
#define MPU6886_ACCEL_YOUT_H 0x3D
#define MPU6886_ACCEL_YOUT_L 0x3E
#define MPU6886_ACCEL_ZOUT_H 0x3F
#define MPU6886_ACCEL_ZOUT_L 0x40
#define MPU6886_TEMP_OUT_H 0x41
#define MPU6886_TEMP_OUT_L 0x42
#define MPU6886_GYRO_XOUT_H 0x43
#define MPU6886_GYRO_XOUT_L 0x44
#define MPU6886_GYRO_YOUT_H 0x45
#define MPU6886_GYRO_YOUT_L 0x46
#define MPU6886_GYRO_ZOUT_H 0x47
#define MPU6886_GYRO_ZOUT_L 0x48
#define MPU6886_USER_CTRL 0x6A
#define MPU6886_PWR_MGMT_1 0x6B
#define MPU6886_PWR_MGMT_2 0x6C
#define MPU6886_CONFIG 0x1A
#define MPU6886_GYRO_CONFIG 0x1B
#define MPU6886_ACCEL_CONFIG 0x1C
#define MPU6886_ACCEL_CONFIG2 0x1D
#define MPU6886_FIFO_EN 0x23
//#define G (9.8)
#define RtA 57.324841
#define AtR 0.0174533
#define Gyro_Gr 0.0010653
enum Ascale
{
AFS_2G = 0,
AFS_4G,
AFS_8G,
AFS_16G
} ;
enum Gscale
{
GFS_250DPS = 0,
GFS_500DPS,
GFS_1000DPS,
GFS_2000DPS
};
int mpu6886_start(void);
void mpu6886_get_accel_adc(int16_t *ax, int16_t *ay, int16_t *az);
void mpu6886_get_gyro_adc(int16_t *gx, int16_t *gy, int16_t *gz);
void mpu6886_get_temp_adc(int16_t *t);
void mpu6886_get_accel_data(float *ax, float *ay, float *az);
void mpu6886_get_gyro_data(float *gx, float *gy, float *gz);
void mpu6886_get_temp_data(float *t);
void mpu6886_set_gyro_fsr(int scale);
void mpu6886_set_accel_fsr(int scale);
#endif

View File

@ -21,39 +21,64 @@
#include "button-input.h"
static int old_button_states[INTERFACE_COMMANDS_SIZE];
static int button_states[INTERFACE_COMMANDS_SIZE];
static float button_states[INTERFACE_COMMANDS_SIZE];
static int button_command_mapping[INTERFACE_COMMANDS_SIZE];
void button_input_check(interface_command_t command)
{
button_states[command] = gpio_get_level(button_command_mapping[command]);
int button_level = gpio_get_level(button_command_mapping[command]);
if (old_button_states[command] != 0 && old_button_states[command] != 1)
if (button_level == 0)
{
old_button_states[command] = 1;
}
button_states[command] = button_states[command] + ((float)INTERFACE_INPUT_TICKS_MS / 1000);
if (button_states[command] == 0 && button_states[command] != old_button_states[command])
if (command == INTERFACE_COMMAND_SET && button_states[command] > INTERFACE_LONG_STATE_SECONDS)
{
button_states[command] = 0;
button_states[INTERFACE_COMMAND_SET_LONG] = button_states[INTERFACE_COMMAND_SET_LONG] + 1;
interface_execute_command(INTERFACE_COMMAND_SET_LONG);
}
else if (command == INTERFACE_COMMAND_RST && button_states[command] > INTERFACE_LONG_STATE_SECONDS)
{
button_states[command] = 0;
button_states[INTERFACE_COMMAND_RST_LONG] = button_states[INTERFACE_COMMAND_RST_LONG] + 1;
interface_execute_command(INTERFACE_COMMAND_RST_LONG);
}
}
else if (button_level == 1 && button_states[command] > 0)
{
interface_execute_command(command);
}
button_states[command] = 0;
old_button_states[command] = button_states[command];
if (command == INTERFACE_COMMAND_SET && button_states[INTERFACE_COMMAND_SET_LONG] > 0)
{
button_states[INTERFACE_COMMAND_SET_LONG] = 0;
}
else if (command == INTERFACE_COMMAND_RST && button_states[INTERFACE_COMMAND_RST_LONG] > 0)
{
button_states[INTERFACE_COMMAND_RST_LONG] = 0;
}
else
{
interface_execute_command(command);
}
}
}
void button_input_task(void *pvParameter)
{
while (1)
{
button_input_check(INTERFACE_COMMAND_RST);
button_input_check(INTERFACE_COMMAND_SET);
button_input_check(INTERFACE_COMMAND_MID);
button_input_check(INTERFACE_COMMAND_RHT);
button_input_check(INTERFACE_COMMAND_LFT);
button_input_check(INTERFACE_COMMAND_DWN);
button_input_check(INTERFACE_COMMAND_UP);
vTaskDelay(20 / portTICK_PERIOD_MS);
if (!interface_is_idle())
{
button_input_check(INTERFACE_COMMAND_RST);
button_input_check(INTERFACE_COMMAND_MID);
button_input_check(INTERFACE_COMMAND_RHT);
button_input_check(INTERFACE_COMMAND_LFT);
button_input_check(INTERFACE_COMMAND_DWN);
button_input_check(INTERFACE_COMMAND_UP);
}
vTaskDelay(INTERFACE_INPUT_TICKS_MS / portTICK_PERIOD_MS);
}
}

View File

@ -0,0 +1,8 @@
idf_component_register(
SRCS
"m5-input.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
interface
imu-mpu6886
)

View File

@ -0,0 +1,205 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "mpu6886.h"
#include "interface.h"
#include "m5-input.h"
static float old_input_states[INTERFACE_COMMANDS_SIZE];
static float input_states[INTERFACE_COMMANDS_SIZE];
static int input_command_mapping[INTERFACE_COMMANDS_SIZE];
static bool flipped = false;
void button_input_check(interface_command_t command)
{
int button_level = gpio_get_level(input_command_mapping[command]);
if (button_level == 0)
{
input_states[command] = input_states[command] + ((float)INTERFACE_INPUT_TICKS_MS / 1000);
if (command == INTERFACE_COMMAND_SET && input_states[command] > INTERFACE_LONG_STATE_SECONDS)
{
input_states[command] = 0;
input_states[INTERFACE_COMMAND_SET_LONG] = input_states[INTERFACE_COMMAND_SET_LONG] + 1;
interface_execute_command(INTERFACE_COMMAND_SET_LONG);
}
else if (command == INTERFACE_COMMAND_RST && input_states[command] > INTERFACE_LONG_STATE_SECONDS)
{
input_states[command] = 0;
input_states[INTERFACE_COMMAND_RST_LONG] = input_states[INTERFACE_COMMAND_RST_LONG] + 1;
interface_execute_command(INTERFACE_COMMAND_RST_LONG);
}
}
else if (button_level == 1 && input_states[command] > 0)
{
input_states[command] = 0;
if (command == INTERFACE_COMMAND_SET && input_states[INTERFACE_COMMAND_SET_LONG] > 0)
{
input_states[INTERFACE_COMMAND_SET_LONG] = 0;
}
else if (command == INTERFACE_COMMAND_RST && input_states[INTERFACE_COMMAND_RST_LONG] > 0)
{
input_states[INTERFACE_COMMAND_RST_LONG] = 0;
}
else
{
if (!interface_is_idle() && flipped)
{
if (command == INTERFACE_COMMAND_SET)
{
command = INTERFACE_COMMAND_RST;
}
else if (command == INTERFACE_COMMAND_RST)
{
command = INTERFACE_COMMAND_SET;
}
}
interface_execute_command(command);
}
}
}
void accel_input_up(float axis)
{
input_states[INTERFACE_COMMAND_UP] = axis;
if (axis < -0.3 && old_input_states[INTERFACE_COMMAND_UP] > -0.3 && old_input_states[INTERFACE_COMMAND_UP] + axis < -0.5)
{
interface_execute_command(INTERFACE_COMMAND_UP);
old_input_states[INTERFACE_COMMAND_UP] = axis;
}
else if (axis > -0.3)
{
old_input_states[INTERFACE_COMMAND_UP] = 0;
}
}
void accel_input_left(float axis)
{
input_states[INTERFACE_COMMAND_LFT] = axis;
if (axis < -0.3 && old_input_states[INTERFACE_COMMAND_LFT] > -0.3 && old_input_states[INTERFACE_COMMAND_LFT] + axis < -0.5)
{
interface_execute_command(INTERFACE_COMMAND_LFT);
old_input_states[INTERFACE_COMMAND_LFT] = axis;
}
else if (axis > -0.3)
{
old_input_states[INTERFACE_COMMAND_LFT] = 0;
}
}
void accel_input_right(float axis)
{
input_states[INTERFACE_COMMAND_RHT] = axis;
if (axis > 0.3 && old_input_states[INTERFACE_COMMAND_RHT] < 0.3 && old_input_states[INTERFACE_COMMAND_RHT] + axis > 0.5)
{
interface_execute_command(INTERFACE_COMMAND_RHT);
old_input_states[INTERFACE_COMMAND_RHT] = axis;
}
else if (axis < 0.3)
{
old_input_states[INTERFACE_COMMAND_RHT] = 0;
}
}
void accel_input_down(float axis)
{
input_states[INTERFACE_COMMAND_DWN] = axis;
if (axis > 0.3 && old_input_states[INTERFACE_COMMAND_DWN] < 0.3 && old_input_states[INTERFACE_COMMAND_DWN] + axis > 0.5)
{
interface_execute_command(INTERFACE_COMMAND_DWN);
old_input_states[INTERFACE_COMMAND_DWN] = axis;
}
else if (axis < 0.3)
{
old_input_states[INTERFACE_COMMAND_DWN] = 0;
}
}
void gyro_input(float axis)
{
input_states[INTERFACE_COMMAND_MID] = axis;
if (axis < -50 && old_input_states[INTERFACE_COMMAND_MID] > 50)
{
// interface_execute_command(INTERFACE_COMMAND_MID);
old_input_states[INTERFACE_COMMAND_MID] = axis;
ESP_LOGI(INTERFACE_LOG, "gyro: %f", axis);
}
else if (axis > 50)
{
old_input_states[INTERFACE_COMMAND_MID] = axis;
}
}
void m5_input_task(void *pvParameter)
{
float ax = 0;
float ay = 0;
float az = 0;
while (1)
{
button_input_check(INTERFACE_COMMAND_SET);
if (!interface_is_idle())
{
button_input_check(INTERFACE_COMMAND_RST);
mpu6886_get_accel_data(&ax, &ay, &az);
accel_input_up(flipped ? -ax : ax);
accel_input_left(flipped ? -ay : ay);
accel_input_right(flipped ? -ay : ay);
accel_input_down(flipped ? -ax : ax);
if (ax >= 1)
{
flipped = false;
interface_flipped(flipped);
}
else if (ax <= -1)
{
flipped = true;
interface_flipped(flipped);
}
}
vTaskDelay(INTERFACE_INPUT_TICKS_MS / portTICK_PERIOD_MS);
}
}
void m5_input_start(void)
{
gpio_config_t io_conf;
io_conf.pin_bit_mask = (1ULL << BUTTON_RST) | (1ULL << BUTTON_SET);
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&io_conf);
input_command_mapping[INTERFACE_COMMAND_RST] = BUTTON_RST;
input_command_mapping[INTERFACE_COMMAND_SET] = BUTTON_SET;
mpu6886_start();
xTaskCreate(&m5_input_task, "m5_input_task", 4096, NULL, 5, NULL);
}

View File

@ -0,0 +1,33 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @file
*
* @brief execute interface commands via simple push buttons
*
*/
#ifndef _m5_input_H_
#define _m5_input_H_
#define BUTTON_RST GPIO_NUM_37
#define BUTTON_SET GPIO_NUM_39
/**
* @brief
*
*
*/
void m5_input_start(void);
#endif

View File

@ -1,9 +1,24 @@
set(priv_requires "ena" "ena-eke-proxy" "display" "rtc" "wifi-controller" )
if(CONFIG_ENA_INTERFACE_CUSTOM)
list(APPEND priv_requires "display-ssd1306" "rtc-ds3231")
elseif(ENA_INTERFACE_M5STICKC)
list(APPEND priv_requires "display-st7735s" "rtc-bm8563" "imu-mpu6886" "pmu-axp192")
elseif(ENA_INTERFACE_M5STICKC_PLUS)
list(APPEND priv_requires "display-st7789" "rtc-bm8563" "imu-mpu6886" "pmu-axp192")
else()
list(APPEND priv_requires "display-ssd1306" "rtc-ds3231") # uncomment for custom device with SSD1306 und DS3231
# list(APPEND priv_requires "display-st7735s" "rtc-bm8563" "imu-mpu6886" "pmu-axp192") # uncomment for M5StickC
# list(APPEND priv_requires "display-st7789" "rtc-bm8563" "imu-mpu6886" "pmu-axp192") # uncomment for M5StickC PLUS
endif()
idf_component_register(
SRCS
"interface.c"
"interface-main.c"
"interface-data.c"
"interface-datetime.c"
"interface-debug.c"
"interface-info.c"
"interface-input.c"
"interface-label.c"
@ -11,12 +26,5 @@ idf_component_register(
"interface-settings.c"
"interface-wifi.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
ena
ena-eke-proxy
display
display-ssd1306
rtc
rtc-ds3231
wifi-controller
PRIV_REQUIRES ${priv_requires}
)

View File

@ -0,0 +1,26 @@
menu "ENA Interface"
config ENA_INTERFACE_IDLE_TIME
int "Seconds after display turns off on inactivity"
default 15
config ENA_INTERFACE_DEBUG
bool "Adds a debug interface for additional information for device"
default false
choice ENA_INTERFACE_DEVICE
prompt "Choose device"
default ENA_INTERFACE_CUSTOM
config ENA_INTERFACE_CUSTOM
bool "Custom"
config ENA_INTERFACE_M5STICKC
bool "M5StickC"
config ENA_INTERFACE_M5STICKC_PLUS
bool "M5StickC PLUS"
endchoice
endmenu

View File

@ -49,9 +49,12 @@ void interface_data_set(void)
else
{
confirm_current = false;
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
display_clear_line(2, false);
display_clear_line(3, false);
display_clear_line(4, false);
display_clear_line(5, false);
display_clear_line(6, false);
display_clear_line(7, false);
}
}
@ -83,9 +86,19 @@ void interface_data_rst(void)
}
confirm_current = false;
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
display_clear_line(2, false);
display_clear_line(3, false);
display_clear_line(4, false);
display_clear_line(5, false);
display_clear_line(6, false);
display_clear_line(7, false);
}
else
{
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
confirm_current = true;
}
}
@ -96,16 +109,20 @@ void interface_data_lft(void)
void interface_data_rht(void)
{
#if defined(CONFIG_ENA_INTERFACE_DEBUG)
interface_debug_start();
#else
interface_info_start();
#endif
}
void interface_data_mid(void)
{
if (!confirm_current)
{
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
confirm_current = true;
}
}
@ -124,9 +141,9 @@ void interface_data_up(void)
current_data_index--;
}
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
}
void interface_data_dwn(void)
@ -142,26 +159,28 @@ void interface_data_dwn(void)
current_data_index++;
}
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
}
void interface_data_display(void)
{
display_menu_headline( interface_get_label_text(&interface_text_headline_data), true, 0);
display_menu_headline(interface_get_label_text(&interface_text_headline_data), true, 0);
if (confirm_current)
{
display_text_line_column( interface_get_label_text(&interface_text_data_del[current_interface_data_state]), 2, 2, false);
display_text_line_column( "?", 2, strlen(interface_get_label_text(&interface_text_data_del[current_interface_data_state])) + 2, false);
display_text_line_column(interface_get_label_text(&interface_text_data_del[current_interface_data_state]), 2, 2, false);
display_text_line_column("?", 2, strlen(interface_get_label_text(&interface_text_data_del[current_interface_data_state])) + 2, false);
display_set_button( interface_get_label_text(&interface_text_button_cancel), true, false);
display_set_button( interface_get_label_text(&interface_text_button_ok), false, true);
display_set_button(interface_get_label_text(&interface_text_button_cancel), true, false);
display_set_button(interface_get_label_text(&interface_text_button_ok), false, true);
}
else
{
display_clear_line( 5, false);
display_clear_line( 7, false);
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
for (int i = 0; i < 3; i++)
{
int index = i + current_data_index;
@ -169,10 +188,14 @@ void interface_data_display(void)
{
if (index == current_interface_data_state)
{
display_data( display_gfx_arrow_right, 8, i * 2 + 2, 8, false);
display_data(display_gfx_arrow_right, 8, i * 2 + 2, 8, false);
}
else
{
display_data(display_gfx_clear, 8, i * 2 + 2, 8, false);
}
display_text_line_column( interface_get_label_text(&interface_text_data_del[index]), i * 2 + 2, 2, false);
display_text_line_column(interface_get_label_text(&interface_text_data_del[index]), i * 2 + 2, 2, false);
}
}
}
@ -189,8 +212,6 @@ void interface_data_start(void)
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_data_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_data_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_data_dwn);
interface_set_display_function(&interface_data_display);
interface_set_display_refresh_function(NULL);
ESP_LOGD(INTERFACE_LOG, "start delete data interface");
interface_set_display_function(&interface_data_display);
}

View File

@ -64,7 +64,6 @@ void interface_datetime_mid(void)
{
current_interface_datetime_state = INTERFACE_DATETIME_STATE_HOUR;
}
ESP_LOGD(INTERFACE_LOG, "datetime to %d", current_interface_datetime_state);
}
void interface_datetime_up(void)
@ -75,7 +74,6 @@ void interface_datetime_up(void)
tv.tv_sec = curtime;
settimeofday(&tv, NULL);
rtc_set_time(gmtime(&curtime));
ESP_LOGD(INTERFACE_LOG, "increment %d about %u %s", current_interface_datetime_state, interface_datetime_steps[current_interface_datetime_state], ctime(&curtime));
}
void interface_datetime_dwn(void)
@ -86,37 +84,40 @@ void interface_datetime_dwn(void)
tv.tv_sec = curtime;
settimeofday(&tv, NULL);
rtc_set_time(gmtime(&curtime));
ESP_LOGD(INTERFACE_LOG, "decrement %d about %u %s", current_interface_datetime_state, interface_datetime_steps[current_interface_datetime_state], ctime(&curtime));
}
void interface_datetime_display(void)
{
display_menu_headline(interface_get_label_text(&interface_text_headline_time), true, 0);
}
void interface_datetime_display_refresh(void)
{
static time_t current_timstamp;
static struct tm *current_tm;
static char time_buffer[9];
static char date_buffer[32];
display_menu_headline( interface_get_label_text(&interface_text_headline_time), true, 0);
static char edit_char[3];
static int edit_line = 3;
int edit_length = 2;
int edit_offset = 0;
display_clear_line( edit_line - 1, false);
display_clear_line( edit_line + 1, false);
display_clear_line(edit_line - 1, false);
display_clear_line(edit_line + 1, false);
time(&current_timstamp);
current_tm = gmtime(&current_timstamp);
current_tm->tm_hour = current_tm->tm_hour + (interface_get_timezone_offset()) % 24;
strftime(time_buffer, 16, INTERFACE_FORMAT_TIME, current_tm);
display_text_line_column( time_buffer, 3, 4, false);
display_text_line_column(time_buffer, 3, 4, false);
sprintf(date_buffer, "%02d %s %02d",
current_tm->tm_mday,
interface_get_label_text(&interface_texts_month[current_tm->tm_mon]),
current_tm->tm_year - 100);
display_text_line_column( date_buffer, 6, 4, false);
display_text_line_column(date_buffer, 6, 4, false);
switch (interface_datetime_state())
{
@ -154,9 +155,11 @@ void interface_datetime_display(void)
break;
}
display_data( display_gfx_arrow_up, 8, edit_line - 1, edit_offset * 8 + 4, false);
display_chars( edit_char, edit_length, edit_line, edit_offset, true);
display_data( display_gfx_arrow_down, 8, edit_line + 1, edit_offset * 8 + 4, false);
display_data(display_gfx_arrow_up, 8, edit_line - 1, edit_offset * 8 + 4, false);
display_chars(edit_char, edit_length, edit_line, edit_offset, true);
display_data(display_gfx_arrow_down, 8, edit_line + 1, edit_offset * 8 + 4, false);
display_menu_headline(interface_get_label_text(&interface_text_headline_time), true, 0);
}
void interface_datetime_start(void)
@ -164,12 +167,12 @@ void interface_datetime_start(void)
current_interface_datetime_state = INTERFACE_DATETIME_STATE_HOUR;
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_datetime_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_datetime_rht);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_datetime_mid);
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_datetime_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_datetime_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_datetime_dwn);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_datetime_set);
interface_register_command_callback(INTERFACE_COMMAND_RST, NULL);
interface_set_display_function(NULL);
interface_set_display_refresh_function(&interface_datetime_display);
ESP_LOGD(INTERFACE_LOG, "start datetime interface");
interface_set_display_function(&interface_datetime_display);
interface_set_display_refresh_function(&interface_datetime_display_refresh);
}

View File

@ -0,0 +1,148 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "display.h"
#include "display-gfx.h"
#if defined(CONFIG_ENA_INTERFACE_M5STICKC) || defined(CONFIG_ENA_INTERFACE_M5STICKC_PLUS)
#include "mpu6886.h"
#include "axp192.h"
#endif
#include "interface.h"
static bool runTask = true;
static TaskHandle_t debugTaskHandle = NULL;
void interface_debug_set(void)
{
runTask = false;
vTaskDelay(100 / portTICK_PERIOD_MS);
vTaskSuspend(debugTaskHandle);
interface_main_start();
}
void interface_debug_rst(void)
{
}
void interface_debug_lft(void)
{
runTask = false;
vTaskDelay(100 / portTICK_PERIOD_MS);
vTaskSuspend(debugTaskHandle);
interface_data_start();
}
void interface_debug_rht(void)
{
runTask = false;
vTaskDelay(100 / portTICK_PERIOD_MS);
vTaskSuspend(debugTaskHandle);
interface_info_start();
}
void interface_debug_mid(void)
{
}
void interface_debug_up(void)
{
}
void interface_debug_dwn(void)
{
}
void interface_debug_task(void *pvParameter)
{
#if defined(CONFIG_ENA_INTERFACE_M5STICKC) || defined(CONFIG_ENA_INTERFACE_M5STICKC_PLUS)
float ax = 0;
float ay = 0;
float az = 0;
float gx = 0;
float gy = 0;
float gz = 0;
#endif
while (1)
{
if (!interface_is_idle() && runTask)
{
#if defined(CONFIG_ENA_INTERFACE_M5STICKC) || defined(CONFIG_ENA_INTERFACE_M5STICKC_PLUS)
mpu6886_get_accel_data(&ax, &ay, &az);
mpu6886_get_gyro_data(&gx, &gy, &gz);
char data_chars[32];
sprintf(data_chars, "acc x:%3.2f", ax);
display_text_line(data_chars, 2, false);
sprintf(data_chars, "acc y:%3.2f", ay);
display_text_line(data_chars, 3, false);
sprintf(data_chars, "acc z:%3.2f", az);
display_text_line(data_chars, 4, false);
sprintf(data_chars, "gyr x:%3.2f", gx);
display_text_line(data_chars, 5, false);
sprintf(data_chars, "gyr y:%3.2f", gy);
display_text_line(data_chars, 6, false);
sprintf(data_chars, "gyr z:%3.2f", gz);
display_text_line(data_chars, 7, false);
float bat_v = axp192_get_bat_voltage();
sprintf(data_chars, "Battery: %.2f V", bat_v);
display_text_line(data_chars, 7, false);
#endif
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void interface_debug_start(void)
{
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_debug_rst);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_debug_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_debug_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_debug_rht);
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_debug_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_debug_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_debug_dwn);
interface_set_display_function(NULL);
display_menu_headline(interface_get_label_text(&interface_text_headline_debug), true, 0);
if (debugTaskHandle == NULL)
{
xTaskCreate(&interface_debug_task, "interface_debug_task", 4096 * 2, NULL, 5, &debugTaskHandle);
}
else
{
vTaskResume(debugTaskHandle);
}
runTask = true;
}

View File

@ -38,7 +38,11 @@ void interface_info_rst(void)
void interface_info_lft(void)
{
#if defined(CONFIG_ENA_INTERFACE_DEBUG)
interface_debug_start();
#else
interface_data_start();
#endif
}
void interface_info_rht(void)
@ -58,40 +62,69 @@ void interface_info_dwn(void)
{
}
int interface_info_num_offset(int num)
{
if (num < 10)
{
return 13;
}
else if (num < 100)
{
return 12;
}
else
{
return 11;
}
}
void interface_info_display(void)
{
char data_chars[10];
ena_exposure_summary_t *current_exposure_summary = ena_exposure_current_summary();
char data_chars[16];
display_menu_headline(interface_get_label_text(&interface_text_headline_info), true, 0);
display_text_line_column(interface_get_label_text(&interface_text_info_num_keys), 2, 1, false);
sprintf(data_chars, "%u", ena_storage_beacons_count());
display_text_line_column(data_chars, 2, 9, false);
int num = ena_storage_beacons_count();
sprintf(data_chars, "%u", num);
display_text_line_column(data_chars, 2, interface_info_num_offset(num), false);
ena_exposure_summary_t *current_exposure_summary = ena_exposure_current_summary();
display_text_line_column(interface_get_label_text(&interface_text_info_last_keys), 3, 1, false);
time_t current_timstamp;
time(&current_timstamp);
int max = ena_expore_check_find_min((uint32_t)current_timstamp);
int min = ena_expore_check_find_min((uint32_t)current_timstamp - 60 * 30);
int last30 = max - min;
if (last30 > 0)
{
sprintf(data_chars, "%d", last30);
display_text_line_column(data_chars, 3, interface_info_num_offset(last30), false);
}
display_text_line_column(interface_get_label_text(&interface_text_info_exp_days), 4, 1, false);
sprintf(data_chars, "%d", current_exposure_summary->days_since_last_exposure);
if (current_exposure_summary->days_since_last_exposure < 0)
int last = current_exposure_summary->days_since_last_exposure;
if (last >= 0)
{
display_text_line_column("/", 4, 12, false);
}
else
{
display_text_line_column(data_chars, 4, 12, false);
sprintf(data_chars, "%d", last);
display_text_line_column(data_chars, 4, interface_info_num_offset(last), false);
}
display_text_line_column(interface_get_label_text(&interface_text_info_exp_num), 5, 1, false);
sprintf(data_chars, "%d", current_exposure_summary->num_exposures);
display_text_line_column(data_chars, 5, 12, false);
display_text_line_column(data_chars, 5, interface_info_num_offset(current_exposure_summary->num_exposures), false);
display_text_line_column(interface_get_label_text(&interface_text_info_exp_max), 6, 1, false);
sprintf(data_chars, "%d", current_exposure_summary->max_risk_score);
display_text_line_column(data_chars, 6, 12, false);
display_text_line_column(data_chars, 6, interface_info_num_offset(current_exposure_summary->max_risk_score), false);
display_text_line_column(interface_get_label_text(&interface_text_info_exp_sum), 7, 1, false);
sprintf(data_chars, "%d", current_exposure_summary->risk_score_sum);
display_text_line_column(data_chars, 7, 12, false);
display_text_line_column(data_chars, 7, interface_info_num_offset(current_exposure_summary->risk_score_sum), false);
}
void interface_info_start(void)
@ -104,8 +137,6 @@ void interface_info_start(void)
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_info_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_info_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_info_dwn);
interface_set_display_function(&interface_info_display);
interface_set_display_refresh_function(NULL);
ESP_LOGD(INTERFACE_LOG, "start info interface");
interface_set_display_function(&interface_info_display);
}

View File

@ -76,7 +76,6 @@ void interface_input_set_char_set(void)
strcpy(current_char_set, char_set_uppercase);
current_char_index = strlen(current_char_set) - strlen(ret);
}
printf("current_char_set: %d %s\n", strlen(current_char_set), current_char_set);
}
void interface_input_set(void)
@ -152,7 +151,6 @@ void interface_input_mid(void)
}
current_char_index = 0;
current_text[current_cursor] = current_char_set[current_char_index];
printf("current_char_set: %d %s\n", strlen(current_char_set), current_char_set);
}
void interface_input_up(void)
@ -187,8 +185,8 @@ void interface_input_display(void)
{
// buttons
display_set_button( interface_get_label_text(&interface_text_button_cancel), true, false);
display_set_button( interface_get_label_text(&interface_text_button_ok), false, true);
display_set_button(interface_get_label_text(&interface_text_button_cancel), true, false);
display_set_button(interface_get_label_text(&interface_text_button_ok), false, true);
size_t start = 0;
uint8_t display_cursor = current_cursor + 1;
@ -198,26 +196,9 @@ void interface_input_display(void)
display_cursor = 14;
}
// arrow
if (current_cursor > 0)
{
display_data( display_gfx_arrow_left, 8, 2, 0, false);
}
else
{
display_data( display_gfx_clear, 8, 2, 0, false);
}
// bounday
display_text_line_column( "______________", 2, 1, false);
// arrow
if (current_cursor < current_limit)
{
display_data( display_gfx_arrow_right, 8, 2, 15 * 8, false);
}
else
{
display_data( display_gfx_clear, 8, 2, 15 * 8, false);
}
display_text_line_column("______________", 2, 1, false);
// text
size_t text_length = strlen(current_text);
if (strlen(current_text) > 14)
@ -231,14 +212,14 @@ void interface_input_display(void)
memcpy(&textdata[i * 8], display_gfx_font[(uint8_t)current_text[i + start] - 32], 8);
}
display_data( textdata, length, 2, 8, true);
display_data(textdata, length, 2, 8, true);
free(textdata);
// clear
display_clear_line( 0, false);
display_clear_line( 1, false);
display_clear_line( 3, false);
display_clear_line( 4, false);
display_clear_line(0, false);
display_clear_line(1, false);
display_clear_line(3, false);
display_clear_line(4, false);
uint8_t current_char = (uint8_t)current_char_set[current_char_index] - 32;
uint8_t prev_char = (uint8_t)current_char_set[current_char_index - 1] - 32;
@ -255,15 +236,32 @@ void interface_input_display(void)
}
// arrow
display_data( display_gfx_arrow_up, 8, 0, display_cursor * 8, false);
display_data(display_gfx_arrow_up, 8, 0, display_cursor * 8, false);
// upper char
display_data( display_gfx_font[prev_char], 8, 1, display_cursor * 8, false);
display_data(display_gfx_font[prev_char], 8, 1, display_cursor * 8, false);
// sel char
display_data( display_gfx_font[current_char], 8, 2, display_cursor * 8, false);
display_data(display_gfx_font[current_char], 8, 2, display_cursor * 8, false);
// lower char
display_data( display_gfx_font[next_char], 8, 3, display_cursor * 8, false);
display_data(display_gfx_font[next_char], 8, 3, display_cursor * 8, false);
// arrow
display_data( display_gfx_arrow_down, 8, 4, display_cursor * 8, false);
display_data(display_gfx_arrow_down, 8, 4, display_cursor * 8, false);
if (current_cursor > 0)
{
display_data(display_gfx_arrow_left, 8, 2, 0, false);
}
else
{
display_data(display_gfx_clear, 8, 2, 0, false);
}
if (current_cursor < current_limit)
{
display_data(display_gfx_arrow_right, 8, 2, 15 * 8, false);
}
else
{
display_data(display_gfx_clear, 8, 2, 15 * 8, false);
}
}
void interface_input_set_text(char *text)
@ -313,8 +311,7 @@ void interface_input(interface_text_callback callback_rst, interface_text_callba
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_input_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_input_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_input_dwn);
interface_register_command_callback(INTERFACE_COMMAND_RST_LONG, &interface_input_mid);
interface_set_display_function(&interface_input_display);
interface_set_display_refresh_function(NULL);
ESP_LOGD(INTERFACE_LOG, "start input interface");
}

View File

@ -49,6 +49,7 @@ void interface_init_label(void)
interface_text_settings_timezone.text[EN] = "UTC:";
interface_text_info_num_keys.text[EN] = "Seen:";
interface_text_info_last_keys.text[EN] = "<=30m:";
interface_text_info_exp_days.text[EN] = "Last Exp:";
interface_text_info_exp_num.text[EN] = "Num Exp:";
interface_text_info_exp_max.text[EN] = "Score:";
@ -111,6 +112,7 @@ void interface_init_label(void)
interface_text_settings_timezone.text[DE] = "GMT:";
interface_text_info_num_keys.text[DE] = "Gesehen:";
interface_text_info_last_keys.text[DE] = "<=30m:";
interface_text_info_exp_days.text[DE] = "letz. Exp:";
interface_text_info_exp_num.text[DE] = "Anz. Exp:";
interface_text_info_exp_max.text[DE] = "Score:";

View File

@ -51,6 +51,7 @@ void interface_main_display(void)
// status unknown if no update or last update older than two days
if (last_update == 0 || ((current_timstamp - last_update) / (60 * 60 * 24)) > 2)
{
display_set_color(YELLOW);
display_data(display_gfx_question[0], 24, 0, 12, false);
display_data(display_gfx_question[1], 24, 1, 12, false);
display_data(display_gfx_question[2], 24, 2, 12, false);
@ -58,18 +59,23 @@ void interface_main_display(void)
}
else if (current_exposure_summary->max_risk_score < 100)
{
display_set_color(GREEN);
display_data(display_gfx_smile[0], 24, 0, 12, false);
display_data(display_gfx_smile[1], 24, 1, 12, false);
display_data(display_gfx_smile[2], 24, 2, 12, false);
display_data(display_gfx_smile[3], 24, 3, 12, false);
display_set_color(WHITE);
}
else
{
display_set_color(RED);
display_data(display_gfx_sad[0], 24, 0, 12, false);
display_data(display_gfx_sad[1], 24, 1, 12, false);
display_data(display_gfx_sad[2], 24, 2, 12, false);
display_data(display_gfx_sad[3], 24, 3, 12, false);
display_set_color(WHITE);
}
// clock icon
display_data(display_gfx_clock, 8, 4, 8, false);
@ -78,9 +84,9 @@ void interface_main_display(void)
last_update_tm->tm_hour = last_update_tm->tm_hour + (interface_get_timezone_offset()) % 24;
sprintf(time_buffer, "%02d %s %02d:%02d",
last_update_tm->tm_mday,
sprintf(time_buffer, "%s %02d %02d:%02d",
interface_get_label_text(&interface_texts_month[last_update_tm->tm_mon]),
last_update_tm->tm_mday,
last_update_tm->tm_hour,
last_update_tm->tm_min);
@ -89,6 +95,8 @@ void interface_main_display(void)
display_text_line_column(time_buffer, 4, 3, false);
}
display_set_color(WHITE);
// buttons
display_set_button(interface_get_label_text(&interface_text_button_menu), true, false);
display_set_button(interface_get_label_text(&interface_text_button_report), false, true);
@ -124,7 +132,6 @@ void interface_main_display_refresh(void)
void interface_main_start(void)
{
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_main_rst);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_main_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, NULL);
@ -135,7 +142,4 @@ void interface_main_start(void)
interface_set_display_function(&interface_main_display);
interface_set_display_refresh_function(&interface_main_display_refresh);
interface_main_display();
ESP_LOGD(INTERFACE_LOG, "start main interface");
}

View File

@ -48,10 +48,10 @@ static int current_report_status = INTERFACE_REPORT_STATUS_NONE;
void interface_report_display(void)
{
display_clear();
if (current_report_status == INTERFACE_REPORT_STATUS_NONE)
{
display_menu_headline(interface_get_label_text(&interface_text_headline_tan), false, 0);
// buttons
display_set_button(interface_get_label_text(&interface_text_button_cancel), true, false);
if (current_cursor == 9)
@ -59,24 +59,6 @@ void interface_report_display(void)
display_set_button(interface_get_label_text(&interface_text_button_ok), false, true);
}
if (current_cursor > 0)
{
display_data(display_gfx_arrow_left, 8, 3, 8, false);
}
else
{
display_data(display_gfx_clear, 8, 3, 8, false);
}
if (current_cursor < 9)
{
display_data(display_gfx_arrow_right, 8, 3, 112, false);
}
else
{
display_data(display_gfx_clear, 8, 3, 112, false);
}
display_clear_line(2, false);
display_clear_line(4, false);
@ -123,25 +105,45 @@ void interface_report_display(void)
display_data(display_gfx_arrow_down, 8, 4, current_cursor * 8 + offset * 8, false);
display_chars(&current_tan[current_cursor], 1, 3, current_cursor + offset, false);
if (current_cursor > 0)
{
display_data(display_gfx_arrow_left, 8, 3, 8, false);
}
else
{
display_data(display_gfx_clear, 8, 3, 8, false);
}
if (current_cursor < 9)
{
display_data(display_gfx_arrow_right, 8, 3, 112, false);
}
else
{
display_data(display_gfx_clear, 8, 3, 112, false);
}
}
else if (current_report_status == INTERFACE_REPORT_STATUS_PENDING)
{
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
display_clear();
display_text_line_column(interface_get_label_text(&interface_text_report_pending), 4, 1, false);
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
}
else if (current_report_status == INTERFACE_REPORT_STATUS_SUCCESS)
{
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
display_clear();
display_text_line_column(interface_get_label_text(&interface_text_report_success), 3, 1, false);
display_set_button(interface_get_label_text(&interface_text_button_ok), false, true);
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
}
else if (current_report_status == INTERFACE_REPORT_STATUS_FAIL)
{
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
display_clear();
display_text_line_column(interface_get_label_text(&interface_text_report_fail), 3, 1, false);
display_set_button(interface_get_label_text(&interface_text_button_back), true, false);
display_set_button(interface_get_label_text(&interface_text_button_ok), false, true);
display_menu_headline(interface_get_label_text(&interface_text_headline_report), false, 0);
}
}
@ -306,8 +308,7 @@ void interface_report_start(void)
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_report_rht);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_report_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_report_dwn);
interface_set_display_function(&interface_report_display);
interface_set_display_refresh_function(NULL);
interface_register_command_callback(INTERFACE_COMMAND_RST_LONG, &interface_report_mid);
ESP_LOGD(INTERFACE_LOG, "start report interface");
interface_set_display_function(&interface_report_display);
}

View File

@ -50,10 +50,6 @@ void interface_settings_set(void)
interface_main_start();
}
void interface_settings_rst(void)
{
}
void interface_settings_lft(void)
{
interface_info_start();
@ -191,15 +187,13 @@ void interface_settings_start(void)
{
current_interface_settings_state = INTERFACE_SETTINGS_LOCALE;
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_settings_rst);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_settings_mid);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_settings_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_settings_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_settings_rht);
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_settings_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_settings_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_settings_dwn);
interface_set_display_function(&interface_settings_display);
interface_set_display_refresh_function(NULL);
ESP_LOGD(INTERFACE_LOG, "start settings interface");
}

View File

@ -22,6 +22,7 @@
#include "display.h"
#include "display-gfx.h"
#include "wifi-controller.h"
#include "ena-eke-proxy.h"
#include "interface.h"
@ -70,12 +71,14 @@ void interface_wifi_rht(void)
{
interface_datetime_start();
}
void interface_wifi_mid(void)
{
memset(&current_wifi_config, 0, sizeof(wifi_config_t));
memcpy(current_wifi_config.sta.ssid, ap_info[ap_selected].ssid, strlen((char *)ap_info[ap_selected].ssid));
interface_input(&interface_wifi_input_rst, &interface_wifi_input_set, 64);
}
void interface_wifi_up(void)
{
ap_selected--;
@ -120,6 +123,7 @@ void interface_wifi_display_refresh(void)
{
if (ap_count > 0)
{
ena_eke_proxy_resume();
display_clear_line(2, false);
display_clear_line(4, false);
display_clear_line(6, false);
@ -132,6 +136,10 @@ void interface_wifi_display_refresh(void)
{
display_data(display_gfx_arrow_right, 8, i * 2 + 2, 8, false);
}
else
{
display_data(display_gfx_clear, 8, i * 2 + 2, 8, false);
}
if (sizeof(ap_info[i].ssid) > 0)
{
@ -171,18 +179,17 @@ void interface_wifi_start(void)
interface_register_command_callback(INTERFACE_COMMAND_MID, &interface_wifi_mid);
interface_register_command_callback(INTERFACE_COMMAND_UP, &interface_wifi_up);
interface_register_command_callback(INTERFACE_COMMAND_DWN, &interface_wifi_dwn);
interface_register_command_callback(INTERFACE_COMMAND_RST, NULL);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_wifi_mid);
interface_set_display_function(&interface_wifi_display);
interface_set_display_refresh_function(&interface_wifi_display_refresh);
interface_wifi_display();
ESP_LOGD(INTERFACE_LOG, "start wifi interface and scanning");
memset(ap_info, 0, sizeof(ap_info));
ap_count = 0;
ap_index = 0;
ap_selected = 0;
ena_eke_proxy_pause();
wifi_controller_scan(ap_info, &ap_count);
}

View File

@ -29,6 +29,12 @@ static interface_display_function current_display_refresh_function;
static TimerHandle_t interface_idle_timer;
static bool interface_idle = false;
static bool busy = false;
bool interface_is_idle(void)
{
return interface_idle;
}
void interface_register_command_callback(interface_command_t command, interface_command_callback callback)
{
@ -37,14 +43,26 @@ void interface_register_command_callback(interface_command_t command, interface_
void interface_set_display_function(interface_display_function display_function)
{
busy = true;
display_clear();
current_display_refresh_function = NULL;
current_display_function = display_function;
if (current_display_function != NULL)
{
(*current_display_function)();
}
busy = false;
}
void interface_set_display_refresh_function(interface_display_function display_function)
{
display_clear();
busy = true;
current_display_refresh_function = display_function;
if (current_display_function != NULL)
{
(*current_display_function)();
}
busy = false;
}
void interface_execute_command(interface_command_t command)
@ -53,19 +71,14 @@ void interface_execute_command(interface_command_t command)
{
xTimerReset(interface_idle_timer, 0);
(*command_callbacks[command])();
if (current_display_function != NULL || current_display_refresh_function != NULL)
if (!busy)
{
display_clear();
if (current_display_refresh_function != NULL)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
(*current_display_refresh_function)();
}
busy = true;
if (current_display_function != NULL)
{
vTaskDelay(10 / portTICK_PERIOD_MS);
(*current_display_function)();
}
busy = false;
}
}
else if (interface_idle && command == INTERFACE_COMMAND_SET)
@ -82,11 +95,15 @@ void interface_display_task(void *pvParameter)
while (1)
{
if (current_display_refresh_function != NULL)
if (!interface_idle && !busy && current_display_refresh_function != NULL)
{
(*current_display_refresh_function)();
vTaskDelay(500 / portTICK_PERIOD_MS);
}
else
{
vTaskDelay(100 / portTICK_PERIOD_MS);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
@ -101,7 +118,7 @@ void interface_start(void)
interface_idle_timer = xTimerCreate(
"interface_idle",
(15 * 1000) / portTICK_PERIOD_MS,
(INTERFACE_IDLE_SECONDS * 1000) / portTICK_PERIOD_MS,
false,
NULL,
interface_idle_callback);
@ -112,10 +129,18 @@ void interface_start(void)
display_start();
display_clear();
for (int i = 0; i < 8; i++)
{
display_data(display_gfx_logo[i], 64, i, 32, false);
}
xTaskCreate(&interface_display_task, "interface_display_task", 4096, NULL, 5, NULL);
}
void interface_flipped(bool flipped)
{
busy = true;
vTaskDelay(500 / portTICK_PERIOD_MS);
display_clear();
display_flipped(flipped);
if (current_display_function != NULL)
{
(*current_display_function)();
}
busy = false;
}

View File

@ -28,6 +28,11 @@
#define INTERFACE_NUM_LOCALE 2
#define INTERFACE_IDLE_SECONDS CONFIG_ENA_INTERFACE_IDLE_TIME
#define INTERFACE_INPUT_TICKS_MS 20
#define INTERFACE_LONG_STATE_SECONDS 1.0
/**
* @brief available commands
*/
@ -40,6 +45,8 @@ typedef enum
INTERFACE_COMMAND_LFT,
INTERFACE_COMMAND_DWN,
INTERFACE_COMMAND_UP,
INTERFACE_COMMAND_RST_LONG,
INTERFACE_COMMAND_SET_LONG,
INTERFACE_COMMANDS_SIZE,
} interface_command_t;
@ -80,6 +87,7 @@ interface_label_t interface_text_settings_locales[INTERFACE_NUM_LOCALE];
interface_label_t interface_text_settings_timezone;
interface_label_t interface_text_info_num_keys;
interface_label_t interface_text_info_last_keys;
interface_label_t interface_text_info_exp_update;
interface_label_t interface_text_info_exp_days;
interface_label_t interface_text_info_exp_num;
@ -116,6 +124,13 @@ typedef void (*interface_display_function)(void);
*/
typedef void (*interface_text_callback)(char *text, uint8_t cursor);
/**
* @brief is interface in idle mode
*
* @return if interface is idle
*/
bool interface_is_idle(void);
/**
* @brief init label
*/
@ -194,6 +209,13 @@ void interface_set_display_refresh_function(interface_display_function display_f
*/
void interface_start(void);
/**
* @brief set interface flipped or not
*
* @param[in] on true interface is flipped
*/
void interface_flipped(bool flipped);
/**
* @brief start delete data interface
*/
@ -229,6 +251,11 @@ void interface_settings_start(void);
*/
void interface_info_start(void);
/**
* @brief start debug interface
*/
void interface_debug_start(void);
/**
* @brief start interface for input
*

View File

@ -0,0 +1,7 @@
idf_component_register(
SRCS
"axp192.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
i2c-main
)

View File

@ -0,0 +1,483 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <time.h>
#include "driver/i2c.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "i2c-main.h"
#include "axp192.h"
void axp192_write_byte(uint8_t addr, uint8_t data)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
// Begin the I2C comm with AXP192_ADDRESS's address (SLA+Write)
i2c_master_write_byte(cmd, (AXP192_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, addr, true);
i2c_master_write_byte(cmd, data, true);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}
void axp192_read_buff(uint8_t addr, uint8_t size, uint8_t *buff)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// Send register address
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (AXP192_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, addr, true);
// Receive data
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (AXP192_ADDRESS << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, buff, size, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}
uint8_t axp192_read_8bit(uint8_t addr)
{
uint8_t data;
axp192_read_buff(addr, 1, &data);
return data;
}
uint16_t axp192_read_12bit(uint8_t addr)
{
uint16_t data = 0;
uint8_t buf[2];
axp192_read_buff(addr, 2, buf);
data = ((buf[0] << 4) + buf[1]); //
return data;
}
uint16_t axp192_read_13bit(uint8_t addr)
{
uint16_t data = 0;
uint8_t buf[2];
axp192_read_buff(addr, 2, buf);
data = ((buf[0] << 5) + buf[1]); //
return data;
}
uint16_t axp192_read_16bit(uint8_t addr)
{
uint16_t data = 0;
uint8_t buf[2];
axp192_read_buff(addr, 2, buf);
data = ((buf[0] << 8) + buf[1]);
return data;
}
uint32_t axp192_read_24bit(uint8_t addr)
{
uint32_t data = 0;
uint8_t buf[3];
axp192_read_buff(addr, 3, buf);
data = ((buf[0] << 16) + (buf[1] << 8) + buf[2]);
return data;
}
uint32_t axp192_read_32bit(uint8_t addr)
{
uint32_t data = 0;
uint8_t buf[4];
axp192_read_buff(addr, 4, buf);
data = ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]);
return data;
}
void axp192_screen_breath(uint8_t brightness)
{
if (brightness > 12)
{
brightness = 12;
}
uint8_t buf = axp192_read_8bit(0x28);
axp192_write_byte(0x28, ((buf & 0x0f) | (brightness << 4)));
}
void axp192_start(void)
{
if (!i2c_is_initialized())
{
i2c_main_init();
}
// Set LDO2 & LDO3(ST7789_LED & TFT) 3.0V
axp192_write_byte(0x28, 0xcc);
// Set ADC sample rate to 200hz
axp192_write_byte(0x84, 0xF2);
// Set ADC to All Enable
axp192_write_byte(0x82, 0xff);
// Bat charge voltage to 4.2, Current 100MA
axp192_write_byte(0x33, 0xc0);
// Enable Bat,ACIN,VBUS,APS adc
axp192_write_byte(0x82, 0xff);
// Enable Ext, LDO2, LDO3, DCDC1
axp192_write_byte(0x12, axp192_read_8bit(0x12) | 0x4D);
// 128ms power on, 4s power off
axp192_write_byte(0x36, 0x0C);
// Set RTC voltage to 3.3V
axp192_write_byte(0x91, 0xF0);
// Set GPIO0 to LDO
axp192_write_byte(0x90, 0x02);
// Disable vbus hold limit
axp192_write_byte(0x30, 0x80);
// Set temperature protection
axp192_write_byte(0x39, 0xfc);
// Enable RTC BAT charge
axp192_write_byte(0x35, 0xa2);
// Enable bat detection
axp192_write_byte(0x32, 0x46);
}
bool axp192_get_bat_state()
{
if (axp192_read_8bit(0x01) | 0x20)
return true;
else
return false;
}
//---------coulombcounter_from_here---------
//enable: void EnableCoulombcounter(void);
//disable: void DisableCOulombcounter(void);
//stop: void StopCoulombcounter(void);
//clear: void ClearCoulombcounter(void);
//get charge data: uint32_t GetCoulombchargedata(void);
//get discharge data: uint32_t GetCoulombdischargedata(void);
//get coulomb val affter calculation: float GetCoulombdata(void);
//------------------------------------------
void axp192_enable_coulombcounter(void)
{
axp192_write_byte(0xB8, 0x80);
}
void axp192_disable_coulombcounter(void)
{
axp192_write_byte(0xB8, 0x00);
}
void axp192_stop_coulombcounter(void)
{
axp192_write_byte(0xB8, 0xC0);
}
void axp192_clear_coulombcounter(void)
{
axp192_write_byte(0xB8, 0xA0);
}
uint32_t axp192_get_coulombcharge_data(void)
{
return axp192_read_32bit(0xB0);
}
uint32_t axp192_get_coulombdischarge_data(void)
{
return axp192_read_32bit(0xB4);
}
float axp192_get_coulomb_data(void)
{
uint32_t coin = 0;
uint32_t coout = 0;
coin = axp192_get_coulombcharge_data();
coout = axp192_get_coulombdischarge_data();
//c = 65536 * current_LSB * (coin - coout) / 3600 / ADC rate
//Adc rate can be read from 84H ,change this variable if you change the ADC reate
float ccc = 65536 * 0.5 * (coin - coout) / 3600.0 / 25.0;
return ccc;
}
//----------coulomb_end_at_here----------
uint16_t axp192_get_Vbatdata(void)
{
uint16_t vbat = 0;
uint8_t buf[2];
axp192_read_buff(0x78, 2, buf);
vbat = ((buf[0] << 4) + buf[1]); // V
return vbat;
}
uint16_t axp192_get_Vindata(void)
{
uint16_t vin = 0;
uint8_t buf[2];
axp192_read_buff(0x56, 2, buf);
vin = ((buf[0] << 4) + buf[1]); // V
return vin;
}
uint16_t axp192_get_Iindata(void)
{
uint16_t iin = 0;
uint8_t buf[2];
axp192_read_buff(0x58, 2, buf);
iin = ((buf[0] << 4) + buf[1]);
return iin;
}
uint16_t axp192_get_Vusbindata(void)
{
uint16_t vin = 0;
uint8_t buf[2];
axp192_read_buff(0x5a, 2, buf);
vin = ((buf[0] << 4) + buf[1]); // V
return vin;
}
uint16_t axp192_get_Iusbindata(void)
{
uint16_t iin = 0;
uint8_t buf[2];
axp192_read_buff(0x5C, 2, buf);
iin = ((buf[0] << 4) + buf[1]);
return iin;
}
uint16_t axp192_get_Ichargedata(void)
{
uint16_t icharge = 0;
uint8_t buf[2];
axp192_read_buff(0x7A, 2, buf);
icharge = (buf[0] << 5) + buf[1];
return icharge;
}
uint16_t axp192_get_Idischargedata(void)
{
uint16_t idischarge = 0;
uint8_t buf[2];
axp192_read_buff(0x7C, 2, buf);
idischarge = (buf[0] << 5) + buf[1];
return idischarge;
}
uint16_t axp192_get_Tempdata(void)
{
uint16_t temp = 0;
uint8_t buf[2];
axp192_read_buff(0x5e, 2, buf);
temp = ((buf[0] << 4) + buf[1]);
return temp;
}
uint32_t axp192_get_Powerbatdata(void)
{
uint32_t power = 0;
uint8_t buf[3];
axp192_read_buff(0x70, 2, buf);
power = (buf[0] << 16) + (buf[1] << 8) + buf[2];
return power;
}
uint16_t axp192_get_Vapsdata(void)
{
uint16_t vaps = 0;
uint8_t buf[2];
axp192_read_buff(0x7e, 2, buf);
vaps = ((buf[0] << 4) + buf[1]);
return vaps;
}
void axp192_set_sleep(void)
{
uint8_t buf = axp192_read_8bit(0x31);
buf = (1 << 3) | buf;
axp192_write_byte(0x31, buf);
axp192_write_byte(0x90, 0x00);
axp192_write_byte(0x12, 0x09);
axp192_write_byte(0x12, 0x00);
}
uint8_t axp192_get_warning_leve(void)
{
uint8_t buf = axp192_read_8bit(0x47);
return (buf & 0x01);
}
// -- sleep
void axp192_deep_sleep(uint64_t time_in_us)
{
axp192_set_sleep();
if (time_in_us > 0)
{
esp_sleep_enable_timer_wakeup(time_in_us);
}
else
{
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
}
(time_in_us == 0) ? esp_deep_sleep_start() : esp_deep_sleep(time_in_us);
}
void axp192_light_sleep(uint64_t time_in_us)
{
axp192_set_sleep();
if (time_in_us > 0)
{
esp_sleep_enable_timer_wakeup(time_in_us);
}
else
{
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
}
esp_light_sleep_start();
}
// 0 not press, 0x01 long press, 0x02 press
uint8_t axp192_get_btn_press()
{
uint8_t state = axp192_read_8bit(0x46);
if (state)
{
axp192_write_byte(0x46, 0x03);
}
return state;
}
uint8_t axp192_get_warning_level(void)
{
return axp192_read_8bit(0x47) & 0x01;
}
float axp192_get_bat_voltage()
{
float ADCLSB = 1.1 / 1000.0;
uint16_t Redata = axp192_read_12bit(0x78);
return Redata * ADCLSB;
}
float axp192_get_bat_current()
{
float ADCLSB = 0.5;
uint16_t CurrentIn = axp192_read_13bit(0x7A);
uint16_t CurrentOut = axp192_read_13bit(0x7C);
return (CurrentIn - CurrentOut) * ADCLSB;
}
float axp192_get_vin_voltage()
{
float ADCLSB = 1.7 / 1000.0;
uint16_t Redata = axp192_read_12bit(0x56);
return Redata * ADCLSB;
}
float axp192_get_vin_current()
{
float ADCLSB = 0.625;
uint16_t Redata = axp192_read_12bit(0x58);
return Redata * ADCLSB;
}
float axp192_get_vbus_voltage()
{
float ADCLSB = 1.7 / 1000.0;
uint16_t Redata = axp192_read_12bit(0x5A);
return Redata * ADCLSB;
}
float axp192_get_vbus_current()
{
float ADCLSB = 0.375;
uint16_t Redata = axp192_read_12bit(0x5C);
return Redata * ADCLSB;
}
float axp192_get_temp()
{
float ADCLSB = 0.1;
const float OFFSET_DEG_C = -144.7;
uint16_t Redata = axp192_read_12bit(0x5E);
return OFFSET_DEG_C + Redata * ADCLSB;
}
float axp192_get_bat_power()
{
float VoltageLSB = 1.1;
float CurrentLCS = 0.5;
uint32_t Redata = axp192_read_24bit(0x70);
return VoltageLSB * CurrentLCS * Redata / 1000.0;
}
float axp192_get_bat_charge_current()
{
float ADCLSB = 0.5;
uint16_t Redata = axp192_read_12bit(0x7A);
return Redata * ADCLSB;
}
float axp192_get_aps_voltage()
{
float ADCLSB = 1.4 / 1000.0;
uint16_t Redata = axp192_read_12bit(0x7E);
return Redata * ADCLSB;
}
float axp192_get_bat_coulomb_input()
{
uint32_t Redata = axp192_read_32bit(0xB0);
return Redata * 65536 * 0.5 / 3600 / 25.0;
}
float axp192_get_bat_coulomb_out()
{
uint32_t Redata = axp192_read_32bit(0xB4);
return Redata * 65536 * 0.5 / 3600 / 25.0;
}
void axp192_set_coulomb_clear()
{
axp192_write_byte(0xB8, 0x20);
}
void axp192_set_ldo2(bool state)
{
uint8_t buf = axp192_read_8bit(0x12);
if (state == true)
buf = (1 << 2) | buf;
else
buf = ~(1 << 2) & buf;
axp192_write_byte(0x12, buf);
}

View File

@ -0,0 +1,66 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _PMW_AXP192_H_
#define _PWM_AXP192_H_
#include "stdio.h"
#define AXP192_ADDRESS 0x34
void axp192_start(void);
void axp192_screen_breath(uint8_t brightness);
bool axp192_get_bat_state();
void axp192_enable_coulombcounter(void);
void axp192_disable_coulombcounter(void);
void axp192_stop_coulombcounter(void);
void axp192_clear_coulombcounter(void);
uint32_t axp192_get_coulombcharge_data(void);
uint32_t axp192_get_coulombdischarge_data(void);
float axp192_get_coulomb_data(void);
uint8_t axp192_get_btn_press(void);
// -- sleep
void axp192_set_sleep(void);
void axp192_deep_sleep(uint64_t time_in_us);
void axp192_light_sleep(uint64_t time_in_us);
uint8_t axp192_get_warning_leve(void);
float axp192_get_bat_voltage();
float axp192_get_bat_current();
float axp192_get_vin_voltage();
float axp192_get_vin_current();
float axp192_get_vbus_voltage();
float axp192_get_vbus_current();
float axp192_get_temp();
float axp192_get_bat_power();
float axp192_get_bat_charge_current();
float axp192_get_aps_voltage();
float axp192_get_bat_coulomb_input();
float axp192_get_bat_coulomb_out();
uint8_t axp192_get_warning_level(void);
void axp192_set_coulomb_clear();
void axp192_set_ldo2(bool state);
void axp192_write_byte(uint8_t addr, uint8_t data);
uint8_t axp192_read_8bit(uint8_t addr);
uint16_t axp192_read_12bit(uint8_t addr);
uint16_t axp192_read_13bit(uint8_t addr);
uint16_t axp192_read_16bit(uint8_t addr);
uint32_t axp192_read_24bit(uint8_t addr);
uint32_t axp192_read_32bit(uint8_t addr);
void axp192_read_buff(uint8_t addr, uint8_t size, uint8_t *buff);
#endif

View File

@ -0,0 +1,8 @@
idf_component_register(
SRCS
"bm8563.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
rtc
i2c-main
)

View File

@ -0,0 +1,112 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <time.h>
#include "driver/i2c.h"
#include "esp_log.h"
#include "rtc.h"
#include "i2c-main.h"
#include "bm8563.h"
uint8_t bm8563_dec2bcd(uint8_t value)
{
return (((value / 10) << 4) | (value % 10));
}
uint8_t bm8563_bcd2dec(uint8_t value)
{
return (((value >> 4) * 10) + (value & 0x0f));
}
/**
* @brief Read time
*/
void rtc_get_time(struct tm *time)
{
if (!i2c_is_initialized())
{
i2c_main_init();
}
uint8_t data[7];
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BM8563_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, BM8563_SECONDS, true);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BM8563_ADDRESS << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, data, 7, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
time->tm_sec = bm8563_bcd2dec(data[0] & 0b01111111);
time->tm_min = bm8563_bcd2dec(data[1] & 0b01111111);
time->tm_hour = bm8563_bcd2dec(data[2] & 0b00111111);
time->tm_mday = bm8563_bcd2dec(data[3] & 0b00111111);
time->tm_wday = bm8563_bcd2dec(data[4] & 0b00000111);
time->tm_mon = bm8563_bcd2dec(data[5] & 0b00011111) - 1;
if (data[5] & BM8563_CENTURY_BIT)
{
time->tm_year = bm8563_bcd2dec(data[6] & 0b11111111) + 100;
}
else
{
time->tm_year = bm8563_bcd2dec(data[6] & 0b01111111);
}
time->tm_isdst = 0;
mktime(time);
}
/**
* @brief Write time
*/
void rtc_set_time(struct tm *time)
{
if (!i2c_is_initialized())
{
i2c_main_init();
}
uint8_t data[7] = {0};
data[0] = bm8563_dec2bcd(time->tm_sec) & 0b01111111;
data[1] = bm8563_dec2bcd(time->tm_min) & 0b01111111;
data[2] = bm8563_dec2bcd(time->tm_hour) & 0b00111111;
data[3] = bm8563_dec2bcd(time->tm_mday) & 0b00111111;
data[4] = bm8563_dec2bcd(time->tm_wday) & 0b00000111;
data[5] = bm8563_dec2bcd(time->tm_mon + 1) & 0b00011111;
if (time->tm_year > 100)
{
data[5] |= BM8563_CENTURY_BIT;
}
data[6] = bm8563_dec2bcd(time->tm_year % 100) & 0b11111111;
i2c_cmd_handle_t cmd;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BM8563_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, BM8563_SECONDS, true);
i2c_master_write(cmd, data, 7, true);
i2c_master_stop(cmd);
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS));
i2c_cmd_link_delete(cmd);
}

View File

@ -0,0 +1,80 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @file
*
* @brief I2C driver for BM8563 RTC
*
*/
#ifndef _RTC_BM8562_H_
#define _RTC_BM8562_H_
#include "stdio.h"
#include <time.h>
#define BM8563_ADDRESS 0x51
#define BM8563_CONTROL_STATUS1 0x00
#define BM8563_TESTC 0b00001000
#define BM8563_STOP 0b00100000
#define BM8563_TEST1 0b10000000
#define BM8563_CONTROL_STATUS2 0x01
#define BM8563_TIE 0b00000001
#define BM8563_AIE 0b00000010
#define BM8563_TF 0b00000100
#define BM8563_AF 0b00001000
#define BM8563_TI_TP 0b00010000
#define BM8563_SECONDS 0x02
#define BM8563_MINUTES 0x03
#define BM8563_HOURS 0x04
#define BM8563_DAY 0x05
#define BM8563_WEEKDAY 0x06
#define BM8563_MONTH 0x07
#define BM8563_YEAR 0x08
#define BM8563_TIME_SIZE 0x07
#define BM8563_CENTURY_BIT 0b10000000
#define BM8563_MINUTE_ALARM 0x09
#define BM8563_HOUR_ALARM 0x0a
#define BM8563_DAY_ALARM 0x0b
#define BM8563_WEEKDAY_ALARM 0x0c
#define BM8563_ALARM_DISABLE 0b10000000
#define BM8563_ALARM_NONE 0xff
#define BM8563_ALARM_SIZE 0x04
#define BM8563_TIMER_CONTROL 0x0e
#define BM8563_TIMER_ENABLE 0b10000000
#define BM8563_TIMER_4_096KHZ 0b00000000
#define BM8563_TIMER_64HZ 0b00000001
#define BM8563_TIMER_1HZ 0b00000010
#define BM8563_TIMER_1_60HZ 0b00000011
#define BM8563_TIMER 0x0f
#define BM8563_ALARM_SET 0x0900
#define BM8563_ALARM_READ 0x0901
#define BM8563_CONTROL_STATUS1_READ 0x0000
#define BM8563_CONTROL_STATUS1_WRITE 0x0001
#define BM8563_CONTROL_STATUS2_READ 0x0100
#define BM8563_CONTROL_STATUS2_WRITE 0x0101
#define BM8563_TIMER_CONTROL_READ 0x0e00
#define BM8563_TIMER_CONTROL_WRITE 0x0e01
#define BM8563_TIMER_READ 0x0f00
#define BM8563_TIMER_WRITE 0x0f01
/* Status codes. */
#define BM8563_ERROR_NOTTY (-1)
#define BM8563_OK (0x00)
#define BM8563_ERR_LOW_VOLTAGE (0x80)
#endif

View File

@ -1,9 +0,0 @@
menu "WiFi STA"
config WIFI_STA_SSID
string "Wifi SSID"
config WIFI_STA_PASSWORD
string "Wifi Password"
endmenu

View File

@ -27,15 +27,20 @@
#include "ena-bluetooth-advertise.h"
#include "ena-bluetooth-scan.h"
#include "ena-eke-proxy.h"
#include "ds3231.h"
#include "ssd1306.h"
#include "interface.h"
#include "button-input.h"
#include "rtc.h"
#include "wifi-controller.h"
#include "sdkconfig.h"
#ifdef CONFIG_ENA_INTERFACE_CUSTOM
#include "button-input.h"
#endif
#if defined(CONFIG_ENA_INTERFACE_M5STICKC) || defined(CONFIG_ENA_INTERFACE_M5STICKC_PLUS)
#include "m5-input.h"
#endif
void time_sync_notification_cb(struct timeval *tv)
{
time_t time = (time_t)tv->tv_sec;
@ -49,6 +54,7 @@ void app_main(void)
{
// debug only own LOG TAGs
esp_log_level_set("*", ESP_LOG_WARN);
esp_log_level_set("wifi", ESP_LOG_ERROR);
esp_log_level_set(ENA_LOG, ESP_LOG_DEBUG);
esp_log_level_set(ENA_BEACON_LOG, ESP_LOG_INFO);
esp_log_level_set(ENA_ADVERTISE_LOG, ESP_LOG_INFO);
@ -83,7 +89,13 @@ void app_main(void)
interface_main_start();
// start button input
#if defined(CONFIG_ENA_INTERFACE_CUSTOM)
button_input_start();
#endif
#if defined(CONFIG_ENA_INTERFACE_M5STICKC) || defined(CONFIG_ENA_INTERFACE_M5STICKC_PLUS)
m5_input_start();
#endif
wifi_controller_reconnect(NULL);