componeent structure, preparation for component branch

This commit is contained in:
Lurkars 2020-09-29 19:58:01 +02:00
parent b473e88be1
commit 43ecb0a42e
45 changed files with 998 additions and 9747 deletions

View File

@ -3,7 +3,7 @@
Implementation of contact tracing with the Covid-19 Exposure Notification API by Apple and Google on an ESP32 (with [ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/index.html)).
More information about the Covid-19 Exposure Notification at [Apple](https://www.apple.com/covid19/contacttracing/) and [Google](https://www.google.com/covid19/exposurenotifications/). This is fully compatible with the official API and is meant for people without smartphone or without access to Apples/Googles implementation.
The main source (the Exposure Notification API) is a separate module in [**components/ena**](components/ena).
The main source (the Exposure Notification API) is a separate branch in [**component**](https://github.com/Lurkars/esp-ena/tree/component).
This implementation fully covers the BLE part including the cryptography specifications needed and the exposure check.
@ -130,38 +130,45 @@ The ena module contains the main functions of eps-ena with bluetooth scanning an
* *ena-storage* storage part to store own TEKs and beacons
* *ena-bluetooth-scan* BLE scans for detecting other beacons
* *ena-bluetooth-advertise* BLE advertising to send own beacons
* *ena-exposure* decode Exposure Key export, compare with stored beacons, calculate score and risk
* *ena-exposure* compare exposed keys with stored beacons, calculate score and risk
* *ena* run all together and timing for scanning and advertising
### ena-binary-export
Module to decode Exposure Key export.
### ena-cwa
Connection to german Exposure App ([Corona Warn App](https://github.com/corona-warn-app)) for download Exposure Key export (and maybe later report infection).
### interface
Adds interface functionality via touch pads for control and setup.
Adds interface functionality for control and setup.
### display
General module for display and gfx.
### rtc
General module for set/get time from RTC.
### i2c-main
Just start I2C driver for display and RTC.
### ds3231
### interface-input-buttons
I2C driver for a DS3231 RTC
Interface with 7 button input
### ssd1306
### rtc-ds3231
I2C driver for a SSD1306 display.
I2C driver for a DS3231 RTC, implementation of [rtc](#-rtc) module
### display-ssd1306
I2C driver for a SSD1306 display, implementation of [display](#-display) module
### nanopb
[Nanopb](https://github.com/nanopb/nanopb) for reading Protocol Buffers of Exposure Key export. Including already generated Headers from *.proto files.
### miniz
[Miniz](https://github.com/richgel999/miniz) for unzipping Exposure Key export (not successful for now due to memory limit)
## Demo
[Demo Video (early stage)](https://twitter.com/Lurkars/status/1282223547579019264)
[Nanopb](https://github.com/nanopb/nanopb) for reading Protocol Buffers of Exposure Key export. Including already generated Headers from *.proto files.

View File

@ -1,8 +1,8 @@
idf_component_register(
SRCS
"ssd1306.c"
"ssd1306-gfx.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
PRIV_REQUIRES
display
i2c-main
)

View File

@ -17,54 +17,12 @@
#include "esp_log.h"
#include "i2c-main.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "ssd1306.h"
uint8_t ssd1306_utf8_to_ascii_char(uint8_t ascii)
{
static uint8_t c1;
if (ascii < 128) // Standard ASCII-set 0..0x7F handling
{
c1 = 0;
return (ascii);
}
// get previous input
uint8_t last = c1; // get last char
c1 = ascii; // remember actual character
switch (last) // conversion depending on first UTF8-character
{
case 0xC2:
return (ascii);
break;
case 0xC3:
return (ascii | 0xC0);
break;
case 0x82:
if (ascii == 0xAC)
return (0x80); // special case Euro-symbol
}
return (0); // otherwise: return zero, if character has to be ignored
}
void ssd1306_utf8_to_ascii(char *input, char *output)
{
strcpy(output, input);
int k = 0;
char c;
for (int i = 0; i < strlen(output); i++)
{
c = ssd1306_utf8_to_ascii_char(output[i]);
if (c != 0)
output[k++] = c;
}
output[k] = 0;
}
void ssd1306_start(uint8_t i2address)
void display_start(void)
{
if (!i2c_is_initialized())
{
@ -75,7 +33,7 @@ void ssd1306_start(uint8_t i2address)
i2c_master_start(cmd);
// Begin the I2C comm with SSD1306's address (SLA+Write)
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
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);
// Turn the Display OFF
@ -127,12 +85,12 @@ void ssd1306_start(uint8_t i2address)
i2c_cmd_link_delete(cmd);
}
void ssd1306_init_data(uint8_t i2address)
void display_init_data(void)
{
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, (i2address << 1) | I2C_MASTER_WRITE, true);
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);
@ -148,14 +106,14 @@ void ssd1306_init_data(uint8_t i2address)
i2c_cmd_link_delete(cmd);
}
void ssd1306_clear_line(uint8_t i2address, uint8_t line, bool invert)
void display_clear_line(uint8_t line, bool invert)
{
i2c_cmd_handle_t cmd;
uint8_t *zeros = calloc(SSD1306_COLUMNS, sizeof(uint8_t));
// set line
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, (SSD1306_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, SSD1306_CONTROL_CMD_STREAM, true);
i2c_master_write_byte(cmd, SSD1306_CMD_COLUMN_LOW, true);
@ -169,7 +127,7 @@ void ssd1306_clear_line(uint8_t i2address, uint8_t line, bool invert)
// fill line with zeros
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, (SSD1306_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, SSD1306_CONTROL_DATA_STREAM, true);
i2c_master_write(cmd, zeros, SSD1306_COLUMNS, true);
i2c_master_stop(cmd);
@ -179,21 +137,21 @@ void ssd1306_clear_line(uint8_t i2address, uint8_t line, bool invert)
free(zeros);
}
void ssd1306_clear(uint8_t i2address)
void display_clear(void)
{
for (uint8_t i = 0; i < SSD1306_PAGES; i++)
{
ssd1306_clear_line(i2address, i, false);
display_clear_line(i, false);
}
}
void ssd1306_on(uint8_t i2address, bool on)
void display_on(bool on)
{
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, (i2address << 1) | I2C_MASTER_WRITE, true);
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);
if (on)
@ -212,7 +170,7 @@ void ssd1306_on(uint8_t i2address, bool on)
i2c_cmd_link_delete(cmd);
}
void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert)
void display_data(uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert)
{
uint8_t column = offset;
@ -226,13 +184,13 @@ void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line,
columns = (SSD1306_COLUMNS - column);
}
ssd1306_init_data(i2address);
display_init_data();
i2c_cmd_handle_t cmd;
// set line
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, (SSD1306_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, SSD1306_CONTROL_CMD_STREAM, true);
i2c_master_write_byte(cmd, SSD1306_CMD_COLUMN_LOW | (column & 0XF), true);
@ -253,7 +211,7 @@ void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line,
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, (SSD1306_ADDRESS << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, SSD1306_CONTROL_DATA_STREAM, true);
i2c_master_write(cmd, data, columns, true);
@ -263,47 +221,17 @@ void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line,
i2c_cmd_link_delete(cmd);
}
uint8_t *ssd1306_text_to_data(char *text, size_t text_length, size_t *length)
void display_text_line_column(char *text, uint8_t line, uint8_t offset, bool invert)
{
char target_text[strlen(text)];
ssd1306_utf8_to_ascii(text, target_text);
uint8_t font_width = sizeof(ssd1306_gfx_font[0]);
*length = text_length * font_width;
uint8_t *data = calloc(*length, sizeof(uint8_t));
for (uint8_t i = 0; i < text_length; i++)
{
memcpy(&data[i * font_width], ssd1306_gfx_font[(uint8_t)target_text[i] - 32], font_width);
}
return data;
display_chars(text, strlen(text), line, offset, invert);
}
void ssd1306_chars(uint8_t i2address, char *text, size_t length, uint8_t line, uint8_t offset, bool invert)
void display_text_line(char *text, uint8_t line, bool invert)
{
if (length > 0)
{
uint8_t font_width = sizeof(ssd1306_gfx_font[0]);
size_t res_length = 0;
uint8_t *textdata = ssd1306_text_to_data(text, length, &res_length);
ssd1306_data(i2address, textdata, res_length, line, offset * font_width, invert);
free(textdata);
}
display_text_line_column(text, line, 0, invert);
}
void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8_t offset, bool invert)
{
ssd1306_chars(i2address, text, strlen(text), line, offset, invert);
}
void ssd1306_text_line(uint8_t i2address, char *text, uint8_t line, bool invert)
{
ssd1306_text_line_column(i2address, text, line, 0, invert);
}
void ssd1306_text_input(uint8_t i2address, char *text, uint8_t position)
void display_text_input(char *text, uint8_t position)
{
size_t start = 0;
if (position > 13)
@ -314,11 +242,11 @@ void ssd1306_text_input(uint8_t i2address, char *text, uint8_t position)
uint8_t cur_char = (uint8_t)text[start + position] - 32;
// arrow
ssd1306_data(i2address, ssd1306_gfx_arrow_left, 8, 2, 0, false);
display_data(display_gfx_arrow_left, 8, 2, 0, false);
// bounday
ssd1306_text_line_column(i2address, "______________", 2, 1, false);
display_text_line_column("______________", 2, 1, false);
// arrow
ssd1306_data(i2address, ssd1306_gfx_arrow_right, 8, 2, 15 * 8, false);
display_data(display_gfx_arrow_right, 8, 2, 15 * 8, false);
// text
size_t text_length = strlen(text);
if (strlen(text) > 14)
@ -326,22 +254,22 @@ void ssd1306_text_input(uint8_t i2address, char *text, uint8_t position)
text_length = 14;
}
size_t length = 0;
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
ssd1306_data(i2address, textdata, length, 2, 8, true);
uint8_t *textdata = display_text_to_data(text, text_length, &length);
display_data(textdata, length, 2, 8, true);
free(textdata);
// arrow
ssd1306_data(i2address, ssd1306_gfx_arrow_up, 8, 0, (position + 1) * 8, false);
display_data(display_gfx_arrow_up, 8, 0, (position + 1) * 8, false);
// upper char
ssd1306_data(i2address, ssd1306_gfx_font[cur_char - 1], 8, 1, (position + 1) * 8, false);
display_data(display_gfx_font[cur_char - 1], 8, 1, (position + 1) * 8, false);
// sel char
ssd1306_data(i2address, ssd1306_gfx_font[cur_char], 8, 2, (position + 1) * 8, false);
display_data(display_gfx_font[cur_char], 8, 2, (position + 1) * 8, false);
// lower char
ssd1306_data(i2address, ssd1306_gfx_font[cur_char + 1], 8, 3, (position + 1) * 8, false);
display_data(display_gfx_font[cur_char + 1], 8, 3, (position + 1) * 8, false);
// arrow
ssd1306_data(i2address, ssd1306_gfx_arrow_down, 8, 4, (position + 1) * 8, false);
display_data(display_gfx_arrow_down, 8, 4, (position + 1) * 8, false);
}
void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool primary)
void display_set_button(char *text, bool selected, bool primary)
{
uint8_t start = 0;
if (primary)
@ -350,15 +278,15 @@ void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool prima
}
if (selected)
{
ssd1306_data(i2address, ssd1306_gfx_button_sel[0], 64, 5, start, false);
ssd1306_data(i2address, ssd1306_gfx_button_sel[1], 64, 6, start, false);
ssd1306_data(i2address, ssd1306_gfx_button_sel[2], 64, 7, start, false);
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
{
ssd1306_data(i2address, ssd1306_gfx_button[0], 64, 5, start, false);
ssd1306_data(i2address, ssd1306_gfx_button[1], 64, 6, start, false);
ssd1306_data(i2address, ssd1306_gfx_button[2], 64, 7, start, false);
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);
@ -367,7 +295,7 @@ void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool prima
text_length = 6;
}
size_t length = 0;
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 6)
@ -375,19 +303,19 @@ void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool prima
offset = (6 - text_length) / 2 * 8;
}
ssd1306_data(i2address, textdata, length, 6, start + 8 + offset, selected);
display_data(textdata, length, 6, start + 8 + offset, selected);
free(textdata);
}
void ssd1306_menu_headline(uint8_t i2address, char *text, bool arrows, uint8_t line)
void display_menu_headline(char *text, bool arrows, uint8_t line)
{
if (arrows)
{
ssd1306_data(i2address, ssd1306_gfx_arrow_left, 8, line, 0, false);
ssd1306_data(i2address, ssd1306_gfx_arrow_right, 8, line, 15 * 8, false);
display_data(display_gfx_arrow_left, 8, line, 0, false);
display_data(display_gfx_arrow_right, 8, line, 15 * 8, false);
}
// bounday
ssd1306_data(i2address, ssd1306_gfx_menu_head, 112, line, 8, false);
display_data(display_gfx_menu_head, 112, line, 8, false);
// text
size_t text_length = strlen(text);
@ -396,7 +324,7 @@ void ssd1306_menu_headline(uint8_t i2address, char *text, bool arrows, uint8_t l
text_length = 10;
}
size_t length = 0;
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
uint8_t *textdata = display_text_to_data(text, text_length, &length);
uint8_t offset = 0;
if (text_length < 10)
@ -404,6 +332,6 @@ void ssd1306_menu_headline(uint8_t i2address, char *text, bool arrows, uint8_t l
offset = (10 - text_length) / 2 * 8;
}
ssd1306_data(i2address, textdata, length, line, 24 + offset, true);
display_data(textdata, length, line, 24 + offset, true);
free(textdata);
}

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 SSD1306 display
*
*/
#ifndef _ssd1306_H_
#define _ssd1306_H_
#include "esp_system.h"
#define SSD1306_ADDRESS (0x3C)
#define SSD1306_COLUMNS (128)
#define SSD1306_PAGES (8)
// Write mode for I2C https://robotcantalk.blogspot.com/2015/03/interfacing-arduino-with-ssd1306-driven.html
#define SSD1306_CONTROL_CMD_BYTE (0x80)
#define SSD1306_CONTROL_CMD_STREAM (0x00)
#define SSD1306_CONTROL_DATA_BYTE (0xC0)
#define SSD1306_CONTROL_DATA_STREAM (0x40)
// 1. Fundamental Command Table
#define SSD1306_CMD_CONTRAST (0x81)
#define SSD1306_CMD_RAM (0xA4)
#define SSD1306_CMD_ALL_ON (0xA5)
#define SSD1306_CMD_NORMAL (0xA6)
#define SSD1306_CMD_INVERSE (0xA7)
#define SSD1306_CMD_OFF (0xAE)
#define SSD1306_CMD_ON (0xAF)
// 2. Scrolling Command Table
#define SSD1306_CMD_SCROLL_HORI_RIGHT (0x26)
#define SSD1306_CMD_SCROLL_HORI_LEFT (0x27)
#define SSD1306_CMD_SCROLL_VERT_RIGHT (0x29)
#define SSD1306_CMD_SCROLL_VERT_LEFT (0x2A)
#define SSD1306_CMD_SCROLL_STOP (0x2E)
#define SSD1306_CMD_SCROLL_START (0x2F)
#define SSD1306_CMD_SCROLL_VERT_AREA (0xA3)
// 3. Addressing Setting Command Table
#define SSD1306_CMD_COLUMN_LOW (0x00)
#define SSD1306_CMD_COLUMN_HIGH (0x10)
#define SSD1306_CMD_MEMORY_MODE (0x20)
#define SSD1306_CMD_COLUMN_ADDRESS (0x21)
#define SSD1306_CMD_PAGE_ADDRESS (0x22)
#define SSD1306_CMD_PAGE (0xB0)
// 4. Hardware Configuration (Panel resolution & layout related) Command Table
#define SSD1306_CMD_START_LINE (0x40)
#define SSD1306_CMD_SEGMENT_LOW (0xA0)
#define SSD1306_CMD_SEGMENT_HIGH (0xA1)
#define SSD1306_CMD_MULTIPLEX_RATIO (0xA8)
#define SSD1306_CMD_SCAN_DIRECTION_NORMAL (0xC0)
#define SSD1306_CMD_SCAN_DIRECTION_REMAPPED (0xC8)
#define SSD1306_CMD_OFFSET (0xD3)
#define SSD1306_CMD_COM_PINS (0xDA)
// 5. Timing & Driving Scheme Setting Command Table
#define SSD1306_CMD_CLOCK (0xD5)
#define SSD1306_CMD_PRE_CHARGE_PERIOD (0xD9)
#define SSD1306_CMD_VCOMH (0xDB)
#define SSD1306_CMD_NOP (0xE3)
// 1. Charge Pump Command Table
#define SSD1306_CMD_CHARGE_PUMP (0x8D)
#endif

View File

@ -0,0 +1,6 @@
idf_component_register(
SRCS
"display.c"
"display-gfx.c"
INCLUDE_DIRS "."
)

View File

@ -11,11 +11,11 @@
// 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 "ssd1306-gfx.h"
#include "display-gfx.h"
uint8_t ssd1306_gfx_clear[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t display_gfx_clear[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t ssd1306_gfx_font[224][8] = {
uint8_t display_gfx_font[224][8] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x5f, 0x5f, 0x00, 0x00, 0x00},
{0x00, 0x08, 0x0e, 0x06, 0x08, 0x0e, 0x06, 0x00},
@ -242,60 +242,60 @@ uint8_t ssd1306_gfx_font[224][8] = {
{0x00, 0x0d, 0x1d, 0x70, 0x70, 0x1d, 0x0d, 0x00},
};
uint8_t ssd1306_gfx_button[3][64] = {
uint8_t display_gfx_button[3][64] = {
{0x00, 0x00, 0x00, 0xe0, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x30, 0xe0, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x07, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x07, 0x00, 0x00, 0x00},
};
uint8_t ssd1306_gfx_button_sel[3][64] = {
uint8_t display_gfx_button_sel[3][64] = {
{0x00, 0x00, 0x00, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x07, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07, 0x00, 0x00, 0x00},
};
uint8_t ssd1306_gfx_clock[8] = {0x3c, 0x42, 0x81, 0x9d, 0x91, 0x81, 0x42, 0x3c};
uint8_t display_gfx_clock[8] = {0x3c, 0x42, 0x81, 0x9d, 0x91, 0x81, 0x42, 0x3c};
uint8_t ssd1306_gfx_menu_head[112] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t display_gfx_menu_head[112] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t ssd1306_gfx_sad[4][24] = {
uint8_t display_gfx_sad[4][24] = {
{0x00, 0x00, 0x00, 0x80, 0xe0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xe0, 0x80, 0x00, 0x00, 0x00},
{0xf8, 0xff, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0x01, 0x01, 0x0f, 0xff, 0xf8},
{0x1f, 0xff, 0xf0, 0x80, 0x00, 0x40, 0x30, 0x38, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x38, 0x30, 0x40, 0x00, 0x80, 0xf0, 0xff, 0x1f},
{0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x07, 0x01, 0x00, 0x00, 0x00},
};
uint8_t ssd1306_gfx_smile[4][24] = {
uint8_t display_gfx_smile[4][24] = {
{0x00, 0x00, 0x00, 0x80, 0xe0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xe0, 0x80, 0x00, 0x00, 0x00},
{0xf8, 0xff, 0x0f, 0x01, 0x01, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x01, 0x01, 0x0f, 0xff, 0xf8},
{0x1f, 0xff, 0xf0, 0x80, 0x86, 0x06, 0x18, 0x38, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x38, 0x18, 0x06, 0x86, 0x80, 0xf0, 0xff, 0x1f},
{0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x07, 0x01, 0x00, 0x00, 0x00},
};
uint8_t ssd1306_gfx_question[4][24] = {
uint8_t display_gfx_question[4][24] = {
{0x00, 0x00, 0x00, 0x80, 0xe0, 0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0xe0, 0x80, 0x00, 0x00, 0x00},
{0xf8, 0xff, 0x0f, 0x01, 0x01, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x01, 0x01, 0x0f, 0xff, 0xf8},
{0x1f, 0xff, 0xf0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x26, 0xb2, 0x92, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xf0, 0xff, 0x1f},
{0x00, 0x00, 0x00, 0x01, 0x07, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x07, 0x01, 0x00, 0x00, 0x00},
};
uint8_t ssd1306_gfx_wifi[8] = {0x00, 0x02, 0x0a, 0x2a, 0x2a, 0x0a, 0x02, 0x00};
uint8_t display_gfx_wifi[8] = {0x00, 0x02, 0x0a, 0x2a, 0x2a, 0x0a, 0x02, 0x00};
uint8_t ssd1306_gfx_wifi_low[8] = {0x00, 0x00, 0x08, 0x28, 0x28, 0x08, 0x00, 0x00};
uint8_t display_gfx_wifi_low[8] = {0x00, 0x00, 0x08, 0x28, 0x28, 0x08, 0x00, 0x00};
uint8_t ssd1306_gfx_wifi_lowest[8] = {0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00};
uint8_t display_gfx_wifi_lowest[8] = {0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00};
uint8_t ssd1306_gfx_arrow_down[8] = {0x08, 0x18, 0x38, 0x78, 0x78, 0x38, 0x18, 0x08};
uint8_t display_gfx_arrow_down[8] = {0x08, 0x18, 0x38, 0x78, 0x78, 0x38, 0x18, 0x08};
uint8_t ssd1306_gfx_arrow_left[8] = {0x00, 0x18, 0x3c, 0x7e, 0xff, 0x00, 0x00, 0x00};
uint8_t display_gfx_arrow_left[8] = {0x00, 0x18, 0x3c, 0x7e, 0xff, 0x00, 0x00, 0x00};
uint8_t ssd1306_gfx_arrow_right[8] = {0x00, 0x00, 0x00, 0xff, 0x7e, 0x3c, 0x18, 0x00};
uint8_t display_gfx_arrow_right[8] = {0x00, 0x00, 0x00, 0xff, 0x7e, 0x3c, 0x18, 0x00};
uint8_t ssd1306_gfx_arrow_up[8] = {0x10, 0x18, 0x1c, 0x1e, 0x1e, 0x1c, 0x18, 0x10};
uint8_t display_gfx_arrow_up[8] = {0x10, 0x18, 0x1c, 0x1e, 0x1e, 0x1c, 0x18, 0x10};
uint8_t ssd1306_gfx_cross[8] = {0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00};
uint8_t display_gfx_cross[8] = {0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00};
uint8_t ssd1306_gfx_logo[8][64] = {
uint8_t display_gfx_logo[8][64] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x86, 0x06, 0x06, 0x0e, 0x0e, 0x1e, 0x1e, 0x3e, 0x3c, 0x7c, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x86, 0x06, 0x06, 0x0e, 0x0e, 0x1e, 0x1e, 0x3e, 0x3c, 0x7c, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x86, 0x06, 0x06, 0x0e, 0x0e, 0x1e, 0x1e, 0x3e, 0x3c, 0x7c, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},

View File

@ -17,46 +17,46 @@
* @brief gfx elements: font, icons, elements
*
*/
#ifndef _ssd1306_GFX_H_
#define _ssd1306_GFX_H_
#ifndef _display_GFX_H_
#define _display_GFX_H_
#include <stdint.h>
uint8_t ssd1306_gfx_clear[8];
uint8_t display_gfx_clear[8];
// Dogica Font https://www.dafont.com/de/dogica.font starting at space (32)
uint8_t ssd1306_gfx_font[224][8];
uint8_t display_gfx_font[224][8];
uint8_t ssd1306_gfx_button[3][64];
uint8_t display_gfx_button[3][64];
uint8_t ssd1306_gfx_button_sel[3][64];
uint8_t display_gfx_button_sel[3][64];
uint8_t ssd1306_gfx_clock[8];
uint8_t display_gfx_clock[8];
uint8_t ssd1306_gfx_menu_head[112];
uint8_t display_gfx_menu_head[112];
uint8_t ssd1306_gfx_sad[4][24];
uint8_t display_gfx_sad[4][24];
uint8_t ssd1306_gfx_smile[4][24];
uint8_t display_gfx_smile[4][24];
uint8_t ssd1306_gfx_question[4][24];
uint8_t display_gfx_question[4][24];
uint8_t ssd1306_gfx_wifi[8];
uint8_t display_gfx_wifi[8];
uint8_t ssd1306_gfx_wifi_low[8];
uint8_t display_gfx_wifi_low[8];
uint8_t ssd1306_gfx_wifi_lowest[8];
uint8_t display_gfx_wifi_lowest[8];
uint8_t ssd1306_gfx_arrow_down[8];
uint8_t display_gfx_arrow_down[8];
uint8_t ssd1306_gfx_arrow_left[8];
uint8_t display_gfx_arrow_left[8];
uint8_t ssd1306_gfx_arrow_right[8];
uint8_t display_gfx_arrow_right[8];
uint8_t ssd1306_gfx_arrow_up[8];
uint8_t display_gfx_arrow_up[8];
uint8_t ssd1306_gfx_cross[8];
uint8_t display_gfx_cross[8];
uint8_t ssd1306_gfx_logo[8][64];
uint8_t display_gfx_logo[8][64];
#endif

View File

@ -0,0 +1,90 @@
// 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 "display.h"
#include "display-gfx.h"
uint8_t display_utf8_to_ascii_char(uint8_t ascii)
{
static uint8_t c1;
if (ascii < 128) // Standard ASCII-set 0..0x7F handling
{
c1 = 0;
return (ascii);
}
// get previous input
uint8_t last = c1; // get last char
c1 = ascii; // remember actual character
switch (last) // conversion depending on first UTF8-character
{
case 0xC2:
return (ascii);
break;
case 0xC3:
return (ascii | 0xC0);
break;
case 0x82:
if (ascii == 0xAC)
return (0x80); // special case Euro-symbol
}
return (0); // otherwise: return zero, if character has to be ignored
}
void display_utf8_to_ascii(char *input, char *output)
{
strcpy(output, input);
int k = 0;
char c;
for (int i = 0; i < strlen(output); i++)
{
c = display_utf8_to_ascii_char(output[i]);
if (c != 0)
output[k++] = c;
}
output[k] = 0;
}
uint8_t *display_text_to_data(char *text, size_t text_length, size_t *length)
{
char target_text[strlen(text)];
display_utf8_to_ascii(text, target_text);
uint8_t font_width = sizeof(display_gfx_font[0]);
*length = text_length * font_width;
uint8_t *data = calloc(*length, sizeof(uint8_t));
for (uint8_t i = 0; i < text_length; i++)
{
memcpy(&data[i * font_width], display_gfx_font[(uint8_t)target_text[i] - 32], font_width);
}
return data;
}
void display_chars(char *text, size_t length, uint8_t line, uint8_t offset, bool invert)
{
if (length > 0)
{
uint8_t font_width = sizeof(display_gfx_font[0]);
size_t res_length = 0;
uint8_t *textdata = display_text_to_data(text, length, &res_length);
display_data(textdata, res_length, line, offset * font_width, invert);
free(textdata);
}
}

View File

@ -0,0 +1,125 @@
// 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 interface for display
*
*/
#ifndef _display_H_
#define _display_H_
#include "esp_system.h"
/**
*
*/
void display_utf8_to_ascii(char *input, char *output);
/**
*
*/
uint8_t *display_text_to_data(char *text, size_t text_length, size_t *length);
/**
* @brief initalize display
*/
void display_start(void);
/**
* @brief clear the display
*
* @param[in] line the line to clear
* @param[in] invert if true, image is inverted
*/
void display_clear_line( uint8_t line, bool invert);
/**
* @brief clear the display
*
*/
void display_clear(void);
/**
* @brief set display on or offf
*
* @param[in] on true if display on, false if display off
*/
void display_on(bool on);
/**
*
*/
uint8_t *display_text_to_data(char *text, size_t text_length, size_t *length);
/**
* @brief write raw bytes to display line at starting column
*
* @param[in] data bytes to display
* @param[in] length length of data
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void display_data(uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write chars to display
*
* @param[in] text text to display
* @param[in] length length of text
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void display_chars(char *text, size_t length, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write text to display line at starting column
*
* @param[in] text text to display
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void display_text_line_column(char *text, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write text to display line
*
* @param[in] text text to display
* @param[in] line the line to write to
* @param[in] invert if true, image is inverted
*/
void display_text_line(char *text, uint8_t line, bool invert);
/**
* @brief display a button element
*
* @param[in] text button text
* @param[in] selected is button selected
* @param[in] primary is button primary
*/
void display_set_button(char *text, bool selected, bool primary);
/**
* @brief display a menu headline
*
* @param[in] text headline text
* @param[in] arrows if left right arrows should be displays
* @param[in] line line the line to write to
*/
void display_menu_headline(char *text, bool arrows, uint8_t line);
#endif

View File

@ -0,0 +1,10 @@
idf_component_register(
SRCS
"ena-binary-export.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
ena
nanopb
EMBED_FILES
"test/export.bin"
)

View File

@ -0,0 +1,90 @@
#include <string.h>
#include <time.h>
#include <limits.h>
#include "esp_err.h"
#include "esp_log.h"
#include "ena-exposure.h"
#include "pb_decode.h"
#include "TemporaryExposureKeyExport.pb.h"
static const char kFileHeader[] = "EK Export v1 ";
static size_t kFileHeaderSize = sizeof(kFileHeader) - 1;
bool ena_binary_export_decode_key_data(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t *key_data = (uint8_t *)*arg;
if (!pb_read(stream, key_data, stream->bytes_left))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(stream));
return false;
}
return true;
}
bool ena_binary_export_decode_key(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t key_data[ENA_KEY_LENGTH] = {0};
TemporaryExposureKey tek = TemporaryExposureKey_init_zero;
tek.key_data = (pb_callback_t){
.funcs.decode = ena_binary_export_decode_key_data,
.arg = &key_data,
};
if (!pb_decode(stream, TemporaryExposureKey_fields, &tek))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(stream));
return false;
}
ESP_LOGD(ENA_EXPOSURE_LOG,
"check reported tek: rolling_start_interval_number %d, rolling_period %d, days_since_last_exposure %d, report_type %d, transmission_risk_values %d",
tek.rolling_start_interval_number, tek.rolling_period, tek.days_since_onset_of_symptoms, tek.report_type, tek.transmission_risk_level);
ESP_LOG_BUFFER_HEXDUMP(ENA_EXPOSURE_LOG, &key_data, ENA_KEY_LENGTH, ESP_LOG_DEBUG);
ena_temporary_exposure_key_t temporary_exposure_key = {
.transmission_risk_level = tek.transmission_risk_level,
.rolling_start_interval_number = tek.rolling_start_interval_number,
.rolling_period = tek.rolling_period,
.report_type = tek.report_type,
.days_since_onset_of_symptoms = tek.days_since_onset_of_symptoms,
};
memcpy(temporary_exposure_key.key_data, key_data, ENA_KEY_LENGTH);
ena_exposure_check_temporary_exposure_key(temporary_exposure_key);
return true;
}
esp_err_t ena_binary_export_check_export(uint8_t *buf, size_t size)
{
// validate header
if (memcmp(kFileHeader, buf, kFileHeaderSize) != 0)
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Wrong or missing header!");
return ESP_FAIL;
}
TemporaryExposureKeyExport tek_export = TemporaryExposureKeyExport_init_zero;
tek_export.keys = (pb_callback_t){
.funcs.decode = ena_binary_export_decode_key,
};
pb_istream_t stream = pb_istream_from_buffer(&buf[kFileHeaderSize], (size - kFileHeaderSize));
if (!pb_decode(&stream, TemporaryExposureKeyExport_fields, &tek_export))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(&stream));
return ESP_FAIL;
}
return ESP_OK;
}

View File

@ -0,0 +1,37 @@
// 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 decode Exposure Key export and run exposure check
*
*/
#ifndef _ena_BINARY_H_
#define _ena_BINARY_H_
#include <stdio.h>
#include "esp_err.h"
/**
* @brief reads a Temporary Exposue Key Export binary and check for exposures
*
* @param[in] buf the buffer containing the binary data
* @param[in] size the size of the buffer
*
* @return
* esp_err_t status of reading binary
*/
esp_err_t ena_binary_export_check_export(uint8_t *buf, size_t size);
#endif

View File

@ -4,8 +4,8 @@ idf_component_register(
INCLUDE_DIRS "."
PRIV_REQUIRES
esp_http_client
miniz
ena
ena-binary-export
wifi-controller
EMBED_FILES
"certs/telekom.pem"

View File

@ -16,16 +16,17 @@
#include "esp_log.h"
#include "esp_event.h"
#include "esp_http_client.h"
#include "miniz.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ena-storage.h"
#include "ena-exposure.h"
#include "ena-cwa.h"
#include "ena-binary-export.h"
#include "wifi-controller.h"
#include "ena-cwa.h"
extern uint8_t export_bin_start[] asm("_binary_export_bin_start"); // test data from Google or https://svc90.main.px.t-online.de/version/v1/diagnosis-keys/country/DE/date/2020-07-22
extern uint8_t export_bin_end[] asm("_binary_export_bin_end");
@ -63,7 +64,7 @@ esp_err_t ena_cwa_http_event_handler(esp_http_client_event_t *evt)
free(output_buffer);
output_buffer = NULL;
output_len = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(ena_exposure_check_export(export_bin_start, (export_bin_end - export_bin_start)));
ESP_ERROR_CHECK_WITHOUT_ABORT(ena_binary_export_check_export(export_bin_start, (export_bin_end - export_bin_start)));
}
else
{

View File

@ -11,8 +11,4 @@ idf_component_register(
PRIV_REQUIRES
spi_flash
mbedtls
bt
nanopb
EMBED_FILES
"test/export.bin"
)
bt)

View File

@ -22,9 +22,6 @@
#include "ena-storage.h"
#include "ena-beacons.h"
#include "pb_decode.h"
#include "TemporaryExposureKeyExport.pb.h"
#include "ena-exposure.h"
static ena_exposure_summary_t *current_summary;
@ -76,9 +73,6 @@ static ena_exposure_config_t DEFAULT_ENA_EXPOSURE_CONFIG = {
},
};
static const char kFileHeader[] = "EK Export v1 ";
static size_t kFileHeaderSize = sizeof(kFileHeader) - 1;
int ena_exposure_transmission_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
{
return config->transmission_risk_values[params.report_type];
@ -273,62 +267,29 @@ ena_exposure_config_t *ena_exposure_default_config(void)
return &DEFAULT_ENA_EXPOSURE_CONFIG;
}
bool ena_exposure_decode_key_data(pb_istream_t *stream, const pb_field_t *field, void **arg)
void ena_exposure_check_temporary_exposure_key(ena_temporary_exposure_key_t temporary_exposure_key)
{
uint8_t *key_data = (uint8_t *)*arg;
if (!pb_read(stream, key_data, stream->bytes_left))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(stream));
return false;
}
return true;
}
bool ena_exposure_decode_key(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t key_data[ENA_KEY_LENGTH] = {0};
TemporaryExposureKey tek = TemporaryExposureKey_init_zero;
tek.key_data = (pb_callback_t){
.funcs.decode = ena_exposure_decode_key_data,
.arg = &key_data,
};
if (!pb_decode(stream, TemporaryExposureKey_fields, &tek))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(stream));
return false;
}
ESP_LOGD(ENA_EXPOSURE_LOG,
"check reported tek: rolling_start_interval_number %d, rolling_period %d, days_since_last_exposure %d, report_type %d, transmission_risk_values %d",
tek.rolling_start_interval_number, tek.rolling_period, tek.days_since_onset_of_symptoms, tek.report_type, tek.transmission_risk_level);
ESP_LOG_BUFFER_HEXDUMP(ENA_EXPOSURE_LOG, &key_data, ENA_KEY_LENGTH, ESP_LOG_DEBUG);
bool match = false;
ena_beacon_t beacon;
ena_exposure_information_t exposure_info;
exposure_info.duration_minutes = 0;
exposure_info.min_attenuation = INT_MAX;
exposure_info.typical_attenuation = 0;
exposure_info.report_type = tek.report_type;
exposure_info.report_type = temporary_exposure_key.report_type;
uint8_t rpi[ENA_KEY_LENGTH];
uint8_t rpik[ENA_KEY_LENGTH];
ena_crypto_rpik(rpik, key_data);
ena_crypto_rpik(rpik, temporary_exposure_key.key_data);
uint32_t beacons_count = ena_storage_beacons_count();
for (int i = 0; i < tek.rolling_period; i++)
for (int i = 0; i < temporary_exposure_key.rolling_period; i++)
{
ena_crypto_rpi(rpi, rpik, tek.rolling_start_interval_number + i);
ena_crypto_rpi(rpi, rpik, temporary_exposure_key.rolling_start_interval_number + i);
for (int y = 0; y < beacons_count; y++)
{
ena_storage_get_beacon(y, &beacon);
if (memcmp(beacon.rpi, rpi, sizeof(ENA_KEY_LENGTH)) == 0)
{
match = true;
exposure_info.day = tek.rolling_start_interval_number * ENA_TIME_WINDOW;
exposure_info.day = temporary_exposure_key.rolling_start_interval_number * ENA_TIME_WINDOW;
exposure_info.duration_minutes += (ENA_BEACON_TRESHOLD / 60);
exposure_info.typical_attenuation = (exposure_info.typical_attenuation + beacon.rssi) / 2;
if (beacon.rssi < exposure_info.min_attenuation)
@ -343,32 +304,4 @@ bool ena_exposure_decode_key(pb_istream_t *stream, const pb_field_t *field, void
{
ena_storage_add_exposure_information(&exposure_info);
}
return true;
}
esp_err_t ena_exposure_check_export(uint8_t *buf, size_t size)
{
// validate header
if (memcmp(kFileHeader, buf, kFileHeaderSize) != 0)
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Wrong or missing header!");
return ESP_FAIL;
}
TemporaryExposureKeyExport tek_export = TemporaryExposureKeyExport_init_zero;
tek_export.keys = (pb_callback_t){
.funcs.decode = ena_exposure_decode_key,
};
pb_istream_t stream = pb_istream_from_buffer(&buf[kFileHeaderSize], (size - kFileHeaderSize));
if (!pb_decode(&stream, TemporaryExposureKeyExport_fields, &tek_export))
{
ESP_LOGW(ENA_EXPOSURE_LOG, "Decoding failed: %s\n", PB_GET_ERROR(&stream));
return ESP_FAIL;
}
return ESP_OK;
}

View File

@ -14,7 +14,7 @@
/**
* @file
*
* @brief decode Exposure Key export, compare with stored beacons, calculate score and risk
* @brief compare temporary exposure keys with stored beacons, calculate score and risk
*
*/
#ifndef _ena_EXPOSURE_H_
@ -142,6 +142,21 @@ typedef struct __attribute__((__packed__))
int risk_score_sum; // sum of all risk_scores
} ena_exposure_summary_t;
/**
* @brief structure for temporary exposure key
*
* The temporary exposure key is used to check for exposure.
*/
typedef struct __attribute__((__packed__))
{
uint8_t key_data[ENA_KEY_LENGTH];
uint8_t transmission_risk_level;
uint8_t rolling_start_interval_number;
uint8_t rolling_period;
ena_report_type_t report_type;
uint32_t days_since_onset_of_symptoms;
} ena_temporary_exposure_key_t;
/**
* @brief calculate transmission risk score
*
@ -216,14 +231,10 @@ ena_exposure_summary_t *ena_exposure_current_summary(void);
ena_exposure_config_t *ena_exposure_default_config(void);
/**
* @brief reads a Temporary Exposue Key Export binary and check for exposures
* @brief reads Temporary Exposue Key and check for exposures
*
* @param[in] buf the buffer containing the binary data
* @param[in] size the size of the buffer
*
* @return
* esp_err_t status of reading binary
* @param[in] temporary_exposure_key the temporary exposure keys to check
*/
esp_err_t ena_exposure_check_export(uint8_t *buf, size_t size);
void ena_exposure_check_temporary_exposure_key(ena_temporary_exposure_key_t temporary_exposure_key);
#endif

View File

@ -0,0 +1,7 @@
idf_component_register(
SRCS
"button-input.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
interface
)

View File

@ -0,0 +1,83 @@
// 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 "interface.h"
#include "button-input.h"
static int old_button_states[INTERFACE_COMMANDS_SIZE];
static int 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]);
if (old_button_states[command] != 0 && old_button_states[command] != 1)
{
old_button_states[command] = 1;
}
if (button_states[command] == 0 && button_states[command] != old_button_states[command])
{
interface_execute_command(command);
}
old_button_states[command] = button_states[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);
}
}
void button_input_start(void)
{
gpio_config_t io_conf;
io_conf.pin_bit_mask = (1ULL << BUTTON_RST) | (1ULL << BUTTON_SET) |
(1ULL << BUTTON_MID) | (1ULL << BUTTON_RHT) |
(1ULL << BUTTON_LFT) | (1ULL << BUTTON_DWN) |
(1ULL << BUTTON_UP);
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);
button_command_mapping[INTERFACE_COMMAND_RST] = BUTTON_RST;
button_command_mapping[INTERFACE_COMMAND_SET] = BUTTON_SET;
button_command_mapping[INTERFACE_COMMAND_MID] = BUTTON_MID;
button_command_mapping[INTERFACE_COMMAND_RHT] = BUTTON_RHT;
button_command_mapping[INTERFACE_COMMAND_LFT] = BUTTON_LFT;
button_command_mapping[INTERFACE_COMMAND_DWN] = BUTTON_DWN;
button_command_mapping[INTERFACE_COMMAND_UP] = BUTTON_UP;
xTaskCreate(&button_input_task, "button_input_task", 4096, NULL, 5, NULL);
}

View File

@ -0,0 +1,38 @@
// 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 _button_input_H_
#define _button_input_H_
#define BUTTON_RST GPIO_NUM_32
#define BUTTON_SET GPIO_NUM_33
#define BUTTON_MID GPIO_NUM_25
#define BUTTON_RHT GPIO_NUM_26
#define BUTTON_LFT GPIO_NUM_27
#define BUTTON_DWN GPIO_NUM_14
#define BUTTON_UP GPIO_NUM_12
/**
* @brief
*
*
*/
void button_input_start(void);
#endif

View File

@ -12,7 +12,9 @@ idf_component_register(
INCLUDE_DIRS "."
PRIV_REQUIRES
ena
ssd1306
ds3231
display
display-ssd1306
rtc
rtc-ds3231
wifi-controller
)

View File

@ -19,8 +19,8 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "ena-storage.h"
@ -49,9 +49,9 @@ void interface_data_set(void)
else
{
confirm_current = false;
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
}
}
@ -83,9 +83,9 @@ void interface_data_rst(void)
}
confirm_current = false;
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
}
}
@ -103,9 +103,9 @@ void interface_data_mid(void)
{
if (!confirm_current)
{
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
confirm_current = true;
}
}
@ -124,9 +124,9 @@ void interface_data_up(void)
current_data_index--;
}
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
}
void interface_data_dwn(void)
@ -142,26 +142,26 @@ void interface_data_dwn(void)
current_data_index++;
}
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
display_clear_line( 6, false);
}
void interface_data_display(void)
{
ssd1306_menu_headline(SSD1306_ADDRESS, 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)
{
ssd1306_text_line_column(SSD1306_ADDRESS, interface_get_label_text(&interface_text_data_del[current_interface_data_state]), 2, 2, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "?", 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);
ssd1306_set_button(SSD1306_ADDRESS, interface_get_label_text(&interface_text_button_cancel), true, false);
ssd1306_set_button(SSD1306_ADDRESS, 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
{
ssd1306_clear_line(SSD1306_ADDRESS, 5, false);
ssd1306_clear_line(SSD1306_ADDRESS, 7, false);
display_clear_line( 5, false);
display_clear_line( 7, false);
for (int i = 0; i < 3; i++)
{
int index = i + current_data_index;
@ -169,10 +169,10 @@ void interface_data_display(void)
{
if (index == current_interface_data_state)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, i * 2 + 2, 8, false);
display_data( display_gfx_arrow_right, 8, i * 2 + 2, 8, false);
}
ssd1306_text_line_column(SSD1306_ADDRESS, 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);
}
}
}
@ -182,13 +182,13 @@ void interface_data_start(void)
{
current_interface_data_state = INTERFACE_DATA_DEL_TEK;
interface_register_button_callback(INTERFACE_BUTTON_RST, &interface_data_rst);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_data_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_data_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_data_rht);
interface_register_button_callback(INTERFACE_BUTTON_MID, &interface_data_mid);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_data_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_data_dwn);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_data_rst);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_data_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_data_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_data_rht);
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);
ESP_LOGD(INTERFACE_LOG, "start delete data interface");

View File

@ -17,9 +17,9 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ds3231.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "rtc.h"
#include "display.h"
#include "display-gfx.h"
#include "interface.h"
@ -74,7 +74,7 @@ void interface_datetime_up(void)
struct timeval tv = {0};
tv.tv_sec = curtime;
settimeofday(&tv, NULL);
ds3231_set_time(gmtime(&curtime));
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));
}
@ -85,7 +85,7 @@ void interface_datetime_dwn(void)
struct timeval tv = {0};
tv.tv_sec = curtime;
settimeofday(&tv, NULL);
ds3231_set_time(gmtime(&curtime));
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));
}
@ -96,26 +96,26 @@ void interface_datetime_display(void)
static char time_buffer[9];
static char date_buffer[32];
ssd1306_menu_headline(SSD1306_ADDRESS, interface_get_label_text(&interface_text_headline_time), true, 0);
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;
ssd1306_clear_line(SSD1306_ADDRESS, edit_line - 1, false);
ssd1306_clear_line(SSD1306_ADDRESS, edit_line + 1, false);
display_clear_line( edit_line - 1, false);
display_clear_line( edit_line + 1, false);
time(&current_timstamp);
current_tm = localtime(&current_timstamp);
strftime(time_buffer, 16, INTERFACE_FORMAT_TIME, current_tm);
ssd1306_text_line_column(SSD1306_ADDRESS, 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);
ssd1306_text_line_column(SSD1306_ADDRESS, date_buffer, 6, 4, false);
display_text_line_column( date_buffer, 6, 4, false);
switch (interface_datetime_state())
{
@ -153,21 +153,21 @@ void interface_datetime_display(void)
break;
}
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_up, 8, edit_line - 1, edit_offset * 8 + 4, false);
ssd1306_chars(SSD1306_ADDRESS, edit_char, edit_length, edit_line, edit_offset, true);
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
}
void interface_datetime_start(void)
{
current_interface_datetime_state = INTERFACE_DATETIME_STATE_HOUR;
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_datetime_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_datetime_rht);
interface_register_button_callback(INTERFACE_BUTTON_MID, &interface_datetime_mid);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_datetime_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_datetime_dwn);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_datetime_set);
interface_register_button_callback(INTERFACE_BUTTON_RST, NULL);
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_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(&interface_datetime_display);
ESP_LOGD(INTERFACE_LOG, "start datetime interface");
}

View File

@ -19,13 +19,13 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "interface.h"
static interface_input_callback current_input_callback_rst;
static interface_input_callback current_input_callback_set;
static interface_text_callback current_input_callback_rst;
static interface_text_callback current_input_callback_set;
static char current_text[255];
static uint8_t current_cursor;
static char current_char_set[32];
@ -186,8 +186,8 @@ void interface_input_display(void)
{
// buttons
ssd1306_set_button(SSD1306_ADDRESS, interface_get_label_text(&interface_text_button_cancel), true, false);
ssd1306_set_button(SSD1306_ADDRESS, 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;
@ -200,22 +200,22 @@ void interface_input_display(void)
// arrow
if (current_cursor > 0)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_left, 8, 2, 0, false);
display_data( display_gfx_arrow_left, 8, 2, 0, false);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 2, 0, false);
display_data( display_gfx_clear, 8, 2, 0, false);
}
// bounday
ssd1306_text_line_column(SSD1306_ADDRESS, "______________", 2, 1, false);
display_text_line_column( "______________", 2, 1, false);
// arrow
if (current_cursor < current_limit)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, 2, 15 * 8, false);
display_data( display_gfx_arrow_right, 8, 2, 15 * 8, false);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 2, 15 * 8, false);
display_data( display_gfx_clear, 8, 2, 15 * 8, false);
}
// text
size_t text_length = strlen(current_text);
@ -227,17 +227,17 @@ void interface_input_display(void)
uint8_t *textdata = calloc(length, sizeof(uint8_t));
for (uint8_t i = 0; i < text_length; i++)
{
memcpy(&textdata[i * 8], ssd1306_gfx_font[(uint8_t)current_text[i + start] - 32], 8);
memcpy(&textdata[i * 8], display_gfx_font[(uint8_t)current_text[i + start] - 32], 8);
}
ssd1306_data(SSD1306_ADDRESS, textdata, length, 2, 8, true);
display_data( textdata, length, 2, 8, true);
free(textdata);
// clear
ssd1306_clear_line(SSD1306_ADDRESS, 0, false);
ssd1306_clear_line(SSD1306_ADDRESS, 1, false);
ssd1306_clear_line(SSD1306_ADDRESS, 3, false);
ssd1306_clear_line(SSD1306_ADDRESS, 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;
@ -254,38 +254,38 @@ void interface_input_display(void)
}
// arrow
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_up, 8, 0, display_cursor * 8, false);
display_data( display_gfx_arrow_up, 8, 0, display_cursor * 8, false);
// upper char
ssd1306_data(SSD1306_ADDRESS, ssd1306_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
ssd1306_data(SSD1306_ADDRESS, ssd1306_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
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_font[next_char], 8, 3, display_cursor * 8, false);
display_data( display_gfx_font[next_char], 8, 3, display_cursor * 8, false);
// arrow
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_down, 8, 4, display_cursor * 8, false);
display_data( display_gfx_arrow_down, 8, 4, display_cursor * 8, false);
}
void interface_input_set_text(char *text)
{
ssd1306_utf8_to_ascii(text, current_text);
display_utf8_to_ascii(text, current_text);
current_cursor = strlen(current_text) - 1;
current_max_index = current_cursor;
interface_input_set_char_set();
}
void interface_input(interface_input_callback callback_rst, interface_input_callback callback_set, uint8_t limit)
void interface_input(interface_text_callback callback_rst, interface_text_callback callback_set, uint8_t limit)
{
current_input_callback_rst = callback_rst;
current_input_callback_set = callback_set;
current_cursor = 0;
current_limit = limit - 1;
ssd1306_utf8_to_ascii("ABCDEFGHIJKLMNOPQRSTUVWXYZ", char_set_uppercase);
ssd1306_utf8_to_ascii("abcdefghijklmnopqrstuvwxyz", char_set_lowercase);
ssd1306_utf8_to_ascii(" !\"#$%&'()*+,-,&:;<=>@[\\]^_´`{}", char_set_special1);
ssd1306_utf8_to_ascii("0123456789", char_set_numeric);
ssd1306_utf8_to_ascii("ÄÖÜ", char_set_special_uppercasecase);
ssd1306_utf8_to_ascii("äöü", char_set_special_lowercase);
display_utf8_to_ascii("ABCDEFGHIJKLMNOPQRSTUVWXYZ", char_set_uppercase);
display_utf8_to_ascii("abcdefghijklmnopqrstuvwxyz", char_set_lowercase);
display_utf8_to_ascii(" !\"#$%&'()*+,-,&:;<=>@[\\]^_´`{}", char_set_special1);
display_utf8_to_ascii("0123456789", char_set_numeric);
display_utf8_to_ascii("ÄÖÜ", char_set_special_uppercasecase);
display_utf8_to_ascii("äöü", char_set_special_lowercase);
strcpy(current_char_set, char_set_uppercase);
@ -305,13 +305,13 @@ void interface_input(interface_input_callback callback_rst, interface_input_call
current_text[current_cursor] = current_char_set[current_char_index];
interface_register_button_callback(INTERFACE_BUTTON_RST, &interface_input_rst);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_input_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_input_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_input_rht);
interface_register_button_callback(INTERFACE_BUTTON_MID, &interface_input_mid);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_input_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_input_dwn);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_input_rst);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_input_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_input_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_input_rht);
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_set_display_function(&interface_input_display);
ESP_LOGD(INTERFACE_LOG, "start input interface");

View File

@ -17,9 +17,8 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ds3231.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "wifi-controller.h"
#include "ena-storage.h"
@ -47,11 +46,11 @@ void interface_main_display(void)
{
if (wifi_connected)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_wifi, 8, 0, 0, false);
display_data( display_gfx_wifi, 8, 0, 0, false);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_cross, 8, 0, 0, false);
display_data( display_gfx_cross, 8, 0, 0, false);
}
time(&current_timstamp);
@ -62,23 +61,23 @@ void interface_main_display(void)
interface_get_label_text(&interface_texts_weekday[current_tm->tm_wday]),
interface_get_label_text(&interface_texts_month[current_tm->tm_mon]),
current_tm->tm_mday);
ssd1306_text_line_column(SSD1306_ADDRESS, text_buffer, 0, 16 - strlen(text_buffer), false);
display_text_line_column( text_buffer, 0, 16 - strlen(text_buffer), false);
// current time
strftime(time_buffer, 16, INTERFACE_FORMAT_TIME, current_tm);
ssd1306_text_line_column(SSD1306_ADDRESS, time_buffer, 1, 16 - strlen(time_buffer), false);
display_text_line_column( time_buffer, 1, 16 - strlen(time_buffer), false);
}
void interface_main_start(void)
{
interface_register_button_callback(INTERFACE_BUTTON_RST, &interface_main_rst);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_main_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, NULL);
interface_register_button_callback(INTERFACE_BUTTON_RHT, NULL);
interface_register_button_callback(INTERFACE_BUTTON_MID, NULL);
interface_register_button_callback(INTERFACE_BUTTON_UP, NULL);
interface_register_button_callback(INTERFACE_BUTTON_DWN, NULL);
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);
interface_register_command_callback(INTERFACE_COMMAND_RHT, NULL);
interface_register_command_callback(INTERFACE_COMMAND_MID, NULL);
interface_register_command_callback(INTERFACE_COMMAND_UP, NULL);
interface_register_command_callback(INTERFACE_COMMAND_DWN, NULL);
if (wifi_controller_connection() != NULL)
{
@ -99,27 +98,27 @@ void interface_main_start(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)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_question[0], 24, 0, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_question[1], 24, 1, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_question[2], 24, 2, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_question[3], 24, 3, 12, false);
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);
display_data( display_gfx_question[3], 24, 3, 12, false);
}
else if (current_exposure_summary->max_risk_score < 100)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_smile[0], 24, 0, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_smile[1], 24, 1, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_smile[2], 24, 2, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_smile[3], 24, 3, 12, false);
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);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_sad[0], 24, 0, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_sad[1], 24, 1, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_sad[2], 24, 2, 12, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_sad[3], 24, 3, 12, false);
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);
}
// clock icon
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clock, 8, 4, 8, false);
display_data( display_gfx_clock, 8, 4, 8, false);
// last update
struct tm *last_update_tm = localtime((time_t*) &last_update);
@ -132,12 +131,12 @@ void interface_main_start(void)
if (last_update != 0)
{
ssd1306_text_line_column(SSD1306_ADDRESS, time_buffer, 4, 3, false);
display_text_line_column( time_buffer, 4, 3, false);
}
// buttons
ssd1306_set_button(SSD1306_ADDRESS, interface_get_label_text(&interface_text_button_menu), true, false);
ssd1306_set_button(SSD1306_ADDRESS, interface_get_label_text(&interface_text_button_report), false, true);
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);
ESP_LOGD(INTERFACE_LOG, "start main interface");
}

View File

@ -19,8 +19,8 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "wifi-controller.h"
@ -83,30 +83,30 @@ void interface_report_dwn(void)
void interface_report_display(void)
{
ssd1306_menu_headline(SSD1306_ADDRESS, interface_get_label_text(&interface_text_headline_tan), false, 0);
display_menu_headline( interface_get_label_text(&interface_text_headline_tan), false, 0);
// buttons
ssd1306_set_button(SSD1306_ADDRESS, interface_get_label_text(&interface_text_button_cancel), true, false);
ssd1306_set_button(SSD1306_ADDRESS, 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);
static char tan_buffer[10] = {0};
if (interface_report_tan_index > 0)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_left, 8, 3, 8, false);
display_data( display_gfx_arrow_left, 8, 3, 8, false);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 3, 8, false);
display_data( display_gfx_clear, 8, 3, 8, false);
}
if (interface_report_tan_index < 9)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, 3, 112, false);
display_data( display_gfx_arrow_right, 8, 3, 112, false);
}
else
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 3, 112, false);
display_data( display_gfx_clear, 8, 3, 112, false);
}
for (int i = 0; i < interface_report_tan_index + 1; i++)
@ -114,21 +114,21 @@ void interface_report_display(void)
sprintf(&tan_buffer[i], "%d", interface_report_tan[i]);
}
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
display_clear_line( 2, false);
display_clear_line( 4, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "-", 3, 5, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "-", 3, 9, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "___", 3, 2, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "___", 3, 6, false);
ssd1306_text_line_column(SSD1306_ADDRESS, "____", 3, 10, false);
display_text_line_column( "-", 3, 5, false);
display_text_line_column( "-", 3, 9, false);
display_text_line_column( "___", 3, 2, false);
display_text_line_column( "___", 3, 6, false);
display_text_line_column( "____", 3, 10, false);
int offset = 2;
for (int i = 0; i < 3; i++)
{
if (i < interface_report_tan_index)
{
ssd1306_chars(SSD1306_ADDRESS, &tan_buffer[i], 1, 3, i + offset, true);
display_chars( &tan_buffer[i], 1, 3, i + offset, true);
}
}
@ -139,7 +139,7 @@ void interface_report_display(void)
{
if (i < interface_report_tan_index)
{
ssd1306_chars(SSD1306_ADDRESS, &tan_buffer[i], 1, 3, i + offset, true);
display_chars( &tan_buffer[i], 1, 3, i + offset, true);
}
}
}
@ -151,26 +151,26 @@ void interface_report_display(void)
{
if (i < interface_report_tan_index)
{
ssd1306_chars(SSD1306_ADDRESS, &tan_buffer[i], 1, 3, i + offset, true);
display_chars( &tan_buffer[i], 1, 3, i + offset, true);
}
}
}
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_up, 8, 2, interface_report_tan_index * 8 + offset * 8, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_down, 8, 4, interface_report_tan_index * 8 + offset * 8, false);
display_data( display_gfx_arrow_up, 8, 2, interface_report_tan_index * 8 + offset * 8, false);
display_data( display_gfx_arrow_down, 8, 4, interface_report_tan_index * 8 + offset * 8, false);
ssd1306_chars(SSD1306_ADDRESS, &tan_buffer[interface_report_tan_index], 1, 3, interface_report_tan_index + offset, false);
display_chars( &tan_buffer[interface_report_tan_index], 1, 3, interface_report_tan_index + offset, false);
}
void interface_report_start(void)
{
interface_register_button_callback(INTERFACE_BUTTON_RST, &interface_report_rst);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_report_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_report_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_report_rht);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_report_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_report_dwn);
interface_register_button_callback(INTERFACE_BUTTON_MID, NULL);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_report_rst);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_report_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_report_lft);
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_register_command_callback(INTERFACE_COMMAND_MID, NULL);
interface_set_display_function(&interface_report_display);
ESP_LOGD(INTERFACE_LOG, "start report interface");

View File

@ -19,8 +19,8 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "ena-storage.h"
@ -62,12 +62,12 @@ void interface_settings_mid(void)
current_interface_settings_state = INTERFACE_SETTINGS_LOCALE;
}
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 3, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 5, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
ssd1306_clear_line(SSD1306_ADDRESS, 7, 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);
}
void interface_settings_up(void)
@ -103,30 +103,30 @@ void interface_settings_dwn(void)
void interface_settings_display(void)
{
ssd1306_menu_headline(SSD1306_ADDRESS, interface_get_label_text(&interface_text_headline_settings), true, 0);
display_menu_headline( interface_get_label_text(&interface_text_headline_settings), true, 0);
ssd1306_text_line_column(SSD1306_ADDRESS, interface_get_label_text(&interface_text_settings_locale), 3, 1, false);
display_text_line_column( interface_get_label_text(&interface_text_settings_locale), 3, 1, false);
ssd1306_text_line_column(SSD1306_ADDRESS, interface_get_label_text(&interface_text_settings_timezone), 6, 1, false);
display_text_line_column( interface_get_label_text(&interface_text_settings_timezone), 6, 1, false);
if (current_interface_settings_state == INTERFACE_SETTINGS_LOCALE)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_up, 8, 2, 12 * 8 + 4, false);
ssd1306_text_line_column(SSD1306_ADDRESS,
display_data( display_gfx_arrow_up, 8, 2, 12 * 8 + 4, false);
display_text_line_column(
interface_get_label_text(&interface_text_settings_locales[interface_get_locale()]), 3, 12, true);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_down, 8, 4, 12 * 8 + 4, false);
display_data( display_gfx_arrow_down, 8, 4, 12 * 8 + 4, false);
}
else
{
ssd1306_text_line_column(SSD1306_ADDRESS,
display_text_line_column(
interface_get_label_text(&interface_text_settings_locales[interface_get_locale()]), 3, 12, true);
}
if (current_interface_settings_state == INTERFACE_SETTINGS_TIMEZONE)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_up, 8, 5, 12 * 8 + 4, false);
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_down, 8, 7, 12 * 8 + 4, false);
display_data( display_gfx_arrow_up, 8, 5, 12 * 8 + 4, false);
display_data( display_gfx_arrow_down, 8, 7, 12 * 8 + 4, false);
}
}
@ -134,13 +134,13 @@ void interface_settings_start(void)
{
current_interface_settings_state = INTERFACE_SETTINGS_LOCALE;
interface_register_button_callback(INTERFACE_BUTTON_RST, &interface_settings_rst);
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_settings_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_settings_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_settings_rht);
interface_register_button_callback(INTERFACE_BUTTON_MID, &interface_settings_mid);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_settings_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_settings_dwn);
interface_register_command_callback(INTERFACE_COMMAND_RST, &interface_settings_rst);
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);
ESP_LOGD(INTERFACE_LOG, "start settings interface");

View File

@ -19,8 +19,8 @@
#include "esp_log.h"
#include "driver/gpio.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "wifi-controller.h"
#include "interface.h"
@ -113,13 +113,13 @@ void interface_wifi_dwn(void)
void interface_wifi_display(void)
{
ssd1306_menu_headline(SSD1306_ADDRESS, interface_get_label_text(&interface_text_headline_wifi), true, 0);
display_menu_headline( interface_get_label_text(&interface_text_headline_wifi), true, 0);
if (ap_count > 0)
{
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
ssd1306_clear_line(SSD1306_ADDRESS, 6, 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 + ap_index;
@ -127,48 +127,48 @@ void interface_wifi_display(void)
{
if (index == ap_selected)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, i * 2 + 2, 8, false);
display_data( display_gfx_arrow_right, 8, i * 2 + 2, 8, false);
}
if (sizeof(ap_info[i].ssid) > 0)
{
ssd1306_text_line_column(SSD1306_ADDRESS, (char *)ap_info[index].ssid, i * 2 + 2, 2, false);
display_text_line_column( (char *)ap_info[index].ssid, i * 2 + 2, 2, false);
}
else
{
ssd1306_text_line_column(SSD1306_ADDRESS, " / ", i * 2 + 2, 2, false);
display_text_line_column( " / ", i * 2 + 2, 2, false);
}
if (ap_info[index].rssi >= -67)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_wifi, 8, i * 2 + 2, 112, false);
display_data( display_gfx_wifi, 8, i * 2 + 2, 112, false);
}
else if (ap_info[index].rssi >= -80)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_wifi_low, 8, i * 2 + 2, 112, false);
display_data( display_gfx_wifi_low, 8, i * 2 + 2, 112, false);
}
else if (ap_info[index].rssi >= -90)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_wifi_lowest, 8, i * 2 + 2, 112, false);
display_data( display_gfx_wifi_lowest, 8, i * 2 + 2, 112, false);
}
}
}
}
else
{
ssd1306_text_line_column(SSD1306_ADDRESS, interface_get_label_text(&interface_text_wifi_scanning), 4, 1, false);
display_text_line_column( interface_get_label_text(&interface_text_wifi_scanning), 4, 1, false);
}
}
void interface_wifi_start(void)
{
interface_register_button_callback(INTERFACE_BUTTON_SET, &interface_wifi_set);
interface_register_button_callback(INTERFACE_BUTTON_LFT, &interface_wifi_lft);
interface_register_button_callback(INTERFACE_BUTTON_RHT, &interface_wifi_rht);
interface_register_button_callback(INTERFACE_BUTTON_MID, &interface_wifi_mid);
interface_register_button_callback(INTERFACE_BUTTON_UP, &interface_wifi_up);
interface_register_button_callback(INTERFACE_BUTTON_DWN, &interface_wifi_dwn);
interface_register_button_callback(INTERFACE_BUTTON_RST, NULL);
interface_register_command_callback(INTERFACE_COMMAND_SET, &interface_wifi_set);
interface_register_command_callback(INTERFACE_COMMAND_LFT, &interface_wifi_lft);
interface_register_command_callback(INTERFACE_COMMAND_RHT, &interface_wifi_rht);
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_set_display_function(&interface_wifi_display);

View File

@ -17,57 +17,31 @@
#include "driver/gpio.h"
#include "esp_log.h"
#include "ssd1306.h"
#include "ssd1306-gfx.h"
#include "display.h"
#include "display-gfx.h"
#include "interface.h"
static int old_button_states[GPIO_PIN_COUNT];
static int button_states[GPIO_PIN_COUNT];
static interface_button_callback button_callbacks[GPIO_PIN_COUNT];
static interface_command_callback command_callbacks[INTERFACE_COMMANDS_SIZE];
static interface_display_function current_display_function;
void interface_register_button_callback(int button_gpio, interface_button_callback callback)
void interface_register_command_callback(interface_command_t command, interface_command_callback callback)
{
button_callbacks[button_gpio] = callback;
command_callbacks[command] = callback;
}
void interface_set_display_function(interface_display_function display_function)
{
ssd1306_clear(SSD1306_ADDRESS);
display_clear();
current_display_function = display_function;
}
void interface_input_check(uint8_t gpio)
void interface_execute_command(interface_command_t command)
{
button_states[gpio] = gpio_get_level(gpio);
if (old_button_states[gpio] != 0 && old_button_states[gpio] != 1)
if (command_callbacks[command] != NULL)
{
old_button_states[gpio] = 1;
}
if (button_states[gpio] == 0 && button_states[gpio] != old_button_states[gpio] && button_callbacks[gpio] != NULL)
{
ssd1306_clear(SSD1306_ADDRESS);
(*button_callbacks[gpio])();
}
old_button_states[gpio] = button_states[gpio];
}
void interface_input_task(void *pvParameter)
{
while (1)
{
interface_input_check(INTERFACE_BUTTON_RST);
interface_input_check(INTERFACE_BUTTON_SET);
interface_input_check(INTERFACE_BUTTON_LFT);
interface_input_check(INTERFACE_BUTTON_RHT);
interface_input_check(INTERFACE_BUTTON_MID);
interface_input_check(INTERFACE_BUTTON_UP);
interface_input_check(INTERFACE_BUTTON_DWN);
vTaskDelay(20 / portTICK_PERIOD_MS);
display_clear();
(*command_callbacks[command])();
}
}
@ -85,30 +59,16 @@ void interface_display_task(void *pvParameter)
void interface_start(void)
{
gpio_config_t io_conf;
io_conf.pin_bit_mask = (1ULL << INTERFACE_BUTTON_RST) | (1ULL << INTERFACE_BUTTON_SET) |
(1ULL << INTERFACE_BUTTON_MID) | (1ULL << INTERFACE_BUTTON_RHT) |
(1ULL << INTERFACE_BUTTON_LFT) | (1ULL << INTERFACE_BUTTON_DWN) |
(1ULL << INTERFACE_BUTTON_UP);
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);
xTaskCreate(&interface_input_task, "interface_input_task", 4096, NULL, 5, NULL);
xTaskCreate(&interface_display_task, "interface_display_task", 4096, NULL, 5, NULL);
// init label
interface_init_label();
ssd1306_start(SSD1306_ADDRESS);
ssd1306_clear(SSD1306_ADDRESS);
display_start();
display_clear();
for (int i = 0; i < 8; i++)
{
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_logo[i], 64, i, 32, false);
display_data(display_gfx_logo[i], 64, i, 32, false);
}
}

View File

@ -24,18 +24,27 @@
#define INTERFACE_LOG "INTERFACE" // TAG for Logging
#define INTERFACE_BUTTON_RST GPIO_NUM_32
#define INTERFACE_BUTTON_SET GPIO_NUM_33
#define INTERFACE_BUTTON_MID GPIO_NUM_25
#define INTERFACE_BUTTON_RHT GPIO_NUM_26
#define INTERFACE_BUTTON_LFT GPIO_NUM_27
#define INTERFACE_BUTTON_DWN GPIO_NUM_14
#define INTERFACE_BUTTON_UP GPIO_NUM_12
#define INTERFACE_FORMAT_TIME "%X"
#define INTERFACE_NUM_LOCALE 2
/**
* @brief available commands
*/
typedef enum
{
INTERFACE_COMMAND_RST = 0,
INTERFACE_COMMAND_SET,
INTERFACE_COMMAND_MID,
INTERFACE_COMMAND_RHT,
INTERFACE_COMMAND_LFT,
INTERFACE_COMMAND_DWN,
INTERFACE_COMMAND_UP,
INTERFACE_COMMANDS_SIZE,
} interface_command_t;
/**
* @brief available locales
*/
@ -78,9 +87,9 @@ interface_label_t interface_texts_weekday[7];
interface_label_t interface_texts_month[12];
/**
* @brief callback function for button press
* @brief callback function for command input (button press)
*/
typedef void (*interface_button_callback)(void);
typedef void (*interface_command_callback)(void);
/**
* @brief current display function
@ -93,7 +102,7 @@ typedef void (*interface_display_function)(void);
* @param[in] text the text from input
* @param[in] cursor current cursor position
*/
typedef void (*interface_input_callback)(char *text, uint8_t cursor);
typedef void (*interface_text_callback)(char *text, uint8_t cursor);
/**
* @brief init label
@ -123,12 +132,19 @@ interface_locale_t interface_get_locale(void);
void interface_set_locale(interface_locale_t locale);
/**
* @brief register a callback function for button event
* @brief register a callback function for command event
*
* @param[in] button_gpio id of the button to listen to
* @param[in] command id of the command to listen to
* @param[in] callback callback function
*/
void interface_register_button_callback(int button_gpio, interface_button_callback callback);
void interface_register_command_callback(interface_command_t command, interface_command_callback callback);
/**
* @brief execute a command
*
* @param[in] command id of the command to trigger
*/
void interface_execute_command(interface_command_t command);
/**
* @brief set the display function
@ -181,7 +197,7 @@ void interface_settings_start(void);
* @param[in] callback_set function to call on SET
* @param[in] limit max character allowed (0=255)
*/
void interface_input(interface_input_callback callback_rst, interface_input_callback callback_set, uint8_t limit);
void interface_input(interface_text_callback callback_rst, interface_text_callback callback_set, uint8_t limit);
/**
* @brief set text for input interface

View File

@ -1,22 +0,0 @@
Copyright 2013-2014 RAD Game Tools and Valve Software
Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ idf_component_register(
SRCS
"ds3231.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
PRIV_REQUIRES
rtc
i2c-main
)

View File

@ -17,6 +17,7 @@
#include "driver/i2c.h"
#include "esp_log.h"
#include "rtc.h"
#include "i2c-main.h"
#include "ds3231.h"
@ -31,7 +32,7 @@ uint8_t ds3231_bcd2dec(uint8_t value)
return ((value / 16 * 10) + (value % 16));
}
void ds3231_get_time(struct tm *time)
void rtc_get_time(struct tm *time)
{
if (!i2c_is_initialized())
{
@ -80,7 +81,7 @@ void ds3231_get_time(struct tm *time)
time->tm_isdst = 0;
}
void ds3231_set_time(struct tm *time)
void rtc_set_time(struct tm *time)
{
if (!i2c_is_initialized())
{

View File

@ -71,14 +71,4 @@
#define DS3231_12_HOUR_MASK 0x1F
#define DS3231_MONTH_MASK 0x1F
/**
* @brief Read time from DS3231
*/
void ds3231_get_time(struct tm *time);
/**
* @brief Write time to DS3231
*/
void ds3231_set_time(struct tm *time);
#endif

View File

@ -1,5 +1,4 @@
idf_component_register(
SRCS
"miniz.c"
INCLUDE_DIRS "."
)
)

35
components/rtc/rtc.h Normal file
View File

@ -0,0 +1,35 @@
// 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 interface for RTC
*
*/
#ifndef _rtc_H_
#define _rtc_H_
#include <time.h>
/**
* @brief Read time
*/
void rtc_get_time(struct tm *time);
/**
* @brief Write time
*/
void rtc_set_time(struct tm *time);
#endif

View File

@ -1,183 +0,0 @@
// 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 SSD1306 display
*
*/
#ifndef _ssd1306_H_
#define _ssd1306_H_
#include "esp_system.h"
#define SSD1306_ADDRESS (0x3C)
#define SSD1306_COLUMNS (128)
#define SSD1306_PAGES (8)
// Write mode for I2C https://robotcantalk.blogspot.com/2015/03/interfacing-arduino-with-ssd1306-driven.html
#define SSD1306_CONTROL_CMD_BYTE (0x80)
#define SSD1306_CONTROL_CMD_STREAM (0x00)
#define SSD1306_CONTROL_DATA_BYTE (0xC0)
#define SSD1306_CONTROL_DATA_STREAM (0x40)
// 1. Fundamental Command Table
#define SSD1306_CMD_CONTRAST (0x81)
#define SSD1306_CMD_RAM (0xA4)
#define SSD1306_CMD_ALL_ON (0xA5)
#define SSD1306_CMD_NORMAL (0xA6)
#define SSD1306_CMD_INVERSE (0xA7)
#define SSD1306_CMD_OFF (0xAE)
#define SSD1306_CMD_ON (0xAF)
// 2. Scrolling Command Table
#define SSD1306_CMD_SCROLL_HORI_RIGHT (0x26)
#define SSD1306_CMD_SCROLL_HORI_LEFT (0x27)
#define SSD1306_CMD_SCROLL_VERT_RIGHT (0x29)
#define SSD1306_CMD_SCROLL_VERT_LEFT (0x2A)
#define SSD1306_CMD_SCROLL_STOP (0x2E)
#define SSD1306_CMD_SCROLL_START (0x2F)
#define SSD1306_CMD_SCROLL_VERT_AREA (0xA3)
// 3. Addressing Setting Command Table
#define SSD1306_CMD_COLUMN_LOW (0x00)
#define SSD1306_CMD_COLUMN_HIGH (0x10)
#define SSD1306_CMD_MEMORY_MODE (0x20)
#define SSD1306_CMD_COLUMN_ADDRESS (0x21)
#define SSD1306_CMD_PAGE_ADDRESS (0x22)
#define SSD1306_CMD_PAGE (0xB0)
// 4. Hardware Configuration (Panel resolution & layout related) Command Table
#define SSD1306_CMD_START_LINE (0x40)
#define SSD1306_CMD_SEGMENT_LOW (0xA0)
#define SSD1306_CMD_SEGMENT_HIGH (0xA1)
#define SSD1306_CMD_MULTIPLEX_RATIO (0xA8)
#define SSD1306_CMD_SCAN_DIRECTION_NORMAL (0xC0)
#define SSD1306_CMD_SCAN_DIRECTION_REMAPPED (0xC8)
#define SSD1306_CMD_OFFSET (0xD3)
#define SSD1306_CMD_COM_PINS (0xDA)
// 5. Timing & Driving Scheme Setting Command Table
#define SSD1306_CMD_CLOCK (0xD5)
#define SSD1306_CMD_PRE_CHARGE_PERIOD (0xD9)
#define SSD1306_CMD_VCOMH (0xDB)
#define SSD1306_CMD_NOP (0xE3)
// 1. Charge Pump Command Table
#define SSD1306_CMD_CHARGE_PUMP (0x8D)
void ssd1306_utf8_to_ascii(char *input, char *output);
/**
* @brief initalize SSD1306 with I2C at given address
*
* @param[in] i2address I2C address of SSD1306
*/
void ssd1306_start(uint8_t i2address);
/**
* @brief clear the display
*
* @param[in] i2address I2C address of SSD1306
* @param[in] line the line to clear
* @param[in] invert if true, image is inverted
*/
void ssd1306_clear_line(uint8_t i2address, uint8_t line, bool invert);
/**
* @brief clear the display
*
* @param[in] i2address I2C address of SSD1306
*/
void ssd1306_clear(uint8_t i2address);
/**
* @brief set display on or offf
*
* @param[in] i2address I2C address of SSD1306
* @param[in] on true if display on, false if display off
*/
void ssd1306_on(uint8_t i2address, bool on);
/**
*
*/
uint8_t *ssd1306_text_to_data(char *text, size_t text_length, size_t *length);
/**
* @brief write raw bytes to display line at starting column
*
* @param[in] i2address I2C address of SSD1306
* @param[in] data bytes to display
* @param[in] length length of data
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write chars to display
*
* @param[in] i2address I2C address of SSD1306
* @param[in] text text to display
* @param[in] length length of text
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void ssd1306_chars(uint8_t i2address, char *text, size_t length, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write text to display line at starting column
*
* @param[in] i2address I2C address of SSD1306
* @param[in] text text to display
* @param[in] line the line to write to
* @param[in] offset number of offset chars to start
* @param[in] invert if true, image is inverted
*/
void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8_t offset, bool invert);
/**
* @brief write text to display line
*
* @param[in] i2address I2C address of SSD1306
* @param[in] text text to display
* @param[in] line the line to write to
* @param[in] invert if true, image is inverted
*/
void ssd1306_text_line(uint8_t i2address, char *text, uint8_t line, bool invert);
/**
* @brief display a button element
*
* @param[in] i2address I2C address of SSD1306
* @param[in] text button text
* @param[in] selected is button selected
* @param[in] primary is button primary
*/
void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool primary);
/**
* @brief display a menu headline
*
* @param[in] i2address I2C address of SSD1306
* @param[in] text headline text
* @param[in] arrows if left right arrows should be displays
* @param[in] line line the line to write to
*/
void ssd1306_menu_headline(uint8_t i2address, char *text, bool arrows, uint8_t line);
#endif

View File

@ -26,11 +26,14 @@
#include "ena-bluetooth-advertise.h"
#include "ena-bluetooth-scan.h"
#include "ena-cwa.h"
#include "interface.h"
#include "ds3231.h"
#include "ssd1306.h"
#include "interface.h"
#include "button-input.h"
#include "rtc.h"
#include "wifi-controller.h"
#include "sdkconfig.h"
void app_main(void)
@ -51,9 +54,9 @@ void app_main(void)
// start interface
interface_start();
// set system time from DS3231
// set system time from RTC
struct tm rtc_time;
ds3231_get_time(&rtc_time);
rtc_get_time(&rtc_time);
time_t curtime = mktime(&rtc_time);
struct timeval tv = {0};
@ -69,6 +72,9 @@ void app_main(void)
// start with main interface
interface_main_start();
// start button input
button_input_start();
while (1)
{
ena_run();