mirror of
https://github.com/Lurkars/esp-ena.git
synced 2024-12-22 21:25:19 +01:00
add/update interface
This commit is contained in:
parent
628ee8fe39
commit
b473e88be1
4
.gitignore
vendored
4
.gitignore
vendored
@ -41,4 +41,6 @@ build
|
||||
dependencies.lock
|
||||
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
sdkconfig.old
|
||||
|
||||
.local
|
15
README.md
15
README.md
@ -19,23 +19,24 @@ The following acronyms will be used in code and comments:
|
||||
* BLE privacy (change random MAC address in random interval)
|
||||
* permanent storage on flash of last keys, beacons and exposures (storage is limited, see [storage math](#some-storage-math) for details)
|
||||
* parsing of Exposure Key export binaries as defined in [Exposure Key export file format and verification](https://developers.google.com/android/exposure-notifications/exposure-key-file-format) (big thanks to [nanopb](https://github.com/nanopb/nanopb) for making this easier than I thought!)
|
||||
* calculating exposure risks/scores (after adding reported keys and storing exposure information) as defined in [ENExposureConfiguration (Apple)](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration)
|
||||
* calculating exposure risks/scores (after adding reported keys and storing exposure information) as defined in [ENExposureConfiguration (Apple)](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration/calculating_the_exposure_risk_value_in_exposurenotification_version_1)
|
||||
|
||||
Additional features for full ENA device
|
||||
* RTC support with DS3231 (for correct system time)
|
||||
* display support with SSD1306
|
||||
* interface to
|
||||
* set time
|
||||
* interface with a 7 button control (joystick up,down,left,right,enter,cancel,ok) to
|
||||
* show exposure status
|
||||
* set time
|
||||
* connect to wifi
|
||||
* delete data
|
||||
* set language
|
||||
* enter tan for infection status (dummy for now)
|
||||
|
||||
### Features in development
|
||||
* automatically receive Exposure Key export from web (started with [Corona Warn App](https://github.com/corona-warn-app))
|
||||
* send infected status (will test [Corona Warn App](https://github.com/corona-warn-app))
|
||||
* battery support
|
||||
* 3d print case
|
||||
* interface to
|
||||
* delete data
|
||||
* report infection
|
||||
|
||||
### Limitations/Problems/Questions
|
||||
* WiFi or other external connection needed for infections status (auto-connect to open WiFis?)
|
||||
@ -71,7 +72,7 @@ So on average it is possible to meet 38 (24 on a lower boundary) different devic
|
||||
|
||||
### Hardware Required
|
||||
|
||||
For now just an ESP32 is required. DS3231 RTC and SSD1306 Display are required for a complete device.
|
||||
For base functionality just an ESP32 is required. DS3231 RTC, SSD1306 Display and 7 buttons are required for a complete device.
|
||||
|
||||
### Configure the project
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"ds3231.c"
|
||||
INCLUDE_DIRS "include"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
i2c-main
|
||||
)
|
@ -1,11 +1,12 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"ena-cwa.c"
|
||||
INCLUDE_DIRS "include"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
esp_http_client
|
||||
miniz
|
||||
ena
|
||||
wifi-controller
|
||||
EMBED_FILES
|
||||
"certs/telekom.pem"
|
||||
)
|
@ -12,15 +12,22 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
|
||||
#include "time.h"
|
||||
#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 "wifi-controller.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");
|
||||
|
||||
extern const uint8_t telekom_pem_start[] asm("_binary_telekom_pem_start");
|
||||
extern const uint8_t telekom__pem_end[] asm("_binary_telekom_pem_end");
|
||||
@ -40,7 +47,7 @@ esp_err_t ena_cwa_http_event_handler(esp_http_client_event_t *evt)
|
||||
output_len = 0;
|
||||
if (output_buffer == NULL)
|
||||
{
|
||||
ESP_LOGE(ENA_CWA_LOG, "Failed to allocate memory for output buffer");
|
||||
ESP_LOGE(ENA_CWA_LOG, "Failed to allocate memory for output buffer, memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
@ -53,62 +60,14 @@ esp_err_t ena_cwa_http_event_handler(esp_http_client_event_t *evt)
|
||||
if (output_buffer != NULL)
|
||||
{
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
|
||||
size_t zip_image_size = esp_http_client_get_content_length(evt->client);
|
||||
// const char *file_name = "export.sig";
|
||||
|
||||
/*
|
||||
mz_zip_archive zip_archive;
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
mz_uint32 file_index;
|
||||
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
mz_zip_reader_init_mem(&zip_archive, output_buffer, sizeof(output_buffer), 0);
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
mz_zip_reader_locate_file_v2(&zip_archive, file_name, NULL, 0, &file_index);
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
mz_zip_reader_file_stat(&zip_archive, file_index, &file_stat);
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
size_t extracted_size = file_stat.m_uncomp_size;
|
||||
|
||||
ESP_LOGD(ENA_CWA_LOG, "size of export.sig: %d", extracted_size);
|
||||
|
||||
char *file_buffer = malloc(extracted_size);
|
||||
|
||||
mz_zip_reader_extract_to_mem(&zip_archive, file_index, file_buffer, extracted_size, 0);
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory: %d kB", (xPortGetFreeHeapSize() / 1024));
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP(ENA_CWA_LOG, file_buffer, extracted_size, ESP_LOG_DEBUG);
|
||||
|
||||
free(file_buffer);
|
||||
*/
|
||||
|
||||
mz_zip_archive zip_archive;
|
||||
ESP_LOGD(ENA_CWA_LOG, "1 memory: %d kB (min %d kB)", (esp_get_free_heap_size() / 1024), (esp_get_minimum_free_heap_size() / 1024));
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
ESP_LOGD(ENA_CWA_LOG, "2 memory: %d kB (min %d kB)", (esp_get_free_heap_size() / 1024), (esp_get_minimum_free_heap_size() / 1024));
|
||||
mz_zip_reader_init_mem(&zip_archive, output_buffer, zip_image_size, 0);
|
||||
ESP_LOGD(ENA_CWA_LOG, "3 memory: %d kB (min %d kB)", (esp_get_free_heap_size() / 1024), (esp_get_minimum_free_heap_size() / 1024));
|
||||
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
|
||||
ESP_LOGD(ENA_CWA_LOG, "4 memory: %d kB (min %d kB)", (esp_get_free_heap_size() / 1024), (esp_get_minimum_free_heap_size() / 1024));
|
||||
/*
|
||||
p = mz_zip_reader_extract_file_to_heap(&zip_archive, file_name, &extracted_size, 0);
|
||||
ESP_LOGD(ENA_CWA_LOG, "4 memory: %d kB", (esp_get_free_heap_size() / 1024));
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
ESP_LOG_BUFFER_HEXDUMP(ENA_CWA_LOG, p, extracted_size, ESP_LOG_DEBUG);
|
||||
free(p);
|
||||
*/
|
||||
|
||||
free(output_buffer);
|
||||
output_buffer = NULL;
|
||||
output_len = 0;
|
||||
ESP_LOGD(ENA_CWA_LOG, "memory freed: %d kB (min %d kB)", (esp_get_free_heap_size() / 1024), (esp_get_minimum_free_heap_size() / 1024));
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(ena_exposure_check_export(export_bin_start, (export_bin_end - export_bin_start)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ESP_FAIL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -117,7 +76,7 @@ esp_err_t ena_cwa_http_event_handler(esp_http_client_event_t *evt)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ena_cwa_receive_keys(char *date_string)
|
||||
esp_err_t ena_cwa_receive_keys(char *date_string)
|
||||
{
|
||||
char *url = malloc(strlen(ENA_CWA_KEYFILES_URL) + strlen(date_string));
|
||||
sprintf(url, ENA_CWA_KEYFILES_URL, date_string);
|
||||
@ -126,6 +85,8 @@ void ena_cwa_receive_keys(char *date_string)
|
||||
.cert_pem = (char *)telekom_pem_start,
|
||||
.event_handler = ena_cwa_http_event_handler,
|
||||
};
|
||||
|
||||
ESP_LOGD(ENA_CWA_LOG, "start memory: %d kB, %s", (xPortGetFreeHeapSize() / 1024), date_string);
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
|
||||
@ -136,7 +97,31 @@ void ena_cwa_receive_keys(char *date_string)
|
||||
esp_http_client_get_status_code(client),
|
||||
content_length);
|
||||
}
|
||||
// free(url);
|
||||
free(url);
|
||||
esp_http_client_close(client);
|
||||
esp_http_client_cleanup(client);
|
||||
return err;
|
||||
}
|
||||
|
||||
void ena_cwa_run(void)
|
||||
{
|
||||
|
||||
static time_t current_time = 0;
|
||||
static uint32_t last_check = 0;
|
||||
current_time = time(NULL);
|
||||
last_check = ena_storage_read_last_exposure_date();
|
||||
if ((((uint32_t)current_time) - last_check) / (60 * 60 * 24) > 0 && wifi_controller_connection() != NULL)
|
||||
{
|
||||
char date_string[11];
|
||||
struct tm *time_info;
|
||||
time_info = localtime(¤t_time);
|
||||
time_info->tm_mday--;
|
||||
strftime(date_string, 11, "%Y-%m-%d", time_info);
|
||||
esp_err_t err = ena_cwa_receive_keys(date_string);
|
||||
if (err == ESP_OK)
|
||||
{
|
||||
ena_storage_write_last_exposure_date((uint32_t)current_time);
|
||||
ena_exposure_summary(ena_exposure_default_config());
|
||||
}
|
||||
}
|
||||
}
|
@ -22,15 +22,22 @@
|
||||
#ifndef _ena_CWA_H_
|
||||
#define _ena_CWA_H_
|
||||
|
||||
#define ENA_CWA_LOG "ESP-ENA-corona-warn-app" // TAG for Logging
|
||||
#include "esp_err.h"
|
||||
|
||||
#define ENA_CWA_KEYFILES_URL "http://svc90.main.px.t-online.de/version/v1/diagnosis-keys/country/DE/date/%s"
|
||||
#define ENA_CWA_LOG "ESP-ENA-cwa" // TAG for Logging
|
||||
|
||||
#define ENA_CWA_KEYFILES_URL "https://svc90.main.px.t-online.de/version/v1/diagnosis-keys/country/DE/date/%s"
|
||||
|
||||
/**
|
||||
* @brief fetch key export for given date
|
||||
*
|
||||
* @param[in] date_string the date to fetch the data for
|
||||
*/
|
||||
void ena_cwa_receive_keys(char *date_string);
|
||||
esp_err_t ena_cwa_receive_keys(char *date_string);
|
||||
|
||||
/**
|
||||
* @brief start ena CWA
|
||||
*/
|
||||
void ena_cwa_run(void);
|
||||
|
||||
#endif
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "ena-exposure.h"
|
||||
|
||||
static ena_exposure_summary_t *current_summary;
|
||||
|
||||
static ena_exposure_config_t DEFAULT_ENA_EXPOSURE_CONFIG = {
|
||||
// transmission_risk_values
|
||||
{
|
||||
@ -77,14 +79,13 @@ static ena_exposure_config_t DEFAULT_ENA_EXPOSURE_CONFIG = {
|
||||
static const char kFileHeader[] = "EK Export v1 ";
|
||||
static size_t kFileHeaderSize = sizeof(kFileHeader) - 1;
|
||||
|
||||
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");
|
||||
|
||||
int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
int ena_exposure_transmission_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
{
|
||||
int score = 1;
|
||||
score *= config->transmission_risk_values[params.report_type];
|
||||
return config->transmission_risk_values[params.report_type];
|
||||
}
|
||||
|
||||
int ena_exposure_duration_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
{
|
||||
// calc duration level
|
||||
int duration_level = MINUTES_0;
|
||||
if (params.duration > 0)
|
||||
@ -118,8 +119,12 @@ int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_paramete
|
||||
duration_level = MINUTES_LONGER;
|
||||
}
|
||||
}
|
||||
score *= config->duration_risk_values[duration_level];
|
||||
|
||||
return config->duration_risk_values[duration_level];
|
||||
}
|
||||
|
||||
int ena_exposure_days_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
{
|
||||
// calc days level
|
||||
int days_level = DAYS_14;
|
||||
|
||||
@ -152,8 +157,11 @@ int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_paramete
|
||||
days_level = DAYS_13;
|
||||
}
|
||||
|
||||
score *= config->days_risk_values[days_level];
|
||||
return config->days_risk_values[days_level];
|
||||
}
|
||||
|
||||
int ena_exposure_attenuation_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
{
|
||||
// calc attenuation level
|
||||
int attenuation_level = ATTENUATION_73;
|
||||
|
||||
@ -186,7 +194,19 @@ int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_paramete
|
||||
attenuation_level = ATTENUATION_63;
|
||||
}
|
||||
|
||||
score *= config->attenuation_risk_values[attenuation_level];
|
||||
return config->attenuation_risk_values[attenuation_level];
|
||||
}
|
||||
|
||||
int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params)
|
||||
{
|
||||
int score = 1;
|
||||
score *= ena_exposure_transmission_risk_score(config, params);
|
||||
|
||||
score *= ena_exposure_duration_risk_score(config, params);
|
||||
|
||||
score *= ena_exposure_days_risk_score(config, params);
|
||||
|
||||
score *= ena_exposure_attenuation_risk_score(config, params);
|
||||
|
||||
if (score > 255)
|
||||
{
|
||||
@ -196,22 +216,25 @@ int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_paramete
|
||||
return score;
|
||||
}
|
||||
|
||||
void ena_exposure_summary(ena_exposure_config_t *config, ena_exposure_summary_t *summary)
|
||||
void ena_exposure_summary(ena_exposure_config_t *config)
|
||||
{
|
||||
// XXX TEST key export (should be called on other location though)
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(ena_exposure_check_export(export_bin_start, (export_bin_end - export_bin_start)));
|
||||
|
||||
uint32_t count = ena_storage_exposure_information_count();
|
||||
uint32_t current_time = (uint32_t)time(NULL);
|
||||
|
||||
summary->days_since_last_exposure = INT_MAX;
|
||||
summary->max_risk_score = 0;
|
||||
summary->risk_score_sum = 0;
|
||||
summary->num_exposures = count;
|
||||
if (current_summary == NULL)
|
||||
{
|
||||
current_summary = malloc(sizeof(ena_exposure_summary_t));
|
||||
}
|
||||
|
||||
current_summary->last_update = ena_storage_read_last_exposure_date();
|
||||
current_summary->days_since_last_exposure = INT_MAX;
|
||||
current_summary->max_risk_score = 0;
|
||||
current_summary->risk_score_sum = 0;
|
||||
current_summary->num_exposures = count;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
summary->days_since_last_exposure = -1;
|
||||
current_summary->days_since_last_exposure = -1;
|
||||
}
|
||||
|
||||
ena_exposure_information_t exposure_info;
|
||||
@ -220,21 +243,31 @@ void ena_exposure_summary(ena_exposure_config_t *config, ena_exposure_summary_t
|
||||
{
|
||||
ena_storage_get_exposure_information(i, &exposure_info);
|
||||
params.days = (current_time - exposure_info.day) / (60 * 60 * 24); // difference in days
|
||||
if (params.days < summary->days_since_last_exposure)
|
||||
if (params.days < current_summary->days_since_last_exposure)
|
||||
{
|
||||
summary->days_since_last_exposure = params.days;
|
||||
current_summary->days_since_last_exposure = params.days;
|
||||
}
|
||||
params.duration = exposure_info.duration_minutes;
|
||||
params.attenuation = exposure_info.typical_attenuation;
|
||||
int score = ena_exposure_risk_score(config, params);
|
||||
if (score > summary->max_risk_score)
|
||||
if (score > current_summary->max_risk_score)
|
||||
{
|
||||
summary->max_risk_score = score;
|
||||
current_summary->max_risk_score = score;
|
||||
}
|
||||
summary->risk_score_sum += score;
|
||||
current_summary->risk_score_sum += score;
|
||||
}
|
||||
}
|
||||
|
||||
ena_exposure_summary_t *ena_exposure_current_summary(void)
|
||||
{
|
||||
if (current_summary == NULL)
|
||||
{
|
||||
ena_exposure_summary(ena_exposure_default_config());
|
||||
}
|
||||
|
||||
return current_summary;
|
||||
}
|
||||
|
||||
ena_exposure_config_t *ena_exposure_default_config(void)
|
||||
{
|
||||
return &DEFAULT_ENA_EXPOSURE_CONFIG;
|
||||
|
@ -22,7 +22,8 @@
|
||||
|
||||
#define BLOCK_SIZE (4096)
|
||||
|
||||
const int ENA_STORAGE_TEK_COUNT_ADDRESS = (ENA_STORAGE_START_ADDRESS); // starting address for TEK COUNT
|
||||
const int ENA_STORAGE_LAST_EXPOSURE_DATE_ADDRESS = (ENA_STORAGE_START_ADDRESS);
|
||||
const int ENA_STORAGE_TEK_COUNT_ADDRESS = (ENA_STORAGE_LAST_EXPOSURE_DATE_ADDRESS + sizeof(uint32_t));
|
||||
const int ENA_STORAGE_TEK_START_ADDRESS = (ENA_STORAGE_TEK_COUNT_ADDRESS + sizeof(uint32_t));
|
||||
const int ENA_STORAGE_EXPOSURE_INFORMATION_COUNT_ADDRESS = (ENA_STORAGE_TEK_START_ADDRESS + sizeof(ena_tek_t) * ENA_STORAGE_TEK_MAX);
|
||||
const int ENA_STORAGE_EXPOSURE_INFORMATION_START_ADDRESS = (ENA_STORAGE_EXPOSURE_INFORMATION_COUNT_ADDRESS + sizeof(uint32_t));
|
||||
@ -144,6 +145,18 @@ void ena_storage_shift_delete(size_t address, size_t end_address, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ena_storage_read_last_exposure_date(void)
|
||||
{
|
||||
uint32_t timestamp = 0;
|
||||
ena_storage_read(ENA_STORAGE_LAST_EXPOSURE_DATE_ADDRESS, ×tamp, sizeof(uint32_t));
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void ena_storage_write_last_exposure_date(uint32_t timestamp)
|
||||
{
|
||||
ena_storage_write(ENA_STORAGE_LAST_EXPOSURE_DATE_ADDRESS, ×tamp, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uint32_t ena_storage_read_last_tek(ena_tek_t *tek)
|
||||
{
|
||||
uint32_t tek_count = 0;
|
||||
@ -298,6 +311,7 @@ void ena_storage_erase(void)
|
||||
ESP_LOGI(ENA_STORAGE_LOG, "erased partition %s!", ENA_STORAGE_PARTITION_NAME);
|
||||
|
||||
uint32_t count = 0;
|
||||
ena_storage_write(ENA_STORAGE_LAST_EXPOSURE_DATE_ADDRESS, &count, sizeof(uint32_t));
|
||||
ena_storage_write(ENA_STORAGE_TEK_COUNT_ADDRESS, &count, sizeof(uint32_t));
|
||||
ena_storage_write(ENA_STORAGE_EXPOSURE_INFORMATION_COUNT_ADDRESS, &count, sizeof(uint32_t));
|
||||
ena_storage_write(ENA_STORAGE_TEMP_BEACONS_COUNT_ADDRESS, &count, sizeof(uint32_t));
|
||||
|
@ -91,6 +91,11 @@ void ena_start(void)
|
||||
ena_storage_erase();
|
||||
#endif
|
||||
|
||||
if (ena_storage_read_last_exposure_date() == 0xFFFFFFFF)
|
||||
{
|
||||
ena_storage_erase();
|
||||
}
|
||||
|
||||
// init NVS for BLE
|
||||
esp_err_t ret;
|
||||
ret = nvs_flash_init();
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define _ena_EXPOSURE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "ena-crypto.h"
|
||||
|
||||
#define ENA_EXPOSURE_LOG "ESP-ENA-exposure" // TAG for Logging
|
||||
@ -135,6 +135,7 @@ typedef struct __attribute__((__packed__))
|
||||
*/
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint32_t last_update; // timestamp of last update of exposure data
|
||||
int days_since_last_exposure; // Number of days since the most recent exposure.
|
||||
int num_exposures; // Number of all exposure information
|
||||
int max_risk_score; // max. risk score of all exposure information
|
||||
@ -142,10 +143,52 @@ typedef struct __attribute__((__packed__))
|
||||
} ena_exposure_summary_t;
|
||||
|
||||
/**
|
||||
* @brief calculate risk score
|
||||
* @brief calculate transmission risk score
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating score
|
||||
* @param[in] params the exposure parameter to calculate with
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int ena_exposure_transmission_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params);
|
||||
|
||||
/**
|
||||
* @brief calculate duration risk score
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating score
|
||||
* @param[in] params the exposure parameter to calculate with
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int ena_exposure_duration_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params);
|
||||
|
||||
/**
|
||||
* @brief calculate days risk score
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating score
|
||||
* @param[in] params the exposure parameter to calculate with
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int ena_exposure_days_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params);
|
||||
|
||||
/**
|
||||
* @brief calculate attenuation risk score
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating score
|
||||
* @param[in] params the exposure parameter to calculate with
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int ena_exposure_attenuation_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params);
|
||||
|
||||
/**
|
||||
* @brief calculate overall risk score
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating score
|
||||
* @param[in] params the exposure parameter to calculate with
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_parameter_t params);
|
||||
|
||||
@ -153,12 +196,22 @@ int ena_exposure_risk_score(ena_exposure_config_t *config, ena_exposure_paramete
|
||||
* @brief returns the current exposure summary
|
||||
*
|
||||
* @param[in] config the exposure configuration used for calculating scores
|
||||
* @param[out] summary pointer to exposure summary to write to
|
||||
*/
|
||||
void ena_exposure_summary(ena_exposure_config_t *config, ena_exposure_summary_t *summary);
|
||||
void ena_exposure_summary(ena_exposure_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief return the current exposure summary
|
||||
*
|
||||
* @return
|
||||
* ena_exposure_summary_t pointer to the current exposure summary
|
||||
*/
|
||||
ena_exposure_summary_t *ena_exposure_current_summary(void);
|
||||
|
||||
/**
|
||||
* @brief return a default exposure configuration
|
||||
*
|
||||
* @return
|
||||
* ena_exposure_config_t default exposure configuration
|
||||
*/
|
||||
ena_exposure_config_t *ena_exposure_default_config(void);
|
||||
|
||||
|
@ -22,11 +22,11 @@
|
||||
|
||||
#include "ena-crypto.h"
|
||||
|
||||
#define ENA_STORAGE_LOG "ESP-ENA-storage" // TAG for Logging
|
||||
#define ENA_STORAGE_PARTITION_NAME (CONFIG_ENA_STORAGE_PARTITION_NAME) // name of partition to use for storing
|
||||
#define ENA_STORAGE_START_ADDRESS (CONFIG_ENA_STORAGE_START_ADDRESS) // start address of storage
|
||||
#define ENA_STORAGE_TEK_MAX (CONFIG_ENA_STORAGE_TEK_MAX) // Period of storing TEKs // length of a stored beacon -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI
|
||||
#define ENA_STORAGE_TEMP_BEACONS_MAX (CONFIG_ENA_STORAGE_TEMP_BEACONS_MAX) // Maximum number of temporary stored beacons // length of a stored beacon -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI
|
||||
#define ENA_STORAGE_LOG "ESP-ENA-storage" // TAG for Logging
|
||||
#define ENA_STORAGE_PARTITION_NAME (CONFIG_ENA_STORAGE_PARTITION_NAME) // name of partition to use for storing
|
||||
#define ENA_STORAGE_START_ADDRESS (CONFIG_ENA_STORAGE_START_ADDRESS) // start address of storage
|
||||
#define ENA_STORAGE_TEK_MAX (CONFIG_ENA_STORAGE_TEK_MAX) // Period of storing TEKs // length of a stored beacon -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI
|
||||
#define ENA_STORAGE_TEMP_BEACONS_MAX (CONFIG_ENA_STORAGE_TEMP_BEACONS_MAX) // Maximum number of temporary stored beacons // length of a stored beacon -> RPI keysize + AEM size + 4 Bytes for ENIN + 4 Bytes for RSSI
|
||||
#define ENA_STORAGE_EXPOSURE_INFORMATION_MAX (CONFIG_ENA_STORAGE_EXPOSURE_INFORMATION_MAX) // Maximum number of stored exposure information
|
||||
|
||||
/**
|
||||
@ -59,7 +59,7 @@ typedef struct __attribute__((__packed__))
|
||||
uint32_t day; // Day of the exposure, using UTC, encapsulated as the time of the beginning of that day.
|
||||
int typical_attenuation; // Aggregation of the attenuations of all of a given diagnosis key's beacons received during the scan, in dB.
|
||||
int min_attenuation; // Minimum attenuation of all of a given diagnosis key's beacons received during the scan, in dB.
|
||||
int duration_minutes; //The duration of the exposure in minutes.
|
||||
int duration_minutes; //The duration of the exposure in minutes.
|
||||
int report_type; // Type of diagnosis associated with a key.
|
||||
} ena_exposure_information_t;
|
||||
|
||||
@ -90,6 +90,21 @@ void ena_storage_write(size_t address, void *data, size_t size);
|
||||
*/
|
||||
void ena_storage_shift_delete(size_t address, size_t end_address, size_t size);
|
||||
|
||||
/**
|
||||
* @brief get timestamp of most recent exposure data
|
||||
*
|
||||
* @return
|
||||
* unix timestamp
|
||||
*/
|
||||
uint32_t ena_storage_read_last_exposure_date(void);
|
||||
|
||||
/**
|
||||
* @brief set timestamp of most recent exposure data
|
||||
*
|
||||
* @param[in] timestamp unix timestamp
|
||||
*/
|
||||
void ena_storage_write_last_exposure_date(uint32_t timestamp);
|
||||
|
||||
/**
|
||||
* @brief get last stored TEK
|
||||
*
|
||||
@ -218,7 +233,6 @@ void ena_storage_erase(void);
|
||||
*/
|
||||
void ena_storage_erase_tek(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief erase all stored exposure information
|
||||
*
|
||||
@ -248,7 +262,6 @@ void ena_storage_erase_beacon(void);
|
||||
*/
|
||||
void ena_storage_dump_teks(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief dump all stored exposure information to serial output
|
||||
*
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _i2c_main_H_
|
||||
#define _i2c_main_H_
|
||||
|
||||
#define I2C_SDA_PIN (21)
|
||||
#define I2C_SDA_PIN (23)
|
||||
#define I2C_SCL_PIN (22)
|
||||
#define I2C_CLK_SPEED (1000000)
|
||||
|
||||
|
@ -1,10 +1,18 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"interface.c"
|
||||
"interface-main.c"
|
||||
"interface-data.c"
|
||||
"interface-datetime.c"
|
||||
"interface-menu.c"
|
||||
"interface-status.c"
|
||||
INCLUDE_DIRS "include"
|
||||
"interface-input.c"
|
||||
"interface-label.c"
|
||||
"interface-report.c"
|
||||
"interface-settings.c"
|
||||
"interface-wifi.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
ena
|
||||
ssd1306
|
||||
ds3231
|
||||
wifi-controller
|
||||
)
|
@ -1,37 +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 interface for changing current date and time
|
||||
*
|
||||
*/
|
||||
#ifndef _interface__DATETIME_H_
|
||||
#define _interface__DATETIME_H_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INTERFACE_DATETIME_STATE_YEAR = 0,
|
||||
INTERFACE_DATETIME_STATE_MONTH,
|
||||
INTERFACE_DATETIME_STATE_DAY,
|
||||
INTERFACE_DATETIME_STATE_HOUR,
|
||||
INTERFACE_DATETIME_STATE_MINUTE,
|
||||
INTERFACE_DATETIME_STATE_SECONDS,
|
||||
} interface_datetime_state_t;
|
||||
|
||||
void interface_datetime_start(void);
|
||||
|
||||
int interface_datetime_state(void);
|
||||
|
||||
#endif
|
@ -1,35 +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 interface menu to navigate through interface
|
||||
*
|
||||
*/
|
||||
#ifndef _interface__MENU_H_
|
||||
#define _interface__MENU_H_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INTERFACE_MENU_STATE_IDLE = 0,
|
||||
INTERFACE_MENU_STATE_SELECT_TIME,
|
||||
INTERFACE_MENU_STATE_SELECT_DEBUG,
|
||||
INTERFACE_MENU_STATE_SELECT_STATUS,
|
||||
} interface_menu_state_t;
|
||||
|
||||
void interface_menu_start(void);
|
||||
|
||||
int interface_menu_get_state(void);
|
||||
|
||||
#endif
|
@ -1,25 +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 interface to show current ENA status (infection risk etc.)
|
||||
*
|
||||
*/
|
||||
#ifndef _interface__STATUS_H_
|
||||
#define _interface__STATUS_H_
|
||||
|
||||
void interface_status_start(void);
|
||||
|
||||
#endif
|
@ -1,79 +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 interface functionality via touch pads for control and setup
|
||||
*
|
||||
*/
|
||||
#ifndef _interface__H_
|
||||
#define _interface__H_
|
||||
|
||||
#define INTERFACE_LOG "INTERFACE" // TAG for Logging
|
||||
|
||||
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
|
||||
#define TOUCH_PAD_COUNT (4)
|
||||
#define TOUCH_PAD_ESC (TOUCH_PAD_NUM0)
|
||||
#define TOUCH_PAD_OK (TOUCH_PAD_NUM6)
|
||||
#define TOUCH_PAD_UP (TOUCH_PAD_NUM4)
|
||||
#define TOUCH_PAD_DOWN (TOUCH_PAD_NUM3)
|
||||
|
||||
/**
|
||||
* @brief different interface states
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
INTERFACE_STATE_IDLE = 0, // ilde state, do nothing
|
||||
INTERFACE_STATE_MENU, // main menu
|
||||
INTERFACE_STATE_SET_DATETIME, // set current date and time
|
||||
INTERFACE_STATE_STATUS, // current status
|
||||
} interface_state_t;
|
||||
|
||||
/**
|
||||
* @brief callback function on touch event
|
||||
*/
|
||||
typedef void (*interface_touch_callback)(void);
|
||||
|
||||
/**
|
||||
* @brief register a callback function for touch event
|
||||
*
|
||||
* @param[in] touch_pad id of the touchpad to listen touch
|
||||
* @param[in] callback callback function
|
||||
*/
|
||||
void interface_register_touch_callback(int touch_pad, interface_touch_callback callback);
|
||||
|
||||
/**
|
||||
* @brief get current interface state
|
||||
*
|
||||
* @return
|
||||
* current state the interface is in
|
||||
*/
|
||||
int interface_get_state(void);
|
||||
|
||||
/**
|
||||
* @brief set current interface state
|
||||
*
|
||||
* @param[in] state new state to set
|
||||
*/
|
||||
void interface_set_state(interface_state_t state);
|
||||
|
||||
/**
|
||||
* @brief start interface logic
|
||||
*
|
||||
* This will initialize the touch controls and start a task to listen to touch
|
||||
* inputs and calling the callbacks
|
||||
*/
|
||||
void interface_start(void);
|
||||
|
||||
#endif
|
195
components/interface/interface-data.c
Normal file
195
components/interface/interface-data.c
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "ena-storage.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INTERFACE_DATA_DEL_TEK = 0,
|
||||
INTERFACE_DATA_DEL_EXPOSURE_INFO,
|
||||
INTERFACE_DATA_DEL_TEMP_RPI,
|
||||
INTERFACE_DATA_DEL_RPI,
|
||||
INTERFACE_DATA_DEL_LAST_EXPOSURE,
|
||||
INTERFACE_DATA_DEL_ALL,
|
||||
} interface_data_state_t;
|
||||
|
||||
static int current_interface_data_state;
|
||||
static int current_data_index;
|
||||
static bool confirm_current;
|
||||
|
||||
void interface_data_set(void)
|
||||
{
|
||||
if (!confirm_current)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_data_rst(void)
|
||||
{
|
||||
|
||||
if (confirm_current)
|
||||
{
|
||||
switch (current_interface_data_state)
|
||||
{
|
||||
case INTERFACE_DATA_DEL_TEK:
|
||||
ena_storage_erase_tek();
|
||||
break;
|
||||
case INTERFACE_DATA_DEL_EXPOSURE_INFO:
|
||||
ena_storage_erase_exposure_information();
|
||||
break;
|
||||
case INTERFACE_DATA_DEL_TEMP_RPI:
|
||||
ena_storage_erase_temporary_beacon();
|
||||
break;
|
||||
case INTERFACE_DATA_DEL_RPI:
|
||||
ena_storage_erase_beacon();
|
||||
break;
|
||||
case INTERFACE_DATA_DEL_LAST_EXPOSURE:
|
||||
ena_storage_write_last_exposure_date(0);
|
||||
break;
|
||||
case INTERFACE_DATA_DEL_ALL:
|
||||
ena_storage_erase();
|
||||
break;
|
||||
}
|
||||
|
||||
confirm_current = false;
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_data_lft(void)
|
||||
{
|
||||
interface_wifi_start();
|
||||
}
|
||||
|
||||
void interface_data_rht(void)
|
||||
{
|
||||
interface_settings_start();
|
||||
}
|
||||
|
||||
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);
|
||||
confirm_current = true;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_data_up(void)
|
||||
{
|
||||
current_interface_data_state--;
|
||||
if (current_interface_data_state < INTERFACE_DATA_DEL_TEK)
|
||||
{
|
||||
current_interface_data_state = INTERFACE_DATA_DEL_ALL;
|
||||
|
||||
current_data_index = 3;
|
||||
}
|
||||
else if (current_interface_data_state < current_data_index)
|
||||
{
|
||||
current_data_index--;
|
||||
}
|
||||
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
|
||||
}
|
||||
|
||||
void interface_data_dwn(void)
|
||||
{
|
||||
current_interface_data_state++;
|
||||
if (current_interface_data_state > INTERFACE_DATA_DEL_ALL)
|
||||
{
|
||||
current_interface_data_state = INTERFACE_DATA_DEL_TEK;
|
||||
current_data_index = 0;
|
||||
}
|
||||
else if (current_interface_data_state >= (current_data_index + 3))
|
||||
{
|
||||
current_data_index++;
|
||||
}
|
||||
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 6, false);
|
||||
}
|
||||
|
||||
void interface_data_display(void)
|
||||
{
|
||||
ssd1306_menu_headline(SSD1306_ADDRESS, 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);
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 5, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 7, false);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int index = i + current_data_index;
|
||||
if (index <= INTERFACE_DATA_DEL_ALL)
|
||||
{
|
||||
if (index == current_interface_data_state)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_set_display_function(&interface_data_display);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start delete data interface");
|
||||
}
|
@ -11,33 +11,58 @@
|
||||
// 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 <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ds3231.h"
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "interface.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "interface-menu.h"
|
||||
|
||||
#include "interface-datetime.h"
|
||||
|
||||
static int current_interface_datetime_state = INTERFACE_DATETIME_STATE_YEAR;
|
||||
|
||||
const uint32_t interface_datetime_steps[6] = {
|
||||
31557600, 2629800, 86400, 3600, 60, 1};
|
||||
|
||||
void interface_datetime_esc(void)
|
||||
typedef enum
|
||||
{
|
||||
interface_menu_start();
|
||||
INTERFACE_DATETIME_STATE_HOUR = 0,
|
||||
INTERFACE_DATETIME_STATE_MINUTE,
|
||||
INTERFACE_DATETIME_STATE_SECONDS,
|
||||
INTERFACE_DATETIME_STATE_DAY,
|
||||
INTERFACE_DATETIME_STATE_MONTH,
|
||||
INTERFACE_DATETIME_STATE_YEAR,
|
||||
} interface_datetime_state_t;
|
||||
|
||||
static int current_interface_datetime_state;
|
||||
|
||||
const uint32_t interface_datetime_steps[6] = {3600, 60, 1, 86400, 2629800, 31557600};
|
||||
|
||||
int interface_datetime_state(void)
|
||||
{
|
||||
return current_interface_datetime_state;
|
||||
}
|
||||
|
||||
void interface_datetime_ok(void)
|
||||
void interface_datetime_set(void)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
|
||||
void interface_datetime_lft(void)
|
||||
{
|
||||
interface_settings_start();
|
||||
}
|
||||
|
||||
void interface_datetime_rht(void)
|
||||
{
|
||||
interface_wifi_start();
|
||||
}
|
||||
|
||||
void interface_datetime_mid(void)
|
||||
{
|
||||
current_interface_datetime_state++;
|
||||
if (current_interface_datetime_state > INTERFACE_DATETIME_STATE_SECONDS)
|
||||
if (current_interface_datetime_state > INTERFACE_DATETIME_STATE_YEAR)
|
||||
{
|
||||
current_interface_datetime_state = INTERFACE_DATETIME_STATE_YEAR;
|
||||
current_interface_datetime_state = INTERFACE_DATETIME_STATE_HOUR;
|
||||
}
|
||||
ESP_LOGD(INTERFACE_LOG, "datetime to %d", current_interface_datetime_state);
|
||||
}
|
||||
@ -49,30 +74,100 @@ void interface_datetime_up(void)
|
||||
struct timeval tv = {0};
|
||||
tv.tv_sec = curtime;
|
||||
settimeofday(&tv, NULL);
|
||||
ds3231_set_time(gmtime(&curtime));
|
||||
ESP_LOGD(INTERFACE_LOG, "increment %d about %u %s", current_interface_datetime_state, interface_datetime_steps[current_interface_datetime_state], ctime(&curtime));
|
||||
}
|
||||
|
||||
void interface_datetime_down(void)
|
||||
void interface_datetime_dwn(void)
|
||||
{
|
||||
time_t curtime = time(NULL);
|
||||
curtime -= interface_datetime_steps[current_interface_datetime_state];
|
||||
struct timeval tv = {0};
|
||||
tv.tv_sec = curtime;
|
||||
settimeofday(&tv, NULL);
|
||||
ds3231_set_time(gmtime(&curtime));
|
||||
ESP_LOGD(INTERFACE_LOG, "decrement %d about %u %s", current_interface_datetime_state, interface_datetime_steps[current_interface_datetime_state], ctime(&curtime));
|
||||
}
|
||||
|
||||
void interface_datetime_display(void)
|
||||
{
|
||||
static time_t current_timstamp;
|
||||
static struct tm *current_tm;
|
||||
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);
|
||||
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);
|
||||
|
||||
time(¤t_timstamp);
|
||||
current_tm = localtime(¤t_timstamp);
|
||||
|
||||
strftime(time_buffer, 16, INTERFACE_FORMAT_TIME, current_tm);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, 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);
|
||||
|
||||
switch (interface_datetime_state())
|
||||
{
|
||||
|
||||
case INTERFACE_DATETIME_STATE_YEAR:
|
||||
memcpy(&edit_char, &date_buffer[7], edit_length);
|
||||
edit_line = 6;
|
||||
edit_offset = 11;
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_DAY:
|
||||
memcpy(&edit_char, &date_buffer[0], edit_length);
|
||||
edit_line = 6;
|
||||
edit_offset = 4;
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_MONTH:
|
||||
edit_length = 3;
|
||||
memcpy(&edit_char, &date_buffer[3], edit_length);
|
||||
edit_line = 6;
|
||||
edit_offset = 7;
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_HOUR:
|
||||
memcpy(&edit_char, &time_buffer[0], edit_length);
|
||||
edit_line = 3;
|
||||
edit_offset = 4;
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_MINUTE:
|
||||
memcpy(&edit_char, &time_buffer[3], edit_length);
|
||||
edit_line = 3;
|
||||
edit_offset = 7;
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_SECONDS:
|
||||
memcpy(&edit_char, &time_buffer[6], edit_length);
|
||||
edit_line = 3;
|
||||
edit_offset = 10;
|
||||
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);
|
||||
}
|
||||
|
||||
void interface_datetime_start(void)
|
||||
{
|
||||
interface_set_state(INTERFACE_STATE_SET_DATETIME);
|
||||
interface_register_touch_callback(TOUCH_PAD_ESC, &interface_datetime_esc);
|
||||
interface_register_touch_callback(TOUCH_PAD_OK, &interface_datetime_ok);
|
||||
interface_register_touch_callback(TOUCH_PAD_UP, &interface_datetime_up);
|
||||
interface_register_touch_callback(TOUCH_PAD_DOWN, &interface_datetime_down);
|
||||
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_set_display_function(&interface_datetime_display);
|
||||
ESP_LOGD(INTERFACE_LOG, "start datetime interface");
|
||||
}
|
||||
|
||||
int interface_datetime_state(void)
|
||||
{
|
||||
return current_interface_datetime_state;
|
||||
}
|
318
components/interface/interface-input.c
Normal file
318
components/interface/interface-input.c
Normal file
@ -0,0 +1,318 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
static interface_input_callback current_input_callback_rst;
|
||||
static interface_input_callback current_input_callback_set;
|
||||
static char current_text[255];
|
||||
static uint8_t current_cursor;
|
||||
static char current_char_set[32];
|
||||
static uint8_t current_char_index;
|
||||
static uint8_t current_limit;
|
||||
static uint8_t current_max_index;
|
||||
|
||||
static char char_set_uppercase[32];
|
||||
static char char_set_lowercase[32];
|
||||
static char char_set_numeric[32];
|
||||
static char char_set_special1[32];
|
||||
static char char_set_special_uppercasecase[32];
|
||||
static char char_set_special_lowercase[32];
|
||||
|
||||
void interface_input_set_char_set(void)
|
||||
{
|
||||
|
||||
char *ret;
|
||||
char cur_char = current_text[current_cursor];
|
||||
|
||||
if ((ret = strchr(char_set_lowercase, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_lowercase);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
else if ((ret = strchr(char_set_numeric, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_numeric);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
else if ((ret = strchr(char_set_special1, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_special1);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
else if ((ret = strchr(char_set_special_uppercasecase, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_special_uppercasecase);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
else if ((ret = strchr(char_set_special_lowercase, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_special_lowercase);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
else if ((ret = strchr(char_set_uppercase, cur_char)) != NULL)
|
||||
{
|
||||
strcpy(current_char_set, char_set_uppercase);
|
||||
current_char_index = strlen(current_char_set) - strlen(ret);
|
||||
}
|
||||
printf("current_char_set: %d %s\n", strlen(current_char_set), current_char_set);
|
||||
}
|
||||
|
||||
void interface_input_set(void)
|
||||
{
|
||||
if (current_input_callback_rst != NULL)
|
||||
{
|
||||
(*current_input_callback_rst)(current_text, current_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_input_rst(void)
|
||||
{
|
||||
if (current_input_callback_set != NULL)
|
||||
{
|
||||
(*current_input_callback_set)(current_text, current_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_input_lft(void)
|
||||
{
|
||||
if (current_cursor > 0)
|
||||
{
|
||||
current_cursor--;
|
||||
interface_input_set_char_set();
|
||||
}
|
||||
}
|
||||
|
||||
void interface_input_rht(void)
|
||||
{
|
||||
if (current_cursor < current_limit)
|
||||
{
|
||||
current_cursor++;
|
||||
if (current_cursor > current_max_index)
|
||||
{
|
||||
current_max_index = current_cursor;
|
||||
strcpy(current_char_set, char_set_uppercase);
|
||||
|
||||
current_char_index = 0;
|
||||
current_text[current_cursor] = current_char_set[current_char_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_input_set_char_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interface_input_mid(void)
|
||||
{
|
||||
if (current_char_set[0] == char_set_uppercase[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_lowercase);
|
||||
}
|
||||
else if (current_char_set[0] == char_set_lowercase[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_numeric);
|
||||
}
|
||||
else if (current_char_set[0] == char_set_numeric[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_special1);
|
||||
}
|
||||
else if (current_char_set[0] == char_set_special1[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_special_uppercasecase);
|
||||
}
|
||||
else if (current_char_set[0] == char_set_special_uppercasecase[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_special_lowercase);
|
||||
}
|
||||
else if (current_char_set[0] == char_set_special_lowercase[0])
|
||||
{
|
||||
strcpy(current_char_set, char_set_uppercase);
|
||||
}
|
||||
current_char_index = 0;
|
||||
current_text[current_cursor] = current_char_set[current_char_index];
|
||||
printf("current_char_set: %d %s\n", strlen(current_char_set), current_char_set);
|
||||
}
|
||||
void interface_input_up(void)
|
||||
{
|
||||
if (current_char_index == 0)
|
||||
{
|
||||
current_char_index = strlen(current_char_set) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_char_index--;
|
||||
}
|
||||
|
||||
current_text[current_cursor] = current_char_set[current_char_index];
|
||||
}
|
||||
|
||||
void interface_input_dwn(void)
|
||||
{
|
||||
if (current_char_index == strlen(current_char_set) - 1)
|
||||
{
|
||||
current_char_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_char_index++;
|
||||
}
|
||||
|
||||
current_text[current_cursor] = current_char_set[current_char_index];
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
size_t start = 0;
|
||||
uint8_t display_cursor = current_cursor + 1;
|
||||
if (current_cursor > 13)
|
||||
{
|
||||
start = current_cursor - 13;
|
||||
display_cursor = 14;
|
||||
}
|
||||
|
||||
// arrow
|
||||
if (current_cursor > 0)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_left, 8, 2, 0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 2, 0, false);
|
||||
}
|
||||
// bounday
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, "______________", 2, 1, false);
|
||||
// arrow
|
||||
if (current_cursor < current_limit)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, 2, 15 * 8, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 2, 15 * 8, false);
|
||||
}
|
||||
// text
|
||||
size_t text_length = strlen(current_text);
|
||||
if (strlen(current_text) > 14)
|
||||
{
|
||||
text_length = 14;
|
||||
}
|
||||
size_t length = text_length * 8;
|
||||
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);
|
||||
}
|
||||
|
||||
ssd1306_data(SSD1306_ADDRESS, 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);
|
||||
|
||||
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;
|
||||
uint8_t next_char = (uint8_t)current_char_set[current_char_index + 1] - 32;
|
||||
|
||||
if (current_char_index == 0)
|
||||
{
|
||||
prev_char = (uint8_t)current_char_set[strlen(current_char_set) - 1] - 32;
|
||||
}
|
||||
|
||||
if (current_char_index == strlen(current_char_set) - 1)
|
||||
{
|
||||
next_char = (uint8_t)current_char_set[0] - 32;
|
||||
}
|
||||
|
||||
// arrow
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
// sel char
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
// arrow
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_down, 8, 4, display_cursor * 8, false);
|
||||
}
|
||||
|
||||
void interface_input_set_text(char *text)
|
||||
{
|
||||
ssd1306_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)
|
||||
{
|
||||
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);
|
||||
|
||||
strcpy(current_char_set, char_set_uppercase);
|
||||
|
||||
printf("char_set_uppercase: %d %s\n", strlen(char_set_uppercase), char_set_uppercase);
|
||||
printf("char_set_lowercase: %d %s\n", strlen(char_set_lowercase), char_set_lowercase);
|
||||
printf("char_set_numeric: %d %s\n", strlen(char_set_numeric), char_set_numeric);
|
||||
printf("char_set_special1: %d %s\n", strlen(char_set_special1), char_set_special1);
|
||||
printf("char_set_special_uppercasecase: %d %s\n", strlen(char_set_special_uppercasecase), char_set_special_uppercasecase);
|
||||
printf("char_set_special_lowercase: %d %s\n", strlen(char_set_special_lowercase), char_set_special_lowercase);
|
||||
|
||||
current_char_index = 0;
|
||||
current_max_index = 0;
|
||||
if (current_limit == 0)
|
||||
{
|
||||
current_limit = 255;
|
||||
}
|
||||
|
||||
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_set_display_function(&interface_input_display);
|
||||
ESP_LOGD(INTERFACE_LOG, "start input interface");
|
||||
}
|
139
components/interface/interface-label.c
Normal file
139
components/interface/interface-label.c
Normal file
@ -0,0 +1,139 @@
|
||||
// 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 texts for intefaces
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "interface.h"
|
||||
|
||||
static interface_locale_t current_locale = EN;
|
||||
|
||||
void interface_init_label(void)
|
||||
{
|
||||
// EN
|
||||
interface_text_button_cancel.text[EN] = "CANCEL";
|
||||
interface_text_button_ok.text[EN] = "OK";
|
||||
interface_text_button_menu.text[EN] = "MENU";
|
||||
interface_text_button_report.text[EN] = "REPORT";
|
||||
|
||||
interface_text_headline_tan.text[EN] = "ENTER TAN";
|
||||
interface_text_headline_wifi.text[EN] = "WIFI";
|
||||
interface_text_headline_time.text[EN] = "TIME/DATE";
|
||||
interface_text_headline_data.text[EN] = "DEL DATA";
|
||||
interface_text_headline_settings.text[EN] = "SETTING";
|
||||
interface_text_headline_debug.text[EN] = "DEBUG";
|
||||
|
||||
interface_text_settings_locale.text[EN] = "Language:";
|
||||
interface_text_settings_locales[EN].text[EN] = "EN";
|
||||
interface_text_settings_locales[DE].text[EN] = "DE";
|
||||
|
||||
interface_text_settings_timezone.text[EN] = "Timezone:";
|
||||
|
||||
interface_text_wifi_scanning.text[EN] = "Scanning...";
|
||||
|
||||
interface_text_data_del[0].text[EN] = "DEL TEK";
|
||||
interface_text_data_del[1].text[EN] = "DEL Exp Info";
|
||||
interface_text_data_del[2].text[EN] = "DEL Tmp RPI";
|
||||
interface_text_data_del[3].text[EN] = "DEL RPI";
|
||||
interface_text_data_del[4].text[EN] = "DEL Lst Upd.";
|
||||
interface_text_data_del[5].text[EN] = "DEL All Data";
|
||||
|
||||
interface_texts_weekday[0].text[EN] = "Sun";
|
||||
interface_texts_weekday[1].text[EN] = "Mon";
|
||||
interface_texts_weekday[2].text[EN] = "Tue";
|
||||
interface_texts_weekday[3].text[EN] = "Wed";
|
||||
interface_texts_weekday[4].text[EN] = "Thu";
|
||||
interface_texts_weekday[5].text[EN] = "Fri";
|
||||
interface_texts_weekday[6].text[EN] = "Sat";
|
||||
|
||||
interface_texts_month[0].text[EN] = "Jan";
|
||||
interface_texts_month[1].text[EN] = "Feb";
|
||||
interface_texts_month[2].text[EN] = "Mar";
|
||||
interface_texts_month[3].text[EN] = "Apr";
|
||||
interface_texts_month[4].text[EN] = "May";
|
||||
interface_texts_month[5].text[EN] = "Jun";
|
||||
interface_texts_month[6].text[EN] = "Jul";
|
||||
interface_texts_month[7].text[EN] = "Aug";
|
||||
interface_texts_month[8].text[EN] = "Sep";
|
||||
interface_texts_month[9].text[EN] = "Oct";
|
||||
interface_texts_month[10].text[EN] = "Nov";
|
||||
interface_texts_month[11].text[EN] = "Dec";
|
||||
|
||||
// DE
|
||||
interface_text_button_cancel.text[DE] = "ZURÜCK";
|
||||
interface_text_button_ok.text[DE] = "OK";
|
||||
interface_text_button_menu.text[DE] = "MENU";
|
||||
interface_text_button_report.text[DE] = "MELDEN";
|
||||
|
||||
interface_text_headline_tan.text[DE] = "TAN EING.";
|
||||
interface_text_headline_wifi.text[DE] = "WLAN";
|
||||
interface_text_headline_time.text[DE] = "ZEIT/DATUM";
|
||||
interface_text_headline_data.text[DE] = "DATEN ENTF";
|
||||
interface_text_headline_settings.text[DE] = "EINSTEL.";
|
||||
interface_text_headline_debug.text[DE] = "DEBUG";
|
||||
|
||||
interface_text_settings_locale.text[DE] = "Sprache:";
|
||||
interface_text_settings_locales[EN].text[DE] = "EN";
|
||||
interface_text_settings_locales[DE].text[DE] = "DE";
|
||||
|
||||
interface_text_settings_timezone.text[DE] = "Zeitzone:";
|
||||
|
||||
interface_text_wifi_scanning.text[DE] = "Scannen...";
|
||||
|
||||
interface_text_data_del[0].text[DE] = "ENTF TEK";
|
||||
interface_text_data_del[1].text[DE] = "ENTF Exp Info";
|
||||
interface_text_data_del[2].text[DE] = "ENTF Tmp RPI";
|
||||
interface_text_data_del[3].text[DE] = "ENTF RPI";
|
||||
interface_text_data_del[4].text[DE] = "ENTF letz. Up";
|
||||
interface_text_data_del[5].text[DE] = "ENTF Daten";
|
||||
|
||||
interface_texts_weekday[0].text[DE] = "So.";
|
||||
interface_texts_weekday[1].text[DE] = "Mo.";
|
||||
interface_texts_weekday[2].text[DE] = "Di.";
|
||||
interface_texts_weekday[3].text[DE] = "Mi.";
|
||||
interface_texts_weekday[4].text[DE] = "Do.";
|
||||
interface_texts_weekday[5].text[DE] = "Fr.";
|
||||
interface_texts_weekday[6].text[DE] = "Sa.";
|
||||
|
||||
interface_texts_month[0].text[DE] = "Jan";
|
||||
interface_texts_month[1].text[DE] = "Feb";
|
||||
interface_texts_month[2].text[DE] = "Mär";
|
||||
interface_texts_month[3].text[DE] = "Apr";
|
||||
interface_texts_month[4].text[DE] = "Mai";
|
||||
interface_texts_month[5].text[DE] = "Jun";
|
||||
interface_texts_month[6].text[DE] = "Jul";
|
||||
interface_texts_month[7].text[DE] = "Aug";
|
||||
interface_texts_month[8].text[DE] = "Sep";
|
||||
interface_texts_month[9].text[DE] = "Okt";
|
||||
interface_texts_month[10].text[DE] = "Nov";
|
||||
interface_texts_month[11].text[DE] = "Dez";
|
||||
}
|
||||
|
||||
interface_locale_t interface_get_locale(void)
|
||||
{
|
||||
return current_locale;
|
||||
}
|
||||
|
||||
void interface_set_locale(interface_locale_t locale)
|
||||
{
|
||||
current_locale = locale;
|
||||
}
|
||||
|
||||
char *interface_get_label_text(interface_label_t *label)
|
||||
{
|
||||
return label->text[current_locale];
|
||||
}
|
143
components/interface/interface-main.c
Normal file
143
components/interface/interface-main.c
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ds3231.h"
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "wifi-controller.h"
|
||||
#include "ena-storage.h"
|
||||
#include "ena-exposure.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
static time_t current_timstamp;
|
||||
static struct tm *current_tm;
|
||||
static char time_buffer[32];
|
||||
static char text_buffer[32];
|
||||
static bool wifi_connected;
|
||||
|
||||
void interface_main_set(void)
|
||||
{
|
||||
interface_datetime_start();
|
||||
}
|
||||
|
||||
void interface_main_rst(void)
|
||||
{
|
||||
interface_report_start();
|
||||
}
|
||||
|
||||
void interface_main_display(void)
|
||||
{
|
||||
if (wifi_connected)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_wifi, 8, 0, 0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_cross, 8, 0, 0, false);
|
||||
}
|
||||
|
||||
time(¤t_timstamp);
|
||||
current_tm = localtime(¤t_timstamp);
|
||||
|
||||
// curent date
|
||||
sprintf(text_buffer, "%s %s %d",
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (wifi_controller_connection() != NULL)
|
||||
{
|
||||
wifi_connected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wifi_connected = false;
|
||||
}
|
||||
|
||||
interface_set_display_function(&interface_main_display);
|
||||
|
||||
ena_exposure_summary_t *current_exposure_summary = ena_exposure_current_summary();
|
||||
|
||||
time(¤t_timstamp);
|
||||
uint32_t last_update = ena_storage_read_last_exposure_date();
|
||||
|
||||
// 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
// clock icon
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clock, 8, 4, 8, false);
|
||||
|
||||
// last update
|
||||
struct tm *last_update_tm = localtime((time_t*) &last_update);
|
||||
|
||||
sprintf(time_buffer, "%02d %s %02d:%02d",
|
||||
last_update_tm->tm_mday,
|
||||
interface_get_label_text(&interface_texts_month[last_update_tm->tm_mon]),
|
||||
last_update_tm->tm_hour,
|
||||
last_update_tm->tm_min);
|
||||
|
||||
if (last_update != 0)
|
||||
{
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, 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);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start main interface");
|
||||
}
|
@ -1,88 +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.
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "interface.h"
|
||||
#include "interface-datetime.h"
|
||||
#include "interface-status.h"
|
||||
|
||||
#include "interface-menu.h"
|
||||
|
||||
static int current_interface_menu_state = INTERFACE_MENU_STATE_IDLE;
|
||||
|
||||
void interface_menu_ok(void)
|
||||
{
|
||||
if (current_interface_menu_state == INTERFACE_MENU_STATE_SELECT_TIME)
|
||||
{
|
||||
interface_datetime_start();
|
||||
}
|
||||
else if (current_interface_menu_state == INTERFACE_MENU_STATE_SELECT_STATUS)
|
||||
{
|
||||
interface_status_start();
|
||||
}
|
||||
else if (current_interface_menu_state == INTERFACE_MENU_STATE_SELECT_DEBUG)
|
||||
{
|
||||
}
|
||||
else if (current_interface_menu_state == INTERFACE_MENU_STATE_IDLE)
|
||||
{
|
||||
if (interface_get_state() == INTERFACE_STATE_MENU)
|
||||
{
|
||||
interface_set_state(INTERFACE_STATE_IDLE);
|
||||
interface_register_touch_callback(TOUCH_PAD_UP, NULL);
|
||||
interface_register_touch_callback(TOUCH_PAD_DOWN, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_menu_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interface_menu_up(void)
|
||||
{
|
||||
current_interface_menu_state--;
|
||||
if (current_interface_menu_state < INTERFACE_MENU_STATE_IDLE)
|
||||
{
|
||||
current_interface_menu_state = INTERFACE_MENU_STATE_SELECT_STATUS;
|
||||
}
|
||||
ESP_LOGD(INTERFACE_LOG, "menu up to %d", current_interface_menu_state);
|
||||
}
|
||||
|
||||
void interface_menu_down(void)
|
||||
{
|
||||
current_interface_menu_state++;
|
||||
if (current_interface_menu_state > INTERFACE_MENU_STATE_SELECT_STATUS)
|
||||
{
|
||||
current_interface_menu_state = INTERFACE_MENU_STATE_IDLE;
|
||||
}
|
||||
ESP_LOGD(INTERFACE_LOG, "menu down to %d", current_interface_menu_state);
|
||||
}
|
||||
|
||||
void interface_menu_start(void)
|
||||
{
|
||||
interface_set_state(INTERFACE_STATE_MENU);
|
||||
interface_register_touch_callback(TOUCH_PAD_ESC, NULL);
|
||||
interface_register_touch_callback(TOUCH_PAD_OK, &interface_menu_ok);
|
||||
interface_register_touch_callback(TOUCH_PAD_UP, &interface_menu_up);
|
||||
interface_register_touch_callback(TOUCH_PAD_DOWN, &interface_menu_down);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start menu interface");
|
||||
}
|
||||
|
||||
int interface_menu_get_state(void)
|
||||
{
|
||||
return current_interface_menu_state;
|
||||
}
|
177
components/interface/interface-report.c
Normal file
177
components/interface/interface-report.c
Normal file
@ -0,0 +1,177 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "wifi-controller.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
static int interface_report_tan[10] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
|
||||
static int interface_report_tan_index = 0;
|
||||
|
||||
void interface_report_set(void)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
|
||||
void interface_report_rst(void)
|
||||
{
|
||||
// TODO: REPORT here, check tan etc.
|
||||
}
|
||||
|
||||
void interface_report_lft(void)
|
||||
{
|
||||
if (interface_report_tan_index > 0)
|
||||
{
|
||||
interface_report_tan_index--;
|
||||
}
|
||||
ESP_LOGD(INTERFACE_LOG, "tan index %d", interface_report_tan_index);
|
||||
}
|
||||
|
||||
void interface_report_rht(void)
|
||||
{
|
||||
if (interface_report_tan_index < 9)
|
||||
{
|
||||
interface_report_tan_index++;
|
||||
}
|
||||
ESP_LOGD(INTERFACE_LOG, "tan index %d", interface_report_tan_index);
|
||||
}
|
||||
|
||||
void interface_report_up(void)
|
||||
{
|
||||
if (interface_report_tan[interface_report_tan_index] > 0)
|
||||
{
|
||||
interface_report_tan[interface_report_tan_index]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_report_tan[interface_report_tan_index] = 9;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_report_dwn(void)
|
||||
{
|
||||
if (interface_report_tan[interface_report_tan_index] < 9)
|
||||
{
|
||||
interface_report_tan[interface_report_tan_index]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_report_tan[interface_report_tan_index] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_report_display(void)
|
||||
{
|
||||
ssd1306_menu_headline(SSD1306_ADDRESS, 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);
|
||||
|
||||
static char tan_buffer[10] = {0};
|
||||
|
||||
if (interface_report_tan_index > 0)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_left, 8, 3, 8, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 3, 8, false);
|
||||
}
|
||||
|
||||
if (interface_report_tan_index < 9)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_arrow_right, 8, 3, 112, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_clear, 8, 3, 112, false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < interface_report_tan_index + 1; i++)
|
||||
{
|
||||
sprintf(&tan_buffer[i], "%d", interface_report_tan[i]);
|
||||
}
|
||||
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 2, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (interface_report_tan_index > 2)
|
||||
{
|
||||
offset = 3;
|
||||
for (int i = 3; i < 6; i++)
|
||||
{
|
||||
if (i < interface_report_tan_index)
|
||||
{
|
||||
ssd1306_chars(SSD1306_ADDRESS, &tan_buffer[i], 1, 3, i + offset, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interface_report_tan_index > 5)
|
||||
{
|
||||
offset = 4;
|
||||
for (int i = 6; i < 10; i++)
|
||||
{
|
||||
if (i < interface_report_tan_index)
|
||||
{
|
||||
ssd1306_chars(SSD1306_ADDRESS, &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);
|
||||
|
||||
ssd1306_chars(SSD1306_ADDRESS, &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_set_display_function(&interface_report_display);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start report interface");
|
||||
}
|
147
components/interface/interface-settings.c
Normal file
147
components/interface/interface-settings.c
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "ena-storage.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INTERFACE_SETTINGS_LOCALE = 0,
|
||||
INTERFACE_SETTINGS_TIMEZONE,
|
||||
} interface_settings_state_t;
|
||||
|
||||
static int current_interface_settings_state;
|
||||
|
||||
void interface_settings_set(void)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
|
||||
void interface_settings_rst(void)
|
||||
{
|
||||
}
|
||||
|
||||
void interface_settings_lft(void)
|
||||
{
|
||||
interface_data_start();
|
||||
}
|
||||
|
||||
void interface_settings_rht(void)
|
||||
{
|
||||
interface_datetime_start();
|
||||
}
|
||||
|
||||
void interface_settings_mid(void)
|
||||
{
|
||||
|
||||
current_interface_settings_state++;
|
||||
if (current_interface_settings_state > INTERFACE_SETTINGS_TIMEZONE)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
void interface_settings_up(void)
|
||||
{
|
||||
if (current_interface_settings_state == INTERFACE_SETTINGS_LOCALE)
|
||||
{
|
||||
if (interface_get_locale() == 0)
|
||||
{
|
||||
interface_set_locale(INTERFACE_NUM_LOCALE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_set_locale(interface_get_locale() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interface_settings_dwn(void)
|
||||
{
|
||||
|
||||
if (current_interface_settings_state == INTERFACE_SETTINGS_LOCALE)
|
||||
{
|
||||
if (interface_get_locale() + 1 == INTERFACE_NUM_LOCALE)
|
||||
{
|
||||
interface_set_locale(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
interface_set_locale(interface_get_locale() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void interface_settings_display(void)
|
||||
{
|
||||
ssd1306_menu_headline(SSD1306_ADDRESS, 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);
|
||||
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, 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,
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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_set_display_function(&interface_settings_display);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start settings interface");
|
||||
}
|
@ -1,37 +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.
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "interface.h"
|
||||
#include "interface-menu.h"
|
||||
|
||||
#include "interface-status.h"
|
||||
|
||||
void interface_status_esc(void)
|
||||
{
|
||||
interface_menu_start();
|
||||
}
|
||||
|
||||
void interface_status_start(void)
|
||||
{
|
||||
interface_set_state(INTERFACE_STATE_STATUS);
|
||||
interface_register_touch_callback(TOUCH_PAD_ESC, &interface_status_esc);
|
||||
interface_register_touch_callback(TOUCH_PAD_OK, NULL);
|
||||
interface_register_touch_callback(TOUCH_PAD_UP, NULL);
|
||||
interface_register_touch_callback(TOUCH_PAD_DOWN, NULL);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start status interface");
|
||||
}
|
183
components/interface/interface-wifi.c
Normal file
183
components/interface/interface-wifi.c
Normal file
@ -0,0 +1,183 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
#include "wifi-controller.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
#define APS_TO_DISPLAY 3
|
||||
|
||||
wifi_ap_record_t ap_info[10];
|
||||
uint16_t ap_count = 0;
|
||||
int ap_index = 0;
|
||||
int ap_selected = 0;
|
||||
|
||||
static wifi_config_t current_wifi_config;
|
||||
|
||||
void interface_wifi_input_rst(char *text, uint8_t cursor)
|
||||
{
|
||||
interface_wifi_start();
|
||||
}
|
||||
|
||||
void interface_wifi_input_set(char *text, uint8_t cursor)
|
||||
{
|
||||
memcpy(current_wifi_config.sta.password, text, cursor + 1);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "ssid: '%s' password '%s'", current_wifi_config.sta.ssid, current_wifi_config.sta.password);
|
||||
|
||||
if (wifi_controller_connect(current_wifi_config) == ESP_OK)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// what happens here?
|
||||
interface_wifi_start();
|
||||
}
|
||||
}
|
||||
|
||||
void interface_wifi_set(void)
|
||||
{
|
||||
interface_main_start();
|
||||
}
|
||||
|
||||
void interface_wifi_lft(void)
|
||||
{
|
||||
interface_datetime_start();
|
||||
}
|
||||
|
||||
void interface_wifi_rht(void)
|
||||
{
|
||||
interface_data_start();
|
||||
}
|
||||
void interface_wifi_mid(void)
|
||||
{
|
||||
memset(¤t_wifi_config, 0, sizeof(wifi_config_t));
|
||||
memcpy(current_wifi_config.sta.ssid, ap_info[ap_selected].ssid, strlen((char *)ap_info[ap_selected].ssid));
|
||||
interface_input(&interface_wifi_input_rst, &interface_wifi_input_set, 64);
|
||||
}
|
||||
void interface_wifi_up(void)
|
||||
{
|
||||
ap_selected--;
|
||||
if (ap_selected < 0)
|
||||
{
|
||||
ap_selected = ap_count - 1;
|
||||
if (ap_count - APS_TO_DISPLAY < 0)
|
||||
{
|
||||
ap_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_index = ap_count - APS_TO_DISPLAY;
|
||||
}
|
||||
}
|
||||
else if (ap_selected < ap_index)
|
||||
{
|
||||
ap_index--;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_wifi_dwn(void)
|
||||
{
|
||||
ap_selected++;
|
||||
if (ap_selected >= ap_count)
|
||||
{
|
||||
ap_selected = 0;
|
||||
ap_index = 0;
|
||||
}
|
||||
else if (ap_selected >= (ap_index + APS_TO_DISPLAY))
|
||||
{
|
||||
ap_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void interface_wifi_display(void)
|
||||
{
|
||||
ssd1306_menu_headline(SSD1306_ADDRESS, 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);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int index = i + ap_index;
|
||||
if (index < ap_count)
|
||||
{
|
||||
if (index == ap_selected)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
}
|
||||
else
|
||||
{
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, " / ", i * 2 + 2, 2, false);
|
||||
}
|
||||
|
||||
if (ap_info[index].rssi >= -67)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
}
|
||||
else if (ap_info[index].rssi >= -90)
|
||||
{
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_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);
|
||||
}
|
||||
}
|
||||
|
||||
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_set_display_function(&interface_wifi_display);
|
||||
|
||||
ESP_LOGD(INTERFACE_LOG, "start wifi interface and scanning");
|
||||
|
||||
memset(ap_info, 0, sizeof(ap_info));
|
||||
ap_count = 0;
|
||||
ap_index = 0;
|
||||
ap_selected = 0;
|
||||
|
||||
wifi_controller_scan(ap_info, &ap_count);
|
||||
}
|
@ -14,85 +14,101 @@
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "ssd1306-gfx.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
static int current_interface_state = INTERFACE_STATE_IDLE;
|
||||
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_display_function current_display_function;
|
||||
|
||||
static int touch_mapping[TOUCH_PAD_COUNT] = {0};
|
||||
static bool touch_status[TOUCH_PAD_COUNT] = {0};
|
||||
static interface_touch_callback touch_callbacks[TOUCH_PAD_MAX];
|
||||
|
||||
void interface_register_touch_callback(int touch_pad, interface_touch_callback callback)
|
||||
void interface_register_button_callback(int button_gpio, interface_button_callback callback)
|
||||
{
|
||||
touch_callbacks[touch_pad] = callback;
|
||||
button_callbacks[button_gpio] = callback;
|
||||
}
|
||||
|
||||
void interface_run(void *pvParameter)
|
||||
void interface_set_display_function(interface_display_function display_function)
|
||||
{
|
||||
ssd1306_clear(SSD1306_ADDRESS);
|
||||
current_display_function = display_function;
|
||||
}
|
||||
|
||||
void interface_input_check(uint8_t gpio)
|
||||
{
|
||||
button_states[gpio] = gpio_get_level(gpio);
|
||||
|
||||
if (old_button_states[gpio] != 0 && old_button_states[gpio] != 1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
static uint16_t touch_value;
|
||||
static uint16_t touch_thresh;
|
||||
static bool touch_status_current[TOUCH_PAD_MAX] = {0};
|
||||
while (1)
|
||||
{
|
||||
for (int i = 0; i < TOUCH_PAD_COUNT; i++)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_display_task(void *pvParameter)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (current_display_function != NULL)
|
||||
{
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(touch_pad_read_filtered(touch_mapping[i], &touch_value));
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(touch_pad_get_thresh(touch_mapping[i], &touch_thresh));
|
||||
touch_status_current[i] = touch_value < touch_thresh;
|
||||
|
||||
if (!touch_status[i] & touch_status_current[i])
|
||||
{
|
||||
ESP_LOGD(INTERFACE_LOG, "touch %u at %d (thresh %u)", touch_value, touch_mapping[i], touch_thresh);
|
||||
if (touch_callbacks[touch_mapping[i]] != NULL)
|
||||
{
|
||||
(*touch_callbacks[touch_mapping[i]])();
|
||||
}
|
||||
}
|
||||
touch_status[i] = touch_status_current[i];
|
||||
(*current_display_function)();
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_start(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
ESP_ERROR_CHECK(touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V));
|
||||
ESP_ERROR_CHECK(touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW));
|
||||
|
||||
touch_mapping[0] = TOUCH_PAD_ESC;
|
||||
touch_mapping[1] = TOUCH_PAD_OK;
|
||||
touch_mapping[2] = TOUCH_PAD_UP;
|
||||
touch_mapping[3] = TOUCH_PAD_DOWN;
|
||||
gpio_config_t io_conf;
|
||||
|
||||
for (int i = 0; i < TOUCH_PAD_COUNT; i++)
|
||||
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);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
ESP_ERROR_CHECK(touch_pad_config(touch_mapping[i], 0));
|
||||
ssd1306_data(SSD1306_ADDRESS, ssd1306_gfx_logo[i], 64, i, 32, false);
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD));
|
||||
uint16_t touch_value;
|
||||
for (int i = 0; i < TOUCH_PAD_COUNT; i++)
|
||||
{
|
||||
ESP_ERROR_CHECK(touch_pad_read_filtered(touch_mapping[i], &touch_value));
|
||||
ESP_ERROR_CHECK(touch_pad_set_thresh(touch_mapping[i], touch_value * 2 / 3));
|
||||
ESP_LOGD(INTERFACE_LOG, "calibrate %u at %u (thresh %u)", touch_mapping[i], touch_value, (touch_value * 2 / 3));
|
||||
}
|
||||
|
||||
xTaskCreate(&interface_run, "interface_run", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
||||
int interface_get_state(void)
|
||||
{
|
||||
return current_interface_state;
|
||||
}
|
||||
|
||||
void interface_set_state(interface_state_t state)
|
||||
{
|
||||
current_interface_state = state;
|
||||
}
|
||||
|
193
components/interface/interface.h
Normal file
193
components/interface/interface.h
Normal file
@ -0,0 +1,193 @@
|
||||
// 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 functionality via input buttons for control and setup
|
||||
*
|
||||
*/
|
||||
#ifndef _interface_H_
|
||||
#define _interface_H_
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#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 locales
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
EN = 0,
|
||||
DE,
|
||||
} interface_locale_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
char *text[INTERFACE_NUM_LOCALE];
|
||||
|
||||
} interface_label_t;
|
||||
|
||||
// label variables
|
||||
interface_label_t interface_text_button_cancel;
|
||||
interface_label_t interface_text_button_ok;
|
||||
interface_label_t interface_text_button_menu;
|
||||
interface_label_t interface_text_button_report;
|
||||
|
||||
interface_label_t interface_text_headline_tan;
|
||||
interface_label_t interface_text_headline_wifi;
|
||||
interface_label_t interface_text_headline_time;
|
||||
interface_label_t interface_text_headline_data;
|
||||
interface_label_t interface_text_headline_settings;
|
||||
interface_label_t interface_text_headline_debug;
|
||||
|
||||
interface_label_t interface_text_settings_locale;
|
||||
interface_label_t interface_text_settings_locales[INTERFACE_NUM_LOCALE];
|
||||
interface_label_t interface_text_settings_timezone;
|
||||
|
||||
interface_label_t interface_text_wifi_scanning;
|
||||
|
||||
interface_label_t interface_text_data_del[5];
|
||||
|
||||
interface_label_t interface_texts_weekday[7];
|
||||
|
||||
interface_label_t interface_texts_month[12];
|
||||
|
||||
/**
|
||||
* @brief callback function for button press
|
||||
*/
|
||||
typedef void (*interface_button_callback)(void);
|
||||
|
||||
/**
|
||||
* @brief current display function
|
||||
*/
|
||||
typedef void (*interface_display_function)(void);
|
||||
|
||||
/**
|
||||
* @brief callback function for text_input
|
||||
*
|
||||
* @param[in] text the text from input
|
||||
* @param[in] cursor current cursor position
|
||||
*/
|
||||
typedef void (*interface_input_callback)(char *text, uint8_t cursor);
|
||||
|
||||
/**
|
||||
* @brief init label
|
||||
*/
|
||||
void interface_init_label(void);
|
||||
|
||||
/**
|
||||
* @brief get text from label for set locale
|
||||
*
|
||||
* @param[in] label the label to get the text from
|
||||
*/
|
||||
char *interface_get_label_text(interface_label_t *label);
|
||||
|
||||
/**
|
||||
* @brief set locale for interface
|
||||
*
|
||||
* @return
|
||||
* interface_locale_t current locale
|
||||
*/
|
||||
interface_locale_t interface_get_locale(void);
|
||||
|
||||
/**
|
||||
* @brief set locale for interface
|
||||
*
|
||||
* @param[in] locale the locale to set
|
||||
*/
|
||||
void interface_set_locale(interface_locale_t locale);
|
||||
|
||||
/**
|
||||
* @brief register a callback function for button event
|
||||
*
|
||||
* @param[in] button_gpio id of the button to listen to
|
||||
* @param[in] callback callback function
|
||||
*/
|
||||
void interface_register_button_callback(int button_gpio, interface_button_callback callback);
|
||||
|
||||
/**
|
||||
* @brief set the display function
|
||||
*
|
||||
* @param[in] display_function display function
|
||||
*/
|
||||
void interface_set_display_function(interface_display_function display_function);
|
||||
|
||||
/**
|
||||
* @brief start interface logic
|
||||
*
|
||||
* This will initialize the controls and start a task to listen to button inputs and calling the callbacks.
|
||||
*/
|
||||
void interface_start(void);
|
||||
|
||||
/**
|
||||
* @brief start delete data interface
|
||||
*/
|
||||
void interface_data_start(void);
|
||||
|
||||
/**
|
||||
* @brief start datetime interface
|
||||
*/
|
||||
void interface_datetime_start(void);
|
||||
|
||||
/**
|
||||
* @brief start main interface
|
||||
*/
|
||||
void interface_main_start(void);
|
||||
|
||||
/**
|
||||
* @brief start report interface
|
||||
*/
|
||||
void interface_report_start(void);
|
||||
|
||||
/**
|
||||
* @brief start wifi interface
|
||||
*/
|
||||
void interface_wifi_start(void);
|
||||
|
||||
/**
|
||||
* @brief start settings interface
|
||||
*/
|
||||
void interface_settings_start(void);
|
||||
|
||||
/**
|
||||
* @brief start interface for input
|
||||
*
|
||||
* @param[in] callback_rst function to call on RST
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @brief set text for input interface
|
||||
*
|
||||
* @param[in] text the text to set
|
||||
*/
|
||||
void interface_input_set_text(char *text);
|
||||
|
||||
#endif
|
@ -1,7 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"ssd1306.c"
|
||||
INCLUDE_DIRS "include"
|
||||
"ssd1306-gfx.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
i2c-main
|
||||
)
|
@ -1,538 +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.
|
||||
#ifndef _ssd1306_FONT_H_
|
||||
#define _ssd1306_FONT_H_
|
||||
|
||||
/**
|
||||
* @brief constant containing a 5x8 ascii font
|
||||
*/
|
||||
const uint8_t ascii_font_5x8[256][5] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00
|
||||
{0x1E, 0x35, 0x31, 0x35, 0x1E}, // 0x01
|
||||
{0x1E, 0x35, 0x37, 0x35, 0x1E}, // 0x02
|
||||
{0x0E, 0x1F, 0x3E, 0x1F, 0x0E}, // 0x03
|
||||
{0x08, 0x1C, 0x7F, 0x1C, 0x08}, // 0x04
|
||||
{0x18, 0x4A, 0x7F, 0x4A, 0x18}, // 0x05
|
||||
{0x1C, 0x4E, 0x7F, 0x4E, 0x1C}, // 0x06
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x07
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x08
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A
|
||||
{0x38, 0x44, 0x44, 0x47, 0x3B}, // 0x0B
|
||||
{0x0E, 0x51, 0xF1, 0x51, 0x0E}, // 0x0C
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D
|
||||
{0x60, 0x7E, 0x02, 0x33, 0x3F}, // 0x0E
|
||||
{0x2A, 0x1C, 0x36, 0x1C, 0x2A}, // 0x0F
|
||||
{0x3E, 0x1C, 0x1C, 0x08, 0x08}, // 0x10
|
||||
{0x08, 0x08, 0x1C, 0x1C, 0x3E}, // 0x11
|
||||
{0x00, 0x22, 0x7F, 0x22, 0x00}, // 0x12
|
||||
{0x00, 0x2E, 0x00, 0x2E, 0x00}, // 0x13
|
||||
{0x06, 0x7F, 0x01, 0x7F, 0x00}, // 0x14
|
||||
{0x00, 0x4A, 0x55, 0x29, 0x00}, // 0x15
|
||||
{0x00, 0x18, 0x18, 0x18, 0x18}, // 0x16
|
||||
{0x00, 0x4A, 0x5F, 0x4A, 0x00}, // 0x17
|
||||
{0x00, 0x02, 0x7F, 0x02, 0x00}, // 0x18
|
||||
{0x00, 0x20, 0x7F, 0x20, 0x00}, // 0x19
|
||||
{0x00, 0x08, 0x08, 0x1C, 0x08}, // 0x1A
|
||||
{0x00, 0x08, 0x1C, 0x08, 0x08}, // 0x1B
|
||||
{0x00, 0x3C, 0x20, 0x20, 0x20}, // 0x1C
|
||||
{0x08, 0x1C, 0x08, 0x1C, 0x08}, // 0x1D
|
||||
{0x20, 0x38, 0x3E, 0x38, 0x20}, // 0x1E
|
||||
{0x02, 0x0E, 0x3E, 0x0E, 0x02}, // 0x1F
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20 (Space)
|
||||
{0x00, 0x00, 0x9E, 0x00, 0x00}, // 0x21 !
|
||||
{0x00, 0x0E, 0x00, 0x0E, 0x00}, // 0x22 "
|
||||
{0x28, 0xFE, 0x28, 0xFE, 0x28}, // 0x23 #
|
||||
{0x48, 0x54, 0xFE, 0x54, 0x24}, // 0x24 $
|
||||
{0x46, 0x26, 0x10, 0xC8, 0xC4}, // 0x25 %
|
||||
{0x6C, 0x92, 0xAA, 0x44, 0xA0}, // 0x26 &
|
||||
{0x00, 0x0A, 0x06, 0x00, 0x00}, // 0x27 '
|
||||
{0x00, 0x38, 0x44, 0x82, 0x00}, // 0x28 (
|
||||
{0x00, 0x82, 0x44, 0x38, 0x00}, // 0x29 )
|
||||
{0x10, 0x54, 0x38, 0x54, 0x10}, // 0x2A *
|
||||
{0x10, 0x10, 0x7C, 0x10, 0x10}, // 0x2B +
|
||||
{0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x2C ,
|
||||
{0x10, 0x10, 0x10, 0x10, 0x10}, // 0x2D -
|
||||
{0x00, 0x60, 0x60, 0x00, 0x00}, // 0x2E .
|
||||
{0x40, 0x20, 0x10, 0x08, 0x04}, // 0x2F /
|
||||
{0x7C, 0xA2, 0x92, 0x8A, 0x7C}, // 0x30 0
|
||||
{0x00, 0x84, 0xFE, 0x80, 0x00}, // 0x31 1
|
||||
{0x84, 0xC2, 0xA2, 0x92, 0x8C}, // 0x32 2
|
||||
{0x42, 0x82, 0x8A, 0x96, 0x62}, // 0x33 3
|
||||
{0x30, 0x28, 0x24, 0xFE, 0x20}, // 0x34 4
|
||||
{0x4E, 0x8A, 0x8A, 0x8A, 0x72}, // 0x35 5
|
||||
{0x78, 0x94, 0x92, 0x92, 0x60}, // 0x36 6
|
||||
{0x02, 0xE2, 0x12, 0x0A, 0x06}, // 0x37 7
|
||||
{0x6C, 0x92, 0x92, 0x92, 0x6C}, // 0x38 8
|
||||
{0x0C, 0x92, 0x92, 0x52, 0x3C}, // 0x39 9
|
||||
{0x00, 0x6C, 0x6C, 0x00, 0x00}, // 0x3A :
|
||||
{0x00, 0xAC, 0x6C, 0x00, 0x00}, // 0x3B ;
|
||||
{0x00, 0x10, 0x28, 0x44, 0x82}, // 0x3C <
|
||||
{0x28, 0x28, 0x28, 0x28, 0x28}, // 0x3D =
|
||||
{0x82, 0x44, 0x28, 0x10, 0x00}, // 0x3E >
|
||||
{0x04, 0x02, 0xA2, 0x12, 0x0C}, // 0x3F ?
|
||||
{0x64, 0x92, 0xF2, 0x82, 0x7C}, // 0x40 @
|
||||
{0xFC, 0x22, 0x22, 0x22, 0xFC}, // 0x41 A
|
||||
{0xFE, 0x92, 0x92, 0x92, 0x6C}, // 0x42 B
|
||||
{0x7C, 0x82, 0x82, 0x82, 0x44}, // 0x43 C
|
||||
{0xFE, 0x82, 0x82, 0x44, 0x38}, // 0x44 D
|
||||
{0xFE, 0x92, 0x92, 0x92, 0x82}, // 0x45 E
|
||||
{0xFE, 0x12, 0x12, 0x02, 0x02}, // 0x46 F
|
||||
{0x7C, 0x82, 0x82, 0xA2, 0x64}, // 0x47 G
|
||||
{0xFE, 0x10, 0x10, 0x10, 0xFE}, // 0x48 H
|
||||
{0x00, 0x82, 0xFE, 0x82, 0x00}, // 0x49 I
|
||||
{0x40, 0x80, 0x82, 0x7E, 0x02}, // 0x4A J
|
||||
{0xFE, 0x10, 0x28, 0x44, 0x82}, // 0x4B K
|
||||
{0xFE, 0x80, 0x80, 0x80, 0x80}, // 0x4C L
|
||||
{0xFE, 0x04, 0x08, 0x04, 0xFE}, // 0x4D M
|
||||
{0xFE, 0x08, 0x10, 0x20, 0xFE}, // 0x4E N
|
||||
{0x7C, 0x82, 0x82, 0x82, 0x7C}, // 0x4F O
|
||||
{0xFE, 0x12, 0x12, 0x12, 0x0C}, // 0x50 P
|
||||
{0x7C, 0x82, 0xA2, 0x42, 0xBC}, // 0x51 Q
|
||||
{0xFE, 0x12, 0x32, 0x52, 0x8C}, // 0x52 R
|
||||
{0x8C, 0x92, 0x92, 0x92, 0x62}, // 0x53 S
|
||||
{0x02, 0x02, 0xFE, 0x02, 0x02}, // 0x54 T
|
||||
{0x7E, 0x80, 0x80, 0x80, 0x7E}, // 0x55 U
|
||||
{0x3E, 0x40, 0x80, 0x40, 0x3E}, // 0x56 V
|
||||
{0xFE, 0x40, 0x30, 0x40, 0xFE}, // 0x57 W
|
||||
{0xC6, 0x28, 0x10, 0x28, 0xC6}, // 0x58 X
|
||||
{0x06, 0x08, 0xF0, 0x08, 0x06}, // 0x59 Y
|
||||
{0xC2, 0xA2, 0x92, 0x8A, 0x86}, // 0x5A Z
|
||||
{0x00, 0x00, 0xFE, 0x82, 0x82}, // 0x5B [
|
||||
{0x04, 0x08, 0x10, 0x20, 0x40}, // 0x5C "\"
|
||||
{0x82, 0x82, 0xFE, 0x00, 0x00}, // 0x5D ]
|
||||
{0x08, 0x04, 0x02, 0x04, 0x08}, // 0x5E ^
|
||||
{0x80, 0x80, 0x80, 0x80, 0x80}, // 0x5F _
|
||||
{0x00, 0x02, 0x04, 0x08, 0x00}, // 0x60 `
|
||||
{0x40, 0xA8, 0xA8, 0xA8, 0xF0}, // 0x61 a
|
||||
{0xFE, 0x90, 0x88, 0x88, 0x70}, // 0x62 b
|
||||
{0x70, 0x88, 0x88, 0x88, 0x40}, // 0x63 c
|
||||
{0x70, 0x88, 0x88, 0x90, 0xFE}, // 0x64 d
|
||||
{0x70, 0xA8, 0xA8, 0xA8, 0x30}, // 0x65 e
|
||||
{0x10, 0xFC, 0x12, 0x02, 0x04}, // 0x66 f
|
||||
{0x10, 0x28, 0xA8, 0xA8, 0x78}, // 0x67 g
|
||||
{0xFE, 0x10, 0x08, 0x08, 0xF0}, // 0x68 h
|
||||
{0x00, 0x88, 0xFA, 0x80, 0x00}, // 0x69 i
|
||||
{0x40, 0x80, 0x88, 0x7A, 0x00}, // 0x6A j
|
||||
{0x00, 0xFE, 0x20, 0x50, 0x88}, // 0x6B k
|
||||
{0x00, 0x82, 0xFE, 0x80, 0x00}, // 0x6C l
|
||||
{0xF8, 0x08, 0x30, 0x08, 0xF0}, // 0x6D m
|
||||
{0xF8, 0x10, 0x08, 0x08, 0xF0}, // 0x6E n
|
||||
{0x70, 0x88, 0x88, 0x88, 0x70}, // 0x6F o
|
||||
{0xF8, 0x28, 0x28, 0x28, 0x10}, // 0x70 p
|
||||
{0x10, 0x28, 0x28, 0x30, 0xF8}, // 0x71 q
|
||||
{0xF8, 0x10, 0x08, 0x08, 0x10}, // 0x72 r
|
||||
{0x90, 0xA8, 0xA8, 0xA8, 0x40}, // 0x73 s
|
||||
{0x08, 0x7E, 0x88, 0x80, 0x40}, // 0x74 t
|
||||
{0x78, 0x80, 0x80, 0x40, 0xF8}, // 0x75 u
|
||||
{0x38, 0x40, 0x80, 0x40, 0x38}, // 0x76 v
|
||||
{0x78, 0x80, 0x60, 0x80, 0x78}, // 0x77 w
|
||||
{0x88, 0x50, 0x20, 0x50, 0x88}, // 0x78 x
|
||||
{0x18, 0xA0, 0xA0, 0xA0, 0x78}, // 0x79 y
|
||||
{0x88, 0xC8, 0xA8, 0x98, 0x88}, // 0x7A z
|
||||
{0x00, 0x10, 0x6C, 0x82, 0x00}, // 0x7B {
|
||||
{0x00, 0x00, 0xFE, 0x00, 0x00}, // 0x7C |
|
||||
{0x00, 0x82, 0x6C, 0x10, 0x00}, // 0x7D }
|
||||
{0x20, 0x10, 0x10, 0x20, 0x10}, // 0x7E
|
||||
{0xF0, 0x88, 0x84, 0x88, 0xF0}, // 0x7F
|
||||
{0x28, 0x7C, 0xAA, 0x82, 0x44}, // 0x80 €
|
||||
{0xF0, 0x29, 0x27, 0x21, 0xFF}, // 0x81
|
||||
{0x00, 0xA0, 0x60, 0x00, 0x00}, // 0x82 ‚
|
||||
{0x40, 0x90, 0x7C, 0x12, 0x04}, // 0x83 ƒ
|
||||
{0xC0, 0xA0, 0x00, 0xC0, 0xA0}, // 0x84 „
|
||||
{0x80, 0x00, 0x80, 0x00, 0x80}, // 0x85 …
|
||||
{0x00, 0x04, 0xFE, 0x04, 0x00}, // 0x86 †
|
||||
{0x00, 0x44, 0xFE, 0x44, 0x00}, // 0x87 ‡
|
||||
{0x00, 0x04, 0x02, 0x04, 0x00}, // 0x88 ˆ
|
||||
{0xC3, 0xD3, 0x08, 0xC4, 0xC2}, // 0x89 ‰
|
||||
{0x4C, 0x93, 0x92, 0x93, 0x64}, // 0x8A Š
|
||||
{0x00, 0x10, 0x28, 0x00, 0x00}, // 0x8B ‹
|
||||
{0x7C, 0x82, 0x82, 0x7C, 0x92}, // 0x8C Œ
|
||||
{0x02, 0xFE, 0x90, 0x90, 0x60}, // 0x8D
|
||||
{0xC2, 0xA3, 0x92, 0x8B, 0x86}, // 0x8E Ž
|
||||
{0x44, 0x92, 0x8A, 0x92, 0x7C}, // 0x8F
|
||||
{0x70, 0x88, 0x90, 0x60, 0x98}, // 0x90
|
||||
{0x00, 0x02, 0x04, 0x08, 0x00}, // 0x91 ‘
|
||||
{0x00, 0x08, 0x04, 0x02, 0x00}, // 0x92 ’
|
||||
{0x02, 0x04, 0x0A, 0x04, 0x08}, // 0x93 “
|
||||
{0x08, 0x04, 0x0A, 0x04, 0x02}, // 0x94 ”
|
||||
{0x00, 0x38, 0x38, 0x38, 0x00}, // 0x95 •
|
||||
{0x00, 0x10, 0x10, 0x10, 0x10}, // 0x96 –
|
||||
{0x10, 0x10, 0x10, 0x10, 0x10}, // 0x97 —
|
||||
{0x02, 0x01, 0x02, 0x04, 0x02}, // 0x98 ˜
|
||||
{0xF1, 0x5B, 0x55, 0x51, 0x51}, // 0x99 ™
|
||||
{0x90, 0xA9, 0xAA, 0xA9, 0x40}, // 0x9A š
|
||||
{0x00, 0x88, 0x50, 0x20, 0x00}, // 0x9B ›
|
||||
{0x70, 0x88, 0x70, 0xA8, 0xB0}, // 0x9C ϡ
|
||||
{0x38, 0x7C, 0xF8, 0x7C, 0x38}, // 0x9D
|
||||
{0x88, 0xC9, 0xAA, 0x99, 0x88}, // 0x9E ž
|
||||
{0x1C, 0x21, 0xC0, 0x21, 0x1C}, // 0x9F Ÿ
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // 0xA0
|
||||
{0x00, 0x00, 0xF2, 0x00, 0x00}, // 0xA1 ¡
|
||||
{0x38, 0x44, 0xFE, 0x44, 0x20}, // 0xA2 ¢
|
||||
{0x90, 0x7C, 0x92, 0x82, 0x40}, // 0xA3 £
|
||||
{0x44, 0x38, 0x28, 0x38, 0x44}, // 0xA4 ¤
|
||||
{0x2A, 0x2C, 0xF8, 0x2C, 0x2A}, // 0xA5 ¥
|
||||
{0x00, 0x00, 0xEE, 0x00, 0x00}, // 0xA6 ¦
|
||||
{0x40, 0x94, 0xAA, 0x52, 0x04}, // 0xA7 §
|
||||
{0x00, 0x02, 0x00, 0x02, 0x00}, // 0xA8 ¨
|
||||
{0xFE, 0x82, 0xBA, 0x92, 0xFE}, // 0xA9 ©
|
||||
{0x90, 0xAA, 0xAA, 0xAA, 0xBC}, // 0xAA ª
|
||||
{0x20, 0x50, 0xA8, 0x50, 0x88}, // 0xAB «
|
||||
{0x20, 0x20, 0x20, 0x20, 0xE0}, // 0xAC ¬
|
||||
{0x20, 0x20, 0x20, 0x20, 0x20}, // 0xAD
|
||||
{0xFE, 0x82, 0xCA, 0xA2, 0xFE}, // 0xAE ®
|
||||
{0x02, 0x02, 0x02, 0x02, 0x02}, // 0xAF ¯
|
||||
{0x0E, 0x11, 0x11, 0x0E, 0x00}, // 0xB0 °
|
||||
{0x88, 0x88, 0xBE, 0x88, 0x88}, // 0xB1 ±
|
||||
{0x12, 0x19, 0x15, 0x12, 0x00}, // 0xB2 ²
|
||||
{0x11, 0x15, 0x15, 0x0A, 0x00}, // 0xB3 ³
|
||||
{0x00, 0x08, 0x04, 0x02, 0x00}, // 0xB4 ´
|
||||
{0xFE, 0x20, 0x20, 0x10, 0x3E}, // 0xB5 µ
|
||||
{0x0C, 0x12, 0x12, 0xFE, 0xFE}, // 0xB6 ¶
|
||||
{0x00, 0x30, 0x30, 0x00, 0x00}, // 0xB7 ·
|
||||
{0x00, 0x80, 0xB0, 0x40, 0x00}, // 0xB8 ¸
|
||||
{0x00, 0x02, 0x0F, 0x00, 0x00}, // 0xB9 ¹
|
||||
{0x00, 0x02, 0x05, 0x02, 0x00}, // 0xBA º
|
||||
{0x44, 0x28, 0x54, 0x28, 0x10}, // 0xBB »
|
||||
{0x22, 0x1F, 0x68, 0x54, 0xFA}, // 0xBC ¼
|
||||
{0x02, 0x1F, 0x90, 0xC8, 0xB0}, // 0xBD ½
|
||||
{0x15, 0x1F, 0x60, 0x50, 0xF8}, // 0xBE ¾
|
||||
{0x60, 0x90, 0x8A, 0x80, 0x40}, // 0xBF ¿
|
||||
{0xF0, 0x29, 0x26, 0x28, 0xF0}, // 0xC0 À
|
||||
{0xF0, 0x28, 0x26, 0x29, 0xF0}, // 0xC1 Á
|
||||
{0xF0, 0x2A, 0x29, 0x2A, 0xF0}, // 0xC2 Â
|
||||
{0xF2, 0x29, 0x29, 0x2A, 0xF1}, // 0xC3 Ã
|
||||
{0xF0, 0x29, 0x24, 0x29, 0xF0}, // 0xC4 Ä
|
||||
{0xF0, 0x2A, 0x2D, 0x2A, 0xF0}, // 0xC5 Å
|
||||
{0xF8, 0x24, 0xFE, 0x92, 0x92}, // 0xC6 Æ
|
||||
{0x1E, 0x21, 0xA1, 0xE1, 0x12}, // 0xC7 Ç
|
||||
{0xF8, 0xA9, 0xAA, 0xA8, 0x88}, // 0xC8 È
|
||||
{0xF8, 0xA8, 0xAA, 0xA9, 0x88}, // 0xC9 É
|
||||
{0xF8, 0xAA, 0xA9, 0xAA, 0x88}, // 0xCA Ê
|
||||
{0xF8, 0xAA, 0xA8, 0xAA, 0x88}, // 0xCB Ë
|
||||
{0x00, 0x89, 0xFA, 0x88, 0x00}, // 0xCC Ì
|
||||
{0x00, 0x88, 0xFA, 0x89, 0x00}, // 0xCD Í
|
||||
{0x00, 0x8A, 0xF9, 0x8A, 0x00}, // 0xCE Î
|
||||
{0x00, 0x8A, 0xF8, 0x8A, 0x00}, // 0xCF Ï
|
||||
{0x10, 0xFE, 0x92, 0x82, 0x7C}, // 0xD0 Ð
|
||||
{0xFA, 0x11, 0x21, 0x42, 0xF9}, // 0xD1 Ñ
|
||||
{0x78, 0x85, 0x86, 0x84, 0x78}, // 0xD2 Ò
|
||||
{0x78, 0x84, 0x86, 0x85, 0x78}, // 0xD3 Ó
|
||||
{0x70, 0x8A, 0x89, 0x8A, 0x70}, // 0xD4 Ô
|
||||
{0x72, 0x89, 0x89, 0x8A, 0x71}, // 0xD5 Õ
|
||||
{0x78, 0x85, 0x84, 0x85, 0x78}, // 0xD6 Ö
|
||||
{0x44, 0x28, 0x10, 0x28, 0x44}, // 0xD7 ×
|
||||
{0x10, 0xAA, 0xFE, 0xAA, 0x10}, // 0xD8 Ø
|
||||
{0x7C, 0x81, 0x82, 0x80, 0x7C}, // 0xD9 Ù
|
||||
{0x7C, 0x80, 0x82, 0x81, 0x7C}, // 0xDA Ú
|
||||
{0x78, 0x82, 0x81, 0x82, 0x78}, // 0xDB Û
|
||||
{0x7C, 0x81, 0x80, 0x81, 0x7C}, // 0xDC Ü
|
||||
{0x04, 0x08, 0xF2, 0x09, 0x04}, // 0xDD Ý
|
||||
{0x81, 0xFF, 0x24, 0x24, 0x18}, // 0xDE Þ
|
||||
{0x80, 0x7C, 0x92, 0x92, 0x6C}, // 0xDF ß
|
||||
{0x40, 0xA9, 0xAA, 0xA8, 0xF0}, // 0xE0 à
|
||||
{0x40, 0xA8, 0xAA, 0xA9, 0xF0}, // 0xE1 á
|
||||
{0x40, 0xAA, 0xA9, 0xAA, 0xF0}, // 0xE2 â
|
||||
{0x42, 0xA9, 0xA9, 0xAA, 0xF1}, // 0xE3 ã
|
||||
{0x40, 0xAA, 0xA8, 0xAA, 0xF0}, // 0xE4 ä
|
||||
{0x40, 0xAA, 0xAD, 0xAA, 0xF0}, // 0xE5 å
|
||||
{0x64, 0x94, 0x78, 0x94, 0x58}, // 0xE6 æ
|
||||
{0x18, 0x24, 0xA4, 0xE4, 0x10}, // 0xE7 ç
|
||||
{0x70, 0xA9, 0xAA, 0xA8, 0x30}, // 0xE8 è
|
||||
{0x70, 0xA8, 0xAA, 0xA9, 0x30}, // 0xE9 é
|
||||
{0x70, 0xAA, 0xA9, 0xAA, 0x30}, // 0xEA ê
|
||||
{0x70, 0xAA, 0xA8, 0xAA, 0x30}, // 0xEB ë
|
||||
{0x00, 0x91, 0xFA, 0x80, 0x00}, // 0xEC ì
|
||||
{0x00, 0x90, 0xFA, 0x81, 0x00}, // 0xED í
|
||||
{0x00, 0x92, 0xF9, 0x82, 0x00}, // 0xEE î
|
||||
{0x00, 0x92, 0xF8, 0x82, 0x00}, // 0xEF ï
|
||||
{0x4A, 0xA4, 0xAA, 0xB0, 0x60}, // 0xF0 ð
|
||||
{0xFA, 0x11, 0x09, 0x0A, 0xF1}, // 0xF1 ñ
|
||||
{0x70, 0x89, 0x8A, 0x88, 0x70}, // 0xF2 ò
|
||||
{0x70, 0x88, 0x8A, 0x89, 0x70}, // 0xF3 ó
|
||||
{0x60, 0x94, 0x92, 0x94, 0x60}, // 0xF4 ô
|
||||
{0x64, 0x92, 0x92, 0x94, 0x62}, // 0xF5 õ
|
||||
{0x70, 0x8A, 0x88, 0x8A, 0x70}, // 0xF6 ö
|
||||
{0x10, 0x10, 0x54, 0x10, 0x10}, // 0xF7 ÷
|
||||
{0x10, 0xA8, 0x7C, 0x2A, 0x10}, // 0xF8 ø
|
||||
{0x78, 0x81, 0x82, 0x40, 0xF8}, // 0xF9 ù
|
||||
{0x78, 0x80, 0x82, 0x41, 0xF8}, // 0xFA ú
|
||||
{0x78, 0x82, 0x81, 0x42, 0xF8}, // 0xFB û
|
||||
{0x78, 0x82, 0x80, 0x42, 0xF8}, // 0xFC ü
|
||||
{0x18, 0xA0, 0xA4, 0xA2, 0x78}, // 0xFD v
|
||||
{0x00, 0x82, 0xFE, 0xA8, 0x10}, // 0xFE þ
|
||||
{0x18, 0xA2, 0xA0, 0xA2, 0x78} // 0xFF ÿ
|
||||
};
|
||||
|
||||
const uint8_t ascii_font_8x8[256][8] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00
|
||||
{0x7E, 0x81, 0x95, 0xB1, 0xB1, 0x95, 0x81, 0x7E}, // 0x01
|
||||
{0x7E, 0xFF, 0xEB, 0xCF, 0xCF, 0xEB, 0xFF, 0x7E}, // 0x02
|
||||
{0x0E, 0x1F, 0x3F, 0x7E, 0x3F, 0x1F, 0x0E, 0x00}, // 0x03
|
||||
{0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x00}, // 0x04
|
||||
{0x38, 0x3A, 0x9F, 0xFF, 0x9F, 0x3A, 0x38, 0x00}, // 0x05
|
||||
{0x10, 0x38, 0xBC, 0xFF, 0xBC, 0x38, 0x10, 0x00}, // 0x06
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x07
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x08
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x09
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0A
|
||||
{0x70, 0xF8, 0x88, 0x88, 0xFD, 0x7F, 0x07, 0x0F}, // 0x0B
|
||||
{0x00, 0x4E, 0x5F, 0xF1, 0xF1, 0x5F, 0x4E, 0x00}, // 0x0C
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x0D
|
||||
{0xC0, 0xFF, 0x7F, 0x05, 0x05, 0x65, 0x7F, 0x3F}, // 0x0E
|
||||
{0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99}, // 0x0F
|
||||
{0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x00}, // 0x10
|
||||
{0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x00}, // 0x11
|
||||
{0x00, 0x24, 0x66, 0xFF, 0xFF, 0x66, 0x24, 0x00}, // 0x12
|
||||
{0x00, 0x5F, 0x5F, 0x00, 0x00, 0x5F, 0x5F, 0x00}, // 0x13
|
||||
{0x06, 0x0F, 0x09, 0x7F, 0x7F, 0x01, 0x7F, 0x7F}, // 0x14
|
||||
{0xDA, 0xBF, 0xA5, 0xA5, 0xFD, 0x59, 0x03, 0x02}, // 0x15
|
||||
{0x00, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x00}, // 0x16
|
||||
{0x80, 0x94, 0xB6, 0xFF, 0xFF, 0xB6, 0x94, 0x80}, // 0x17
|
||||
{0x00, 0x04, 0x06, 0x7F, 0x7F, 0x06, 0x04, 0x00}, // 0x18
|
||||
{0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00}, // 0x19
|
||||
{0x08, 0x08, 0x08, 0x2A, 0x3E, 0x1C, 0x08, 0x00}, // 0x1A
|
||||
{0x08, 0x1C, 0x3E, 0x2A, 0x08, 0x08, 0x08, 0x00}, // 0x1B
|
||||
{0x3C, 0x3C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // 0x1C
|
||||
{0x08, 0x1C, 0x3E, 0x08, 0x08, 0x3E, 0x1C, 0x08}, // 0x1D
|
||||
{0x30, 0x38, 0x3C, 0x3E, 0x3E, 0x3C, 0x38, 0x30}, // 0x1E
|
||||
{0x06, 0x0E, 0x1E, 0x3E, 0x3E, 0x1E, 0x0E, 0x06}, // 0x1F
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x20
|
||||
{0x00, 0x06, 0x5F, 0x5F, 0x06, 0x00, 0x00, 0x00}, // 0x21
|
||||
{0x00, 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x00}, // 0x22
|
||||
{0x14, 0x7F, 0x7F, 0x14, 0x7F, 0x7F, 0x14, 0x00}, // 0x23
|
||||
{0x24, 0x2E, 0x6B, 0x6B, 0x3A, 0x12, 0x00, 0x00}, // 0x24
|
||||
{0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, 0x00}, // 0x25
|
||||
{0x30, 0x7A, 0x4F, 0x5D, 0x37, 0x7A, 0x48, 0x00}, // 0x26
|
||||
{0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x27
|
||||
{0x00, 0x1C, 0x3E, 0x63, 0x41, 0x00, 0x00, 0x00}, // 0x28
|
||||
{0x00, 0x41, 0x63, 0x3E, 0x1C, 0x00, 0x00, 0x00}, // 0x29
|
||||
{0x08, 0x2A, 0x3E, 0x1C, 0x1C, 0x3E, 0x2A, 0x08}, // 0x2A
|
||||
{0x08, 0x08, 0x3E, 0x3E, 0x08, 0x08, 0x00, 0x00}, // 0x2B
|
||||
{0x00, 0xA0, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00}, // 0x2C
|
||||
{0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, // 0x2D
|
||||
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, // 0x2E
|
||||
{0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // 0x2F
|
||||
{0x3E, 0x7F, 0x59, 0x4D, 0x7F, 0x3E, 0x00, 0x00}, // 0x30
|
||||
{0x42, 0x42, 0x7F, 0x7F, 0x40, 0x40, 0x00, 0x00}, // 0x31
|
||||
{0x62, 0x73, 0x59, 0x49, 0x6F, 0x66, 0x00, 0x00}, // 0x32
|
||||
{0x22, 0x63, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00}, // 0x33
|
||||
{0x18, 0x1C, 0x16, 0x13, 0x7F, 0x7F, 0x10, 0x00}, // 0x34
|
||||
{0x27, 0x67, 0x45, 0x45, 0x7D, 0x39, 0x00, 0x00}, // 0x35
|
||||
{0x3C, 0x7E, 0x4B, 0x49, 0x79, 0x30, 0x00, 0x00}, // 0x36
|
||||
{0x03, 0x63, 0x71, 0x19, 0x0F, 0x07, 0x00, 0x00}, // 0x37
|
||||
{0x36, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00}, // 0x38
|
||||
{0x06, 0x4F, 0x49, 0x69, 0x3F, 0x1E, 0x00, 0x00}, // 0x39
|
||||
{0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00}, // 0x3A
|
||||
{0x00, 0xA0, 0xEC, 0x6C, 0x00, 0x00, 0x00, 0x00}, // 0x3B
|
||||
{0x08, 0x1C, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00}, // 0x3C
|
||||
{0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00}, // 0x3D
|
||||
{0x00, 0x41, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00}, // 0x3E
|
||||
{0x02, 0x03, 0x51, 0x59, 0x0F, 0x06, 0x00, 0x00}, // 0x3F
|
||||
{0x3E, 0x7F, 0x41, 0x5D, 0x5D, 0x1F, 0x1E, 0x00}, // 0x40
|
||||
{0x7C, 0x7E, 0x13, 0x13, 0x7E, 0x7C, 0x00, 0x00}, // 0x41
|
||||
{0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}, // 0x42
|
||||
{0x1C, 0x3E, 0x63, 0x41, 0x41, 0x63, 0x22, 0x00}, // 0x43
|
||||
{0x41, 0x7F, 0x7F, 0x41, 0x63, 0x7F, 0x1C, 0x00}, // 0x44
|
||||
{0x41, 0x7F, 0x7F, 0x49, 0x5D, 0x41, 0x63, 0x00}, // 0x45
|
||||
{0x41, 0x7F, 0x7F, 0x49, 0x1D, 0x01, 0x03, 0x00}, // 0x46
|
||||
{0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00}, // 0x47
|
||||
{0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00}, // 0x48
|
||||
{0x00, 0x41, 0x7F, 0x7F, 0x41, 0x00, 0x00, 0x00}, // 0x49
|
||||
{0x30, 0x70, 0x40, 0x41, 0x7F, 0x3F, 0x01, 0x00}, // 0x4A
|
||||
{0x41, 0x7F, 0x7F, 0x08, 0x1C, 0x77, 0x63, 0x00}, // 0x4B
|
||||
{0x41, 0x7F, 0x7F, 0x41, 0x40, 0x60, 0x70, 0x00}, // 0x4C
|
||||
{0x7F, 0x7F, 0x06, 0x0C, 0x06, 0x7F, 0x7F, 0x00}, // 0x4D
|
||||
{0x7F, 0x7F, 0x06, 0x0C, 0x18, 0x7F, 0x7F, 0x00}, // 0x4E
|
||||
{0x1C, 0x3E, 0x63, 0x41, 0x63, 0x3E, 0x1C, 0x00}, // 0x4F
|
||||
{0x41, 0x7F, 0x7F, 0x49, 0x09, 0x0F, 0x06, 0x00}, // 0x50
|
||||
{0x1E, 0x3F, 0x21, 0x71, 0x7F, 0x5E, 0x00, 0x00}, // 0x51
|
||||
{0x41, 0x7F, 0x7F, 0x19, 0x39, 0x6F, 0x46, 0x00}, // 0x52
|
||||
{0x26, 0x67, 0x4D, 0x59, 0x7B, 0x32, 0x00, 0x00}, // 0x53
|
||||
{0x03, 0x41, 0x7F, 0x7F, 0x41, 0x03, 0x00, 0x00}, // 0x54
|
||||
{0x7F, 0x7F, 0x40, 0x40, 0x7F, 0x7F, 0x00, 0x00}, // 0x55
|
||||
{0x1F, 0x3F, 0x60, 0x60, 0x3F, 0x1F, 0x00, 0x00}, // 0x56
|
||||
{0x7F, 0x7F, 0x30, 0x18, 0x30, 0x7F, 0x7F, 0x00}, // 0x57
|
||||
{0x63, 0x77, 0x1C, 0x08, 0x1C, 0x77, 0x63, 0x00}, // 0x58
|
||||
{0x07, 0x4F, 0x78, 0x78, 0x4F, 0x07, 0x00, 0x00}, // 0x59
|
||||
{0x67, 0x73, 0x59, 0x4D, 0x47, 0x63, 0x71, 0x00}, // 0x5A
|
||||
{0x00, 0x7F, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00}, // 0x5B
|
||||
{0x01, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00}, // 0x5C
|
||||
{0x00, 0x41, 0x41, 0x7F, 0x7F, 0x00, 0x00, 0x00}, // 0x5D
|
||||
{0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, 0x00}, // 0x5E
|
||||
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, // 0x5F
|
||||
{0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x00}, // 0x60
|
||||
{0x20, 0x74, 0x54, 0x54, 0x3C, 0x78, 0x40, 0x00}, // 0x61
|
||||
{0x41, 0x3F, 0x7F, 0x44, 0x44, 0x7C, 0x38, 0x00}, // 0x62
|
||||
{0x38, 0x7C, 0x44, 0x44, 0x6C, 0x28, 0x00, 0x00}, // 0x63
|
||||
{0x30, 0x78, 0x48, 0x49, 0x3F, 0x7F, 0x40, 0x00}, // 0x64
|
||||
{0x38, 0x7C, 0x54, 0x54, 0x5C, 0x18, 0x00, 0x00}, // 0x65
|
||||
{0x48, 0x7E, 0x7F, 0x49, 0x03, 0x02, 0x00, 0x00}, // 0x66
|
||||
{0x98, 0xBC, 0xA4, 0xA4, 0xF8, 0x7C, 0x04, 0x00}, // 0x67
|
||||
{0x41, 0x7F, 0x7F, 0x08, 0x04, 0x7C, 0x78, 0x00}, // 0x68
|
||||
{0x00, 0x44, 0x7D, 0x7D, 0x40, 0x00, 0x00, 0x00}, // 0x69
|
||||
{0x40, 0xC4, 0x84, 0xFD, 0x7D, 0x00, 0x00, 0x00}, // 0x6A
|
||||
{0x41, 0x7F, 0x7F, 0x10, 0x38, 0x6C, 0x44, 0x00}, // 0x6B
|
||||
{0x00, 0x41, 0x7F, 0x7F, 0x40, 0x00, 0x00, 0x00}, // 0x6C
|
||||
{0x7C, 0x7C, 0x0C, 0x18, 0x0C, 0x7C, 0x78, 0x00}, // 0x6D
|
||||
{0x7C, 0x7C, 0x04, 0x04, 0x7C, 0x78, 0x00, 0x00}, // 0x6E
|
||||
{0x38, 0x7C, 0x44, 0x44, 0x7C, 0x38, 0x00, 0x00}, // 0x6F
|
||||
{0x84, 0xFC, 0xF8, 0xA4, 0x24, 0x3C, 0x18, 0x00}, // 0x70
|
||||
{0x18, 0x3C, 0x24, 0xA4, 0xF8, 0xFC, 0x84, 0x00}, // 0x71
|
||||
{0x44, 0x7C, 0x78, 0x44, 0x1C, 0x18, 0x00, 0x00}, // 0x72
|
||||
{0x48, 0x5C, 0x54, 0x54, 0x74, 0x24, 0x00, 0x00}, // 0x73
|
||||
{0x00, 0x04, 0x3E, 0x7F, 0x44, 0x24, 0x00, 0x00}, // 0x74
|
||||
{0x3C, 0x7C, 0x40, 0x40, 0x3C, 0x7C, 0x40, 0x00}, // 0x75
|
||||
{0x1C, 0x3C, 0x60, 0x60, 0x3C, 0x1C, 0x00, 0x00}, // 0x76
|
||||
{0x3C, 0x7C, 0x60, 0x30, 0x60, 0x7C, 0x3C, 0x00}, // 0x77
|
||||
{0x44, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0x44, 0x00}, // 0x78
|
||||
{0x9C, 0xBC, 0xA0, 0xA0, 0xFC, 0x7C, 0x00, 0x00}, // 0x79
|
||||
{0x4C, 0x64, 0x74, 0x5C, 0x4C, 0x64, 0x00, 0x00}, // 0x7A
|
||||
{0x08, 0x08, 0x3E, 0x77, 0x41, 0x41, 0x00, 0x00}, // 0x7B
|
||||
{0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x00}, // 0x7C
|
||||
{0x41, 0x41, 0x77, 0x3E, 0x08, 0x08, 0x00, 0x00}, // 0x7D
|
||||
{0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00}, // 0x7E
|
||||
{0x78, 0x7C, 0x46, 0x43, 0x46, 0x7C, 0x78, 0x00}, // 0x7F
|
||||
{0x1E, 0xBF, 0xE1, 0x61, 0x33, 0x12, 0x00, 0x00}, // 0x80
|
||||
{0x3A, 0x7A, 0x40, 0x40, 0x7A, 0x7A, 0x40, 0x00}, // 0x81
|
||||
{0x38, 0x7C, 0x56, 0x57, 0x5D, 0x18, 0x00, 0x00}, // 0x82
|
||||
{0x02, 0x23, 0x75, 0x55, 0x55, 0x7D, 0x7B, 0x42}, // 0x83
|
||||
{0x21, 0x75, 0x54, 0x54, 0x7D, 0x79, 0x40, 0x00}, // 0x84
|
||||
{0x20, 0x75, 0x57, 0x56, 0x7C, 0x78, 0x40, 0x00}, // 0x85
|
||||
{0x00, 0x22, 0x77, 0x55, 0x55, 0x7F, 0x7A, 0x40}, // 0x86
|
||||
{0x1C, 0xBE, 0xE2, 0x62, 0x36, 0x14, 0x00, 0x00}, // 0x87
|
||||
{0x02, 0x3B, 0x7D, 0x55, 0x55, 0x5D, 0x1B, 0x02}, // 0x88
|
||||
{0x39, 0x7D, 0x54, 0x54, 0x5D, 0x19, 0x00, 0x00}, // 0x89
|
||||
{0x38, 0x7D, 0x57, 0x56, 0x5C, 0x18, 0x00, 0x00}, // 0x8A
|
||||
{0x01, 0x45, 0x7C, 0x7C, 0x41, 0x01, 0x00, 0x00}, // 0x8B
|
||||
{0x02, 0x03, 0x45, 0x7D, 0x7D, 0x43, 0x02, 0x00}, // 0x8C
|
||||
{0x00, 0x45, 0x7F, 0x7E, 0x40, 0x00, 0x00, 0x00}, // 0x8D
|
||||
{0x79, 0x7D, 0x26, 0x26, 0x7D, 0x79, 0x00, 0x00}, // 0x8E
|
||||
{0x70, 0x7A, 0x2D, 0x2D, 0x7A, 0x70, 0x00, 0x00}, // 0x8F
|
||||
{0x44, 0x7C, 0x7E, 0x57, 0x55, 0x44, 0x00, 0x00}, // 0x90
|
||||
{0x20, 0x74, 0x54, 0x54, 0x7C, 0x7C, 0x54, 0x54}, // 0x91
|
||||
{0x7C, 0x7E, 0x0B, 0x09, 0x7F, 0x7F, 0x49, 0x00}, // 0x92
|
||||
{0x32, 0x7B, 0x49, 0x49, 0x7B, 0x32, 0x00, 0x00}, // 0x93
|
||||
{0x32, 0x7A, 0x48, 0x48, 0x7A, 0x32, 0x00, 0x00}, // 0x94
|
||||
{0x30, 0x79, 0x4B, 0x4A, 0x78, 0x30, 0x00, 0x00}, // 0x95
|
||||
{0x3A, 0x7B, 0x41, 0x41, 0x7B, 0x7A, 0x40, 0x00}, // 0x96
|
||||
{0x38, 0x79, 0x43, 0x42, 0x78, 0x78, 0x40, 0x00}, // 0x97
|
||||
{0xBA, 0xBA, 0xA0, 0xA0, 0xFA, 0x7A, 0x00, 0x00}, // 0x98
|
||||
{0x39, 0x7D, 0x44, 0x44, 0x44, 0x7D, 0x39, 0x00}, // 0x99
|
||||
{0x3D, 0x7D, 0x40, 0x40, 0x7D, 0x3D, 0x00, 0x00}, // 0x9A
|
||||
{0x38, 0x7C, 0x64, 0x54, 0x4C, 0x7C, 0x38, 0x00}, // 0x9B
|
||||
{0x68, 0x7E, 0x7F, 0x49, 0x43, 0x66, 0x20, 0x00}, // 0x9C
|
||||
{0x5C, 0x3E, 0x73, 0x49, 0x67, 0x3E, 0x1D, 0x00}, // 0x9D
|
||||
{0x44, 0x6C, 0x38, 0x38, 0x6C, 0x44, 0x00, 0x00}, // 0x9E
|
||||
{0x40, 0xC8, 0x88, 0xFE, 0x7F, 0x09, 0x0B, 0x02}, // 0x9F
|
||||
{0x20, 0x74, 0x56, 0x57, 0x7D, 0x78, 0x40, 0x00}, // 0xA0
|
||||
{0x00, 0x44, 0x7E, 0x7F, 0x41, 0x00, 0x00, 0x00}, // 0xA1
|
||||
{0x30, 0x78, 0x48, 0x4A, 0x7B, 0x31, 0x00, 0x00}, // 0xA2
|
||||
{0x38, 0x78, 0x40, 0x42, 0x7B, 0x79, 0x40, 0x00}, // 0xA3
|
||||
{0x7A, 0x7B, 0x09, 0x0B, 0x7A, 0x73, 0x01, 0x00}, // 0xA4
|
||||
{0x7A, 0x7B, 0x19, 0x33, 0x7A, 0x7B, 0x01, 0x00}, // 0xA5
|
||||
{0x00, 0x26, 0x2F, 0x29, 0x2F, 0x2F, 0x28, 0x00}, // 0xA6
|
||||
{0x00, 0x26, 0x2F, 0x29, 0x29, 0x2F, 0x26, 0x00}, // 0xA7
|
||||
{0x30, 0x78, 0x4D, 0x45, 0x60, 0x20, 0x00, 0x00}, // 0xA8
|
||||
{0x1C, 0x22, 0x7D, 0x4B, 0x5B, 0x65, 0x22, 0x1C}, // 0xA9
|
||||
{0x08, 0x08, 0x08, 0x08, 0x38, 0x38, 0x00, 0x00}, // 0xAA
|
||||
{0x61, 0x3F, 0x1F, 0xCC, 0xEE, 0xAB, 0xB9, 0x90}, // 0xAB
|
||||
{0x61, 0x3F, 0x1F, 0x4C, 0x66, 0x73, 0xD9, 0xF8}, // 0xAC
|
||||
{0x00, 0x00, 0x60, 0xFA, 0xFA, 0x60, 0x00, 0x00}, // 0xAD
|
||||
{0x08, 0x1C, 0x36, 0x22, 0x08, 0x1C, 0x36, 0x22}, // 0xAE
|
||||
{0x22, 0x36, 0x1C, 0x08, 0x22, 0x36, 0x1C, 0x08}, // 0xAF
|
||||
{0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00}, // 0xB0
|
||||
{0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}, // 0xB1
|
||||
{0x55, 0xFF, 0xAA, 0xFF, 0x55, 0xFF, 0xAA, 0xFF}, // 0xB2
|
||||
{0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // 0xB3
|
||||
{0x10, 0x10, 0x10, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // 0xB4
|
||||
{0x70, 0x78, 0x2C, 0x2E, 0x7B, 0x71, 0x00, 0x00}, // 0xB5
|
||||
{0x72, 0x79, 0x2D, 0x2D, 0x79, 0x72, 0x00, 0x00}, // 0xB6
|
||||
{0x71, 0x7B, 0x2E, 0x2C, 0x78, 0x70, 0x00, 0x00}, // 0xB7
|
||||
{0x1C, 0x22, 0x5D, 0x55, 0x55, 0x41, 0x22, 0x1C}, // 0xB8
|
||||
{0x14, 0x14, 0xF7, 0xF7, 0x00, 0xFF, 0xFF, 0x00}, // 0xB9
|
||||
{0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00}, // 0xBA
|
||||
{0x14, 0x14, 0xF4, 0xF4, 0x04, 0xFC, 0xFC, 0x00}, // 0xBB
|
||||
{0x14, 0x14, 0x17, 0x17, 0x10, 0x1F, 0x1F, 0x00}, // 0xBC
|
||||
{0x18, 0x3C, 0x24, 0xE7, 0xE7, 0x24, 0x24, 0x00}, // 0xBD
|
||||
{0x2B, 0x2F, 0xFC, 0xFC, 0x2F, 0x2B, 0x00, 0x00}, // 0xBE
|
||||
{0x10, 0x10, 0x10, 0xF0, 0xF0, 0x00, 0x00, 0x00}, // 0xBF
|
||||
{0x00, 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x10}, // 0xC0
|
||||
{0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10}, // 0xC1
|
||||
{0x10, 0x10, 0x10, 0xF0, 0xF0, 0x10, 0x10, 0x10}, // 0xC2
|
||||
{0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10}, // 0xC3
|
||||
{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, // 0xC4
|
||||
{0x10, 0x10, 0x10, 0xFF, 0xFF, 0x10, 0x10, 0x10}, // 0xC5
|
||||
{0x22, 0x77, 0x55, 0x57, 0x7E, 0x7B, 0x41, 0x00}, // 0xC6
|
||||
{0x72, 0x7B, 0x2D, 0x2F, 0x7A, 0x73, 0x01, 0x00}, // 0xC7
|
||||
{0x00, 0x00, 0x1F, 0x1F, 0x10, 0x17, 0x17, 0x14}, // 0xC8
|
||||
{0x00, 0x00, 0xFC, 0xFC, 0x04, 0xF4, 0xF4, 0x14}, // 0xC9
|
||||
{0x14, 0x14, 0x17, 0x17, 0x10, 0x17, 0x17, 0x14}, // 0xCA
|
||||
{0x14, 0x14, 0xF4, 0xF4, 0x04, 0xF4, 0xF4, 0x14}, // 0xCB
|
||||
{0x00, 0x00, 0xFF, 0xFF, 0x00, 0xF7, 0xF7, 0x14}, // 0xCC
|
||||
{0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // 0xCD
|
||||
{0x14, 0x14, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0x14}, // 0xCE
|
||||
{0x66, 0x3C, 0x3C, 0x24, 0x3C, 0x3C, 0x66, 0x00}, // 0xCF
|
||||
{0x05, 0x27, 0x72, 0x57, 0x7D, 0x38, 0x00, 0x00}, // 0xD0
|
||||
{0x49, 0x7F, 0x7F, 0x49, 0x63, 0x7F, 0x1C, 0x00}, // 0xD1
|
||||
{0x46, 0x7D, 0x7D, 0x55, 0x55, 0x46, 0x00, 0x00}, // 0xD2
|
||||
{0x45, 0x7D, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x00}, // 0xD3
|
||||
{0x44, 0x7D, 0x7F, 0x56, 0x54, 0x44, 0x00, 0x00}, // 0xD4
|
||||
{0x0A, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xD5
|
||||
{0x00, 0x44, 0x7E, 0x7F, 0x45, 0x00, 0x00, 0x00}, // 0xD6
|
||||
{0x02, 0x45, 0x7D, 0x7D, 0x45, 0x02, 0x00, 0x00}, // 0xD7
|
||||
{0x01, 0x45, 0x7C, 0x7C, 0x45, 0x01, 0x00, 0x00}, // 0xD8
|
||||
{0x10, 0x10, 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x00}, // 0xD9
|
||||
{0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10, 0x10}, // 0xDA
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // 0xDB
|
||||
{0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // 0xDC
|
||||
{0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x00}, // 0xDD
|
||||
{0x00, 0x45, 0x7F, 0x7E, 0x44, 0x00, 0x00, 0x00}, // 0xDE
|
||||
{0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // 0xDF
|
||||
{0x38, 0x7C, 0x46, 0x47, 0x45, 0x7C, 0x38, 0x00}, // 0xE0
|
||||
{0xFC, 0xFE, 0x2A, 0x2A, 0x3E, 0x14, 0x00, 0x00}, // 0xE1
|
||||
{0x3A, 0x7D, 0x45, 0x45, 0x45, 0x7D, 0x3A, 0x00}, // 0xE2
|
||||
{0x38, 0x7C, 0x45, 0x47, 0x46, 0x7C, 0x38, 0x00}, // 0xE3
|
||||
{0x32, 0x7B, 0x49, 0x4B, 0x7A, 0x33, 0x01, 0x00}, // 0xE4
|
||||
{0x3A, 0x7F, 0x45, 0x47, 0x46, 0x7F, 0x39, 0x00}, // 0xE5
|
||||
{0x80, 0xFE, 0x7E, 0x20, 0x20, 0x3E, 0x1E, 0x00}, // 0xE6
|
||||
{0x42, 0x7E, 0x7E, 0x54, 0x1C, 0x08, 0x00, 0x00}, // 0xE7
|
||||
{0x41, 0x7F, 0x7F, 0x55, 0x14, 0x1C, 0x08, 0x00}, // 0xE8
|
||||
{0x3C, 0x7C, 0x42, 0x43, 0x7D, 0x3C, 0x00, 0x00}, // 0xE9
|
||||
{0x3A, 0x79, 0x41, 0x41, 0x79, 0x3A, 0x00, 0x00}, // 0xEA
|
||||
{0x3C, 0x7D, 0x43, 0x42, 0x7C, 0x3C, 0x00, 0x00}, // 0xEB
|
||||
{0xB8, 0xB8, 0xA2, 0xA3, 0xF9, 0x78, 0x00, 0x00}, // 0xEC
|
||||
{0x0C, 0x5C, 0x72, 0x73, 0x5D, 0x0C, 0x00, 0x00}, // 0xED
|
||||
{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, // 0xEE
|
||||
{0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00}, // 0xEF
|
||||
{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00}, // 0xF0
|
||||
{0x44, 0x44, 0x5F, 0x5F, 0x44, 0x44, 0x00, 0x00}, // 0xF1
|
||||
{0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00}, // 0xF2
|
||||
{0x71, 0x35, 0x1F, 0x4C, 0x66, 0x73, 0xD9, 0xF8}, // 0xF3
|
||||
{0x06, 0x0F, 0x09, 0x7F, 0x7F, 0x01, 0x7F, 0x7F}, // 0xF4
|
||||
{0xDA, 0xBF, 0xA5, 0xA5, 0xFD, 0x59, 0x03, 0x02}, // 0xF5
|
||||
{0x08, 0x08, 0x6B, 0x6B, 0x08, 0x08, 0x00, 0x00}, // 0xF6
|
||||
{0x00, 0x80, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00}, // 0xF7
|
||||
{0x00, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00}, // 0xF8
|
||||
{0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00}, // 0xF9
|
||||
{0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00}, // 0xFA
|
||||
{0x00, 0x12, 0x13, 0x1F, 0x1F, 0x10, 0x10, 0x00}, // 0xFB
|
||||
{0x00, 0x11, 0x15, 0x15, 0x1F, 0x1F, 0x0A, 0x00}, // 0xFC
|
||||
{0x00, 0x19, 0x1D, 0x15, 0x17, 0x12, 0x00, 0x00}, // 0xFD
|
||||
{0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, // 0xFE
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 0xFF
|
||||
};
|
||||
|
||||
#endif
|
307
components/ssd1306/ssd1306-gfx.c
Normal file
307
components/ssd1306/ssd1306-gfx.c
Normal file
@ -0,0 +1,307 @@
|
||||
// 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 "ssd1306-gfx.h"
|
||||
|
||||
uint8_t ssd1306_gfx_clear[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t ssd1306_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},
|
||||
{0x00, 0x24, 0x7e, 0x7e, 0x24, 0x7e, 0x7e, 0x24},
|
||||
{0x00, 0x4c, 0xde, 0x92, 0xfe, 0x92, 0xf6, 0x64},
|
||||
{0x06, 0x8d, 0xe6, 0x78, 0x1e, 0x67, 0xd1, 0x60},
|
||||
{0x00, 0x36, 0x7f, 0x49, 0x5f, 0x76, 0x70, 0x50},
|
||||
{0x00, 0x00, 0x00, 0x08, 0x0e, 0x06, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x3e, 0x7f, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x41, 0x7f, 0x3e, 0x00, 0x00},
|
||||
{0x00, 0x14, 0x1c, 0x3e, 0x3e, 0x1c, 0x14, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc0, 0xf0, 0x3c, 0x0f, 0x03, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x4d, 0x59, 0x7f, 0x3e, 0x00},
|
||||
{0x00, 0x42, 0x42, 0x7f, 0x7f, 0x40, 0x40, 0x00},
|
||||
{0x00, 0x42, 0x63, 0x71, 0x59, 0x4f, 0x46, 0x00},
|
||||
{0x00, 0x41, 0x49, 0x49, 0x49, 0x7f, 0x36, 0x00},
|
||||
{0x00, 0x18, 0x1c, 0x16, 0x7f, 0x7f, 0x10, 0x00},
|
||||
{0x00, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x49, 0x49, 0x7b, 0x32, 0x00},
|
||||
{0x00, 0x03, 0x63, 0x71, 0x19, 0x0f, 0x07, 0x00},
|
||||
{0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00},
|
||||
{0x00, 0x06, 0x4f, 0x49, 0x69, 0x3f, 0x1e, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x80, 0xe8, 0x68, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x08, 0x1c, 0x36, 0x22, 0x00, 0x00},
|
||||
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14},
|
||||
{0x00, 0x00, 0x00, 0x22, 0x36, 0x1c, 0x08, 0x00},
|
||||
{0x00, 0x02, 0x13, 0x59, 0x49, 0x0f, 0x06, 0x00},
|
||||
{0x3e, 0x7f, 0x55, 0x5d, 0x5d, 0x5f, 0x6e, 0x20},
|
||||
{0x00, 0x7e, 0x7f, 0x11, 0x11, 0x7f, 0x7e, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x41, 0x41, 0x63, 0x22, 0x00},
|
||||
{0x01, 0x7f, 0x7f, 0x41, 0x41, 0x7f, 0x3e, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x09, 0x09, 0x09, 0x01, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x41, 0x49, 0x79, 0x79, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x08, 0x08, 0x7f, 0x7f, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x41, 0x7f, 0x3f, 0x01, 0x00, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x0c, 0x3e, 0x73, 0x41, 0x00},
|
||||
{0x00, 0x00, 0x7f, 0x7f, 0x40, 0x40, 0x40, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x0c, 0x08, 0x0c, 0x7f, 0x7f},
|
||||
{0x00, 0x7f, 0x7f, 0x06, 0x0c, 0x7f, 0x7f, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x41, 0x41, 0x7f, 0x3e, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x09, 0x09, 0x0f, 0x06, 0x00},
|
||||
{0x00, 0x3e, 0x7f, 0x51, 0x61, 0x7f, 0x5e, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66, 0x00},
|
||||
{0x00, 0x26, 0x6f, 0x49, 0x49, 0x7b, 0x32, 0x00},
|
||||
{0x00, 0x01, 0x01, 0x7f, 0x7f, 0x01, 0x01, 0x00},
|
||||
{0x00, 0x3f, 0x7f, 0x40, 0x40, 0x7f, 0x3f, 0x00},
|
||||
{0x00, 0x0f, 0x3f, 0x70, 0x70, 0x3f, 0x0f, 0x00},
|
||||
{0x3f, 0x7f, 0x60, 0x3c, 0x3c, 0x60, 0x7f, 0x3f},
|
||||
{0x00, 0x63, 0x77, 0x1c, 0x1c, 0x77, 0x63, 0x00},
|
||||
{0x00, 0x07, 0x0f, 0x78, 0x78, 0x0f, 0x07, 0x00},
|
||||
{0x00, 0x61, 0x71, 0x59, 0x4d, 0x47, 0x43, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x7f, 0x7f, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x03, 0x0f, 0x3c, 0xf0, 0xc0, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x41, 0x7f, 0x7f, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x04, 0x06, 0x02, 0x06, 0x04, 0x00},
|
||||
{0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
|
||||
{0x00, 0x00, 0x00, 0x02, 0x0e, 0x0c, 0x00, 0x00},
|
||||
{0x00, 0x30, 0x7a, 0x4a, 0x4a, 0x7e, 0x7c, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x44, 0x44, 0x7c, 0x38, 0x00},
|
||||
{0x00, 0x3c, 0x7e, 0x42, 0x42, 0x46, 0x44, 0x00},
|
||||
{0x00, 0x38, 0x7c, 0x44, 0x44, 0x7f, 0x7f, 0x00},
|
||||
{0x00, 0x3c, 0x7e, 0x4a, 0x4a, 0x4e, 0x4c, 0x00},
|
||||
{0x00, 0x08, 0x7e, 0x7f, 0x09, 0x09, 0x01, 0x00},
|
||||
{0x00, 0x1c, 0xbe, 0xa2, 0xa2, 0xfe, 0x7e, 0x00},
|
||||
{0x00, 0x7f, 0x7f, 0x0c, 0x04, 0x7c, 0x78, 0x00},
|
||||
{0x00, 0x00, 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x82, 0xfe, 0x7e, 0x02, 0x00, 0x00},
|
||||
{0x00, 0x7e, 0x7e, 0x18, 0x3c, 0x66, 0x42, 0x00},
|
||||
{0x00, 0x00, 0x3e, 0x7e, 0x40, 0x40, 0x00, 0x00},
|
||||
{0x7c, 0x7e, 0x02, 0x7e, 0x7e, 0x02, 0x7e, 0x7c},
|
||||
{0x00, 0x7c, 0x7c, 0x06, 0x02, 0x7e, 0x7c, 0x00},
|
||||
{0x00, 0x3c, 0x7e, 0x42, 0x42, 0x7e, 0x3c, 0x00},
|
||||
{0x00, 0xfe, 0xfe, 0x22, 0x22, 0x3e, 0x1c, 0x00},
|
||||
{0x00, 0x1c, 0x3e, 0x22, 0x22, 0xfe, 0xfe, 0x00},
|
||||
{0x00, 0x00, 0x7c, 0x7e, 0x06, 0x02, 0x02, 0x00},
|
||||
{0x00, 0x24, 0x6e, 0x4a, 0x4a, 0x7a, 0x30, 0x00},
|
||||
{0x00, 0x00, 0x3f, 0x7f, 0x44, 0x44, 0x44, 0x00},
|
||||
{0x00, 0x3e, 0x7e, 0x40, 0x60, 0x7e, 0x7e, 0x00},
|
||||
{0x00, 0x0e, 0x3e, 0x70, 0x70, 0x3e, 0x0e, 0x00},
|
||||
{0x3c, 0x7c, 0x40, 0x7c, 0x7c, 0x40, 0x7e, 0x3e},
|
||||
{0x00, 0x42, 0x66, 0x3c, 0x3c, 0x66, 0x42, 0x00},
|
||||
{0x00, 0x00, 0x4e, 0x5e, 0x70, 0x3e, 0x0e, 0x00},
|
||||
{0x00, 0x00, 0x62, 0x72, 0x5a, 0x4e, 0x46, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x7e, 0xc3, 0x81, 0x42, 0x00},
|
||||
{0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x42, 0x81, 0xc3, 0x7e, 0x18, 0x00},
|
||||
{0x00, 0x10, 0x18, 0x08, 0x18, 0x10, 0x18, 0x08},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x28, 0x7c, 0xfe, 0xaa, 0xaa, 0x8a, 0xc6, 0x44},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x00, 0x00, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x48, 0x7c, 0x3e, 0x0a, 0x00, 0x00},
|
||||
{0x00, 0x80, 0xe0, 0x60, 0x80, 0xe0, 0x60, 0x00},
|
||||
{0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40},
|
||||
{0x00, 0x08, 0x04, 0x7e, 0x7e, 0x04, 0x08, 0x00},
|
||||
{0x00, 0x24, 0x42, 0xff, 0xff, 0x42, 0x24, 0x00},
|
||||
{0x00, 0x04, 0x06, 0x03, 0x03, 0x06, 0x04, 0x00},
|
||||
{0xc0, 0x66, 0x1d, 0x66, 0xd8, 0x66, 0xd3, 0x60},
|
||||
{0x00, 0x25, 0x6f, 0x4a, 0x4a, 0x7b, 0x31, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x18, 0x3c, 0x24, 0x00, 0x00},
|
||||
{0x3e, 0x7f, 0x41, 0x61, 0x7f, 0x7f, 0x49, 0x49},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x00, 0x61, 0x73, 0x5a, 0x4e, 0x47, 0x43, 0x00},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x00, 0x00, 0x00, 0x06, 0x0e, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x02, 0x0e, 0x0c, 0x00, 0x00},
|
||||
{0x00, 0x06, 0x0e, 0x08, 0x06, 0x0e, 0x08, 0x00},
|
||||
{0x00, 0x02, 0x0e, 0x0c, 0x02, 0x0e, 0x0c, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00},
|
||||
{0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00},
|
||||
{0x00, 0x04, 0x06, 0x02, 0x04, 0x06, 0x02, 0x00},
|
||||
{0x01, 0x0f, 0x0f, 0x01, 0x0e, 0x02, 0x0f, 0x0f},
|
||||
{0x00, 0x25, 0x6f, 0x4a, 0x4a, 0x7b, 0x31, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x24, 0x3c, 0x18, 0x00, 0x00},
|
||||
{0x3c, 0x7e, 0x42, 0x62, 0x7e, 0x7e, 0x52, 0x52},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x00, 0x01, 0x63, 0x72, 0x5a, 0x4e, 0x47, 0x01},
|
||||
{0x00, 0x05, 0x0d, 0x78, 0x78, 0x0d, 0x05, 0x00},
|
||||
{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
|
||||
{0x00, 0x00, 0x00, 0x7d, 0x7d, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x7c, 0x44, 0xfe, 0x44, 0x6c, 0x28},
|
||||
{0x00, 0x90, 0xfc, 0xfe, 0x92, 0x92, 0xc6, 0x44},
|
||||
{0x00, 0x42, 0x5a, 0x3c, 0x24, 0x3c, 0x5a, 0x42},
|
||||
{0x00, 0x52, 0x56, 0xfc, 0xfc, 0x56, 0x52, 0x00},
|
||||
{0x00, 0x00, 0x00, 0xf7, 0xf7, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x1a, 0xbf, 0xa5, 0xfd, 0x58, 0x00},
|
||||
{0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00},
|
||||
{0x3c, 0x7e, 0xdb, 0xa5, 0xa5, 0xd3, 0x7e, 0x3c},
|
||||
{0x00, 0x10, 0x16, 0x13, 0x13, 0x16, 0x10, 0x00},
|
||||
{0x00, 0x18, 0x3c, 0x24, 0x18, 0x3c, 0x24, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x38},
|
||||
{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00},
|
||||
{0x7e, 0xff, 0x81, 0xbd, 0x95, 0xa9, 0xff, 0x7e},
|
||||
{0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
||||
{0x00, 0x00, 0x0c, 0x1a, 0x1a, 0x0c, 0x00, 0x00},
|
||||
{0x00, 0x48, 0x48, 0x7e, 0x7e, 0x48, 0x48, 0x00},
|
||||
{0x00, 0x00, 0x19, 0x1d, 0x17, 0x12, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x11, 0x15, 0x1f, 0x0a, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00},
|
||||
{0x00, 0xfe, 0xfe, 0x20, 0x30, 0x3e, 0x7e, 0x40},
|
||||
{0x00, 0x06, 0x0f, 0xff, 0xff, 0x01, 0xff, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x12, 0x1f, 0x1f, 0x10, 0x00, 0x00},
|
||||
{0x00, 0x10, 0x17, 0x17, 0x15, 0x17, 0x17, 0x10},
|
||||
{0x00, 0x24, 0x3c, 0x18, 0x24, 0x3c, 0x18, 0x00},
|
||||
{0x09, 0xcf, 0x7f, 0x3c, 0x6e, 0x53, 0xf8, 0xf8},
|
||||
{0x89, 0xcf, 0x6f, 0x38, 0xdc, 0xee, 0xbb, 0x90},
|
||||
{0x91, 0xd5, 0x7f, 0x3a, 0x6c, 0x56, 0xfb, 0xf8},
|
||||
{0x00, 0x60, 0xf0, 0x92, 0x9a, 0xc8, 0x40, 0x00},
|
||||
{0x00, 0x01, 0x7b, 0x7e, 0x24, 0x24, 0x7c, 0x78},
|
||||
{0x00, 0x78, 0x7c, 0x24, 0x24, 0x7e, 0x7b, 0x01},
|
||||
{0x02, 0x7b, 0x7d, 0x25, 0x25, 0x7d, 0x7b, 0x02},
|
||||
{0x02, 0x7b, 0x7d, 0x25, 0x27, 0x7e, 0x7b, 0x01},
|
||||
{0x00, 0x79, 0x7d, 0x24, 0x24, 0x7d, 0x79, 0x00},
|
||||
{0x00, 0x78, 0x7e, 0x25, 0x25, 0x7e, 0x78, 0x00},
|
||||
{0x70, 0x7c, 0x0e, 0x0b, 0x7f, 0x7f, 0x49, 0x49},
|
||||
{0x00, 0x3e, 0x7f, 0x41, 0x41, 0xe3, 0xa2, 0x00},
|
||||
{0x00, 0x01, 0x7f, 0x7e, 0x54, 0x54, 0x54, 0x44},
|
||||
{0x7c, 0x7c, 0x54, 0x54, 0x54, 0x46, 0x03, 0x01},
|
||||
{0x02, 0x03, 0x7d, 0x7d, 0x55, 0x55, 0x03, 0x02},
|
||||
{0x00, 0x7d, 0x7d, 0x54, 0x54, 0x55, 0x45, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x7b, 0x7a, 0x40, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x40, 0x7a, 0x7b, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x43, 0x7d, 0x7d, 0x43, 0x02, 0x00},
|
||||
{0x00, 0x01, 0x41, 0x7c, 0x7c, 0x41, 0x01, 0x00},
|
||||
{0x00, 0x11, 0x7f, 0x7f, 0x51, 0x41, 0x7f, 0x3e},
|
||||
{0x02, 0x03, 0x7d, 0x7d, 0x1b, 0x72, 0x7b, 0x01},
|
||||
{0x00, 0x01, 0x3b, 0x7e, 0x44, 0x44, 0x7c, 0x38},
|
||||
{0x00, 0x38, 0x7c, 0x44, 0x44, 0x7e, 0x3b, 0x01},
|
||||
{0x02, 0x3b, 0x7d, 0x45, 0x45, 0x7d, 0x3b, 0x02},
|
||||
{0x02, 0x3b, 0x7d, 0x45, 0x47, 0x7e, 0x3b, 0x01},
|
||||
{0x00, 0x39, 0x7d, 0x44, 0x44, 0x7d, 0x39, 0x00},
|
||||
{0x00, 0x22, 0x36, 0x1c, 0x1c, 0x36, 0x22, 0x00},
|
||||
{0x00, 0x5e, 0x7f, 0x39, 0x5d, 0x46, 0x7f, 0x3d},
|
||||
{0x00, 0x01, 0x3f, 0x7e, 0x40, 0x40, 0x7c, 0x3c},
|
||||
{0x00, 0x3c, 0x7c, 0x40, 0x40, 0x7e, 0x3f, 0x01},
|
||||
{0x02, 0x3b, 0x79, 0x41, 0x41, 0x79, 0x3b, 0x02},
|
||||
{0x00, 0x3d, 0x7d, 0x40, 0x40, 0x7d, 0x3d, 0x00},
|
||||
{0x00, 0x0e, 0x1e, 0x70, 0x72, 0x1b, 0x09, 0x00},
|
||||
{0x00, 0x00, 0x7e, 0x7e, 0x24, 0x3c, 0x18, 0x00},
|
||||
{0x00, 0xfe, 0xff, 0x49, 0x4f, 0x7e, 0x38, 0x00},
|
||||
{0x00, 0x01, 0x7b, 0x7e, 0x24, 0x24, 0x7c, 0x78},
|
||||
{0x00, 0x78, 0x7c, 0x24, 0x24, 0x7e, 0x7b, 0x01},
|
||||
{0x02, 0x7b, 0x7d, 0x25, 0x25, 0x7d, 0x7b, 0x02},
|
||||
{0x02, 0x7b, 0x7d, 0x25, 0x27, 0x7e, 0x7b, 0x01},
|
||||
{0x00, 0x79, 0x7d, 0x24, 0x24, 0x7d, 0x79, 0x00},
|
||||
{0x00, 0x78, 0x7e, 0x25, 0x25, 0x7e, 0x78, 0x00},
|
||||
{0x60, 0x78, 0x1c, 0x16, 0x7e, 0x7e, 0x52, 0x52},
|
||||
{0x00, 0x3c, 0x7e, 0x42, 0x42, 0xe6, 0xa4, 0x00},
|
||||
{0x00, 0x01, 0x7f, 0x7e, 0x54, 0x54, 0x54, 0x44},
|
||||
{0x7c, 0x7c, 0x54, 0x54, 0x54, 0x46, 0x03, 0x01},
|
||||
{0x02, 0x03, 0x7d, 0x7d, 0x55, 0x55, 0x03, 0x02},
|
||||
{0x00, 0x7d, 0x7d, 0x54, 0x54, 0x55, 0x45, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x7b, 0x7a, 0x40, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x40, 0x7a, 0x7b, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x43, 0x7d, 0x7d, 0x43, 0x02, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x79, 0x79, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x7c, 0x44, 0x44, 0x7f, 0x3f, 0x04},
|
||||
{0x02, 0x03, 0x7d, 0x7d, 0x1b, 0x72, 0x7b, 0x01},
|
||||
{0x00, 0x01, 0x3b, 0x7e, 0x44, 0x44, 0x7c, 0x38},
|
||||
{0x00, 0x38, 0x7c, 0x44, 0x44, 0x7e, 0x3b, 0x01},
|
||||
{0x02, 0x3b, 0x7d, 0x45, 0x45, 0x7d, 0x3b, 0x02},
|
||||
{0x02, 0x3b, 0x7d, 0x45, 0x47, 0x7e, 0x3b, 0x01},
|
||||
{0x00, 0x39, 0x7d, 0x44, 0x44, 0x7d, 0x39, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x2a, 0x2a, 0x08, 0x08, 0x00},
|
||||
{0x00, 0x5c, 0x7e, 0x32, 0x5a, 0x4c, 0x7e, 0x3a},
|
||||
{0x00, 0x01, 0x3f, 0x7e, 0x40, 0x40, 0x7c, 0x3c},
|
||||
{0x00, 0x3c, 0x7c, 0x40, 0x40, 0x7e, 0x3f, 0x01},
|
||||
{0x02, 0x3b, 0x79, 0x41, 0x41, 0x79, 0x3b, 0x02},
|
||||
{0x00, 0x3d, 0x7d, 0x40, 0x40, 0x7d, 0x3d, 0x00},
|
||||
{0x00, 0x08, 0x18, 0x72, 0x73, 0x19, 0x08, 0x00},
|
||||
{0x00, 0x00, 0x7e, 0x7e, 0x24, 0x3c, 0x18, 0x00},
|
||||
{0x00, 0x0d, 0x1d, 0x70, 0x70, 0x1d, 0x0d, 0x00},
|
||||
};
|
||||
|
||||
uint8_t ssd1306_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] = {
|
||||
{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 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 ssd1306_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] = {
|
||||
{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] = {
|
||||
{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 ssd1306_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 ssd1306_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 ssd1306_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 ssd1306_gfx_cross[8] = {0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00};
|
||||
|
||||
uint8_t ssd1306_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},
|
||||
{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},
|
||||
{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},
|
||||
};
|
62
components/ssd1306/ssd1306-gfx.h
Normal file
62
components/ssd1306/ssd1306-gfx.h
Normal file
@ -0,0 +1,62 @@
|
||||
// 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 gfx elements: font, icons, elements
|
||||
*
|
||||
*/
|
||||
#ifndef _ssd1306_GFX_H_
|
||||
#define _ssd1306_GFX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t ssd1306_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 ssd1306_gfx_button[3][64];
|
||||
|
||||
uint8_t ssd1306_gfx_button_sel[3][64];
|
||||
|
||||
uint8_t ssd1306_gfx_clock[8];
|
||||
|
||||
uint8_t ssd1306_gfx_menu_head[112];
|
||||
|
||||
uint8_t ssd1306_gfx_sad[4][24];
|
||||
|
||||
uint8_t ssd1306_gfx_smile[4][24];
|
||||
|
||||
uint8_t ssd1306_gfx_question[4][24];
|
||||
|
||||
uint8_t ssd1306_gfx_wifi[8];
|
||||
|
||||
uint8_t ssd1306_gfx_wifi_low[8];
|
||||
|
||||
uint8_t ssd1306_gfx_wifi_lowest[8];
|
||||
|
||||
uint8_t ssd1306_gfx_arrow_down[8];
|
||||
|
||||
uint8_t ssd1306_gfx_arrow_left[8];
|
||||
|
||||
uint8_t ssd1306_gfx_arrow_right[8];
|
||||
|
||||
uint8_t ssd1306_gfx_arrow_up[8];
|
||||
|
||||
uint8_t ssd1306_gfx_cross[8];
|
||||
|
||||
uint8_t ssd1306_gfx_logo[8][64];
|
||||
|
||||
#endif
|
@ -17,10 +17,53 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "i2c-main.h"
|
||||
#include "ssd1306-ascii.h"
|
||||
#include "ssd1306-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)
|
||||
{
|
||||
if (!i2c_is_initialized())
|
||||
@ -163,22 +206,21 @@ void ssd1306_on(uint8_t i2address, bool on)
|
||||
// Turn the Display OFF
|
||||
i2c_master_write_byte(cmd, SSD1306_CMD_OFF, true);
|
||||
}
|
||||
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8_t offset, bool invert)
|
||||
void ssd1306_data(uint8_t i2address, uint8_t *data, size_t length, uint8_t line, uint8_t offset, bool invert)
|
||||
{
|
||||
|
||||
uint8_t font_width = sizeof(ascii_font_5x8[0]);
|
||||
uint8_t column = offset * font_width;
|
||||
uint8_t column = offset;
|
||||
if (column > SSD1306_COLUMNS)
|
||||
{
|
||||
column = 0;
|
||||
}
|
||||
size_t columns = strlen(text) * font_width;
|
||||
size_t columns = length;
|
||||
if (columns > (SSD1306_COLUMNS - column))
|
||||
{
|
||||
columns = (SSD1306_COLUMNS - column);
|
||||
@ -201,17 +243,11 @@ void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
uint8_t *linedata = calloc(columns, sizeof(uint8_t));
|
||||
for (uint8_t i = 0; i < (columns / font_width); i++)
|
||||
{
|
||||
memcpy(&linedata[i * font_width], ascii_font_5x8[(uint8_t)text[i]], font_width);
|
||||
}
|
||||
|
||||
if (invert)
|
||||
{
|
||||
for (uint8_t i = 0; i < columns; i++)
|
||||
{
|
||||
linedata[i] = ~linedata[i];
|
||||
data[i] = ~data[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,16 +256,154 @@ void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8
|
||||
i2c_master_write_byte(cmd, (i2address << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, SSD1306_CONTROL_DATA_STREAM, true);
|
||||
|
||||
i2c_master_write(cmd, linedata, columns, true);
|
||||
i2c_master_write(cmd, data, columns, true);
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
free(linedata);
|
||||
uint8_t *ssd1306_text_to_data(char *text, size_t text_length, size_t *length)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void ssd1306_chars(uint8_t i2address, char *text, size_t length, uint8_t line, uint8_t offset, 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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size_t start = 0;
|
||||
if (position > 13)
|
||||
{
|
||||
position = 13;
|
||||
start = position - 13;
|
||||
}
|
||||
uint8_t cur_char = (uint8_t)text[start + position] - 32;
|
||||
|
||||
// arrow
|
||||
ssd1306_data(i2address, ssd1306_gfx_arrow_left, 8, 2, 0, false);
|
||||
// bounday
|
||||
ssd1306_text_line_column(i2address, "______________", 2, 1, false);
|
||||
// arrow
|
||||
ssd1306_data(i2address, ssd1306_gfx_arrow_right, 8, 2, 15 * 8, false);
|
||||
// text
|
||||
size_t text_length = strlen(text);
|
||||
if (strlen(text) > 14)
|
||||
{
|
||||
text_length = 14;
|
||||
}
|
||||
size_t length = 0;
|
||||
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
|
||||
ssd1306_data(i2address, textdata, length, 2, 8, true);
|
||||
free(textdata);
|
||||
// arrow
|
||||
ssd1306_data(i2address, ssd1306_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);
|
||||
// sel char
|
||||
ssd1306_data(i2address, ssd1306_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);
|
||||
// arrow
|
||||
ssd1306_data(i2address, ssd1306_gfx_arrow_down, 8, 4, (position + 1) * 8, false);
|
||||
}
|
||||
|
||||
void ssd1306_set_button(uint8_t i2address, char *text, bool selected, bool primary)
|
||||
{
|
||||
uint8_t start = 0;
|
||||
if (primary)
|
||||
{
|
||||
start = 64;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
// text
|
||||
size_t text_length = strlen(text);
|
||||
if (strlen(text) > 6)
|
||||
{
|
||||
text_length = 6;
|
||||
}
|
||||
size_t length = 0;
|
||||
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
|
||||
|
||||
uint8_t offset = 0;
|
||||
if (text_length < 6)
|
||||
{
|
||||
offset = (6 - text_length) / 2 * 8;
|
||||
}
|
||||
|
||||
ssd1306_data(i2address, textdata, length, 6, start + 8 + offset, selected);
|
||||
free(textdata);
|
||||
}
|
||||
|
||||
void ssd1306_menu_headline(uint8_t i2address, 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);
|
||||
}
|
||||
// bounday
|
||||
ssd1306_data(i2address, ssd1306_gfx_menu_head, 112, line, 8, false);
|
||||
|
||||
// text
|
||||
size_t text_length = strlen(text);
|
||||
if (strlen(text) > 10)
|
||||
{
|
||||
text_length = 10;
|
||||
}
|
||||
size_t length = 0;
|
||||
uint8_t *textdata = ssd1306_text_to_data(text, text_length, &length);
|
||||
|
||||
uint8_t offset = 0;
|
||||
if (text_length < 10)
|
||||
{
|
||||
offset = (10 - text_length) / 2 * 8;
|
||||
}
|
||||
|
||||
ssd1306_data(i2address, textdata, length, line, 24 + offset, true);
|
||||
free(textdata);
|
||||
}
|
@ -20,6 +20,8 @@
|
||||
#ifndef _ssd1306_H_
|
||||
#define _ssd1306_H_
|
||||
|
||||
#include "esp_system.h"
|
||||
|
||||
#define SSD1306_ADDRESS (0x3C)
|
||||
#define SSD1306_COLUMNS (128)
|
||||
#define SSD1306_PAGES (8)
|
||||
@ -75,6 +77,8 @@
|
||||
// 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
|
||||
*
|
||||
@ -106,6 +110,11 @@ void ssd1306_clear(uint8_t i2address);
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -118,6 +127,18 @@ void ssd1306_on(uint8_t i2address, bool on);
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -139,4 +160,24 @@ void ssd1306_text_line_column(uint8_t i2address, char *text, uint8_t line, uint8
|
||||
*/
|
||||
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
|
8
components/wifi-controller/CMakeLists.txt
Normal file
8
components/wifi-controller/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"wifi-controller.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
esp_wifi
|
||||
nvs_flash
|
||||
)
|
185
components/wifi-controller/wifi-controller.c
Normal file
185
components/wifi-controller/wifi-controller.c
Normal file
@ -0,0 +1,185 @@
|
||||
// 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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "wifi-controller.h"
|
||||
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
static wifi_ap_record_t current_wifi_ap;
|
||||
|
||||
void wifi_controller_init(void)
|
||||
{
|
||||
// init NVS for WIFI
|
||||
esp_err_t ret;
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
|
||||
assert(sta_netif);
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void wifi_controller_scan(wifi_ap_record_t *ap_info, uint16_t *ap_count)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
wifi_controller_init();
|
||||
}
|
||||
|
||||
uint16_t number = 10;
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, true));
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(ap_count));
|
||||
ESP_ERROR_CHECK(esp_wifi_stop());
|
||||
}
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||
{
|
||||
esp_wifi_connect();
|
||||
}
|
||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||
{
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||
{
|
||||
ESP_LOGD(WIFI_LOG, "got IP");
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
heap_caps_check_integrity_all(true);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t wifi_controller_connect(wifi_config_t wifi_config)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
wifi_controller_init();
|
||||
}
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
vEventGroupDelete(s_wifi_event_group);
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT)
|
||||
{
|
||||
ESP_LOGV(WIFI_LOG, "connected to ap SSID:%s", wifi_config.sta.ssid);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (bits & WIFI_FAIL_BIT)
|
||||
{
|
||||
ESP_LOGI(WIFI_LOG, "Failed to connect to SSID:%s with PASSWORD:%s", wifi_config.sta.ssid, wifi_config.sta.password);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(WIFI_LOG, "UNEXPECTED EVENT");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t wifi_controller_reconnect(void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
wifi_controller_init();
|
||||
}
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
vEventGroupDelete(s_wifi_event_group);
|
||||
|
||||
if (bits & WIFI_CONNECTED_BIT)
|
||||
{
|
||||
ESP_LOGV(WIFI_LOG, "reconnected to last ap");
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (bits & WIFI_FAIL_BIT)
|
||||
{
|
||||
ESP_LOGI(WIFI_LOG, "Failed to reconnect to last ap");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(WIFI_LOG, "UNEXPECTED EVENT");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
wifi_ap_record_t *wifi_controller_connection(void)
|
||||
{
|
||||
if (esp_wifi_sta_get_ap_info(¤t_wifi_ap) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(WIFI_LOG, "Current AP: %s", current_wifi_ap.ssid);
|
||||
return ¤t_wifi_ap;
|
||||
}
|
||||
return NULL;
|
||||
}
|
56
components/wifi-controller/wifi-controller.h
Normal file
56
components/wifi-controller/wifi-controller.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2020 Lukas Haubaum
|
||||
//
|
||||
// Licensed under the GNU Affero General Public License, Version 3;
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _wifi_CONTROLLER_H_
|
||||
#define _wifi_CONTROLLER_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
#define WIFI_LOG "wifi-controller" // TAG for Logging
|
||||
|
||||
/**
|
||||
* @brief scan for WiFis
|
||||
*
|
||||
* @param[out] ap_info scanned APs
|
||||
* @param[out] ap_count number of scanned APs
|
||||
*/
|
||||
void wifi_controller_scan(wifi_ap_record_t ap_info[], uint16_t *ap_count);
|
||||
|
||||
/**
|
||||
* @brief connect to wifi ap
|
||||
*
|
||||
* @param[in] wifi_config config of wifi to connect
|
||||
*
|
||||
* @return
|
||||
* esp_err_t connection status
|
||||
*/
|
||||
esp_err_t wifi_controller_connect(wifi_config_t wifi_config);
|
||||
|
||||
/**
|
||||
* @brief reconnect to previous wifi
|
||||
*
|
||||
* @return
|
||||
* esp_err_t connection status
|
||||
*/
|
||||
esp_err_t wifi_controller_reconnect(void);
|
||||
|
||||
/**
|
||||
* @brief reconnect to previous wifi
|
||||
*
|
||||
* @return
|
||||
* wifi_ap_record_t pointer to current wifi connection, NULL if not connected
|
||||
*/
|
||||
wifi_ap_record_t *wifi_controller_connection(void);
|
||||
|
||||
#endif
|
@ -1,7 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
"display-interface.c"
|
||||
"wifi.c"
|
||||
INCLUDE_DIRS ""
|
||||
)
|
||||
|
@ -1,20 +0,0 @@
|
||||
menu "Wifi Setup"
|
||||
|
||||
config WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config WIFI_MAXIMUM_RETRY
|
||||
int "Maximum retry"
|
||||
default 5
|
||||
help
|
||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||
endmenu
|
@ -1,153 +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.
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "ds3231.h"
|
||||
#include "ena-exposure.h"
|
||||
#include "interface.h"
|
||||
#include "interface-menu.h"
|
||||
#include "interface-datetime.h"
|
||||
#include "ssd1306.h"
|
||||
|
||||
void interface_display_time(void *pvParameter)
|
||||
{
|
||||
static time_t curtime;
|
||||
static char *curtime_text;
|
||||
static struct tm rtc_time;
|
||||
static bool edit_invert = false;
|
||||
while (1)
|
||||
{
|
||||
curtime = time(NULL);
|
||||
localtime_r(&curtime, &rtc_time);
|
||||
curtime_text = asctime(&rtc_time);
|
||||
ssd1306_text_line(SSD1306_ADDRESS, curtime_text, 0, false);
|
||||
gmtime_r(&curtime, &rtc_time);
|
||||
curtime_text = asctime(&rtc_time);
|
||||
ssd1306_text_line(SSD1306_ADDRESS, curtime_text, 1, false);
|
||||
if (interface_get_state() == INTERFACE_STATE_SET_DATETIME)
|
||||
{
|
||||
edit_invert = !edit_invert;
|
||||
ds3231_set_time(&rtc_time);
|
||||
char edit_year[4] = "";
|
||||
char edit_month[3] = "";
|
||||
char edit_day[2] = "";
|
||||
char edit_hour[2] = "";
|
||||
char edit_minute[2] = "";
|
||||
char edit_second[2] = "";
|
||||
switch (interface_datetime_state())
|
||||
{
|
||||
|
||||
case INTERFACE_DATETIME_STATE_YEAR:
|
||||
memcpy(&edit_year, &curtime_text[20], 4);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_year, 0, 20, edit_invert);
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_MONTH:
|
||||
memcpy(&edit_month, &curtime_text[4], 3);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_month, 0, 4, edit_invert);
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_DAY:
|
||||
memcpy(&edit_day, &curtime_text[8], 2);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_day, 0, 8, edit_invert);
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_HOUR:
|
||||
memcpy(&edit_hour, &curtime_text[11], 2);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_hour, 0, 11, edit_invert);
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_MINUTE:
|
||||
memcpy(&edit_minute, &curtime_text[14], 2);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_minute, 0, 14, edit_invert);
|
||||
break;
|
||||
case INTERFACE_DATETIME_STATE_SECONDS:
|
||||
memcpy(&edit_second[0], &curtime_text[17], 2);
|
||||
ssd1306_text_line_column(SSD1306_ADDRESS, edit_second, 0, 17, edit_invert);
|
||||
break;
|
||||
}
|
||||
}
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_display_status(void *pvParameter)
|
||||
{
|
||||
static bool get_status = true;
|
||||
while (1)
|
||||
{
|
||||
if (interface_get_state() == INTERFACE_STATE_STATUS)
|
||||
{
|
||||
if (get_status)
|
||||
{
|
||||
ena_exposure_summary_t summary;
|
||||
ena_exposure_summary(ena_exposure_default_config(), &summary);
|
||||
char buffer[23];
|
||||
sprintf(buffer, "Days: %d", summary.days_since_last_exposure);
|
||||
ssd1306_text_line(SSD1306_ADDRESS, buffer, 3, false);
|
||||
sprintf(buffer, "Exposures: %d", summary.num_exposures);
|
||||
ssd1306_text_line(SSD1306_ADDRESS, buffer, 4, false);
|
||||
sprintf(buffer, "Score: %d, Max: %d", summary.risk_score_sum, summary.max_risk_score);
|
||||
ssd1306_text_line(SSD1306_ADDRESS, buffer, 5, false);
|
||||
get_status = false;
|
||||
}
|
||||
}
|
||||
else if (!get_status)
|
||||
{
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 3, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 4, false);
|
||||
ssd1306_clear_line(SSD1306_ADDRESS, 5, false);
|
||||
get_status = true;
|
||||
}
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void interface_display_idle(void *pvParameter)
|
||||
{
|
||||
static bool set_status = true;
|
||||
while (1)
|
||||
{
|
||||
if (interface_get_state() == INTERFACE_STATE_IDLE)
|
||||
{
|
||||
if (set_status)
|
||||
{
|
||||
ssd1306_on(SSD1306_ADDRESS, false);
|
||||
set_status = false;
|
||||
}
|
||||
}
|
||||
else if (!set_status)
|
||||
{
|
||||
ssd1306_on(SSD1306_ADDRESS, true);
|
||||
set_status = true;
|
||||
}
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void display_interface_start(void)
|
||||
{
|
||||
ssd1306_start(SSD1306_ADDRESS);
|
||||
ssd1306_clear(SSD1306_ADDRESS);
|
||||
|
||||
interface_start();
|
||||
interface_menu_start();
|
||||
|
||||
xTaskCreate(&interface_display_time, "interface_display_time", 4096, NULL, 5, NULL);
|
||||
xTaskCreate(&interface_display_status, "interface_display_status", 4096, NULL, 5, NULL);
|
||||
xTaskCreate(&interface_display_idle, "interface_display_idle", 4096, NULL, 5, NULL);
|
||||
}
|
@ -1,22 +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.
|
||||
#ifndef _display_interface_H_
|
||||
#define _display_interface_H_
|
||||
|
||||
/**
|
||||
* @brief start display + interface
|
||||
*/
|
||||
void display_interface_start(void);
|
||||
|
||||
#endif
|
16
main/main.c
16
main/main.c
@ -25,16 +25,17 @@
|
||||
#include "ena-exposure.h"
|
||||
#include "ena-bluetooth-advertise.h"
|
||||
#include "ena-bluetooth-scan.h"
|
||||
#include "interface.h"
|
||||
#include "ena-cwa.h"
|
||||
#include "interface.h"
|
||||
#include "ds3231.h"
|
||||
#include "display-interface.h"
|
||||
#include "wifi.h"
|
||||
#include "ssd1306.h"
|
||||
#include "wifi-controller.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
// debug only own LOG TAGs
|
||||
esp_log_level_set("*", ESP_LOG_WARN);
|
||||
esp_log_level_set(ENA_LOG, ESP_LOG_DEBUG);
|
||||
@ -47,6 +48,9 @@ void app_main(void)
|
||||
esp_log_level_set(INTERFACE_LOG, ESP_LOG_DEBUG);
|
||||
esp_log_level_set(WIFI_LOG, ESP_LOG_DEBUG);
|
||||
|
||||
// start interface
|
||||
interface_start();
|
||||
|
||||
// set system time from DS3231
|
||||
struct tm rtc_time;
|
||||
ds3231_get_time(&rtc_time);
|
||||
@ -62,11 +66,13 @@ void app_main(void)
|
||||
|
||||
ena_start();
|
||||
|
||||
display_interface_start();
|
||||
|
||||
// start with main interface
|
||||
interface_main_start();
|
||||
|
||||
while (1)
|
||||
{
|
||||
ena_run();
|
||||
ena_cwa_run();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
172
main/wifi.c
172
main/wifi.c
@ -1,172 +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.
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "ena-cwa.h"
|
||||
|
||||
#include "wifi.h"
|
||||
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static bool connected = false;
|
||||
|
||||
void wifi_stop(void)
|
||||
{
|
||||
connected = false;
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
esp_event_loop_delete_default();
|
||||
}
|
||||
|
||||
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
|
||||
{
|
||||
esp_wifi_connect();
|
||||
}
|
||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
|
||||
{
|
||||
if (s_retry_num < WIFI_MAXIMUM_RETRY)
|
||||
{
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGD(WIFI_LOG, "retry to connect to the AP");
|
||||
}
|
||||
else
|
||||
{
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
ESP_LOGD(WIFI_LOG, "connect to the AP fail");
|
||||
connected = false;
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
|
||||
{
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
connected = true;
|
||||
|
||||
heap_caps_check_integrity_all(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGD(WIFI_LOG, "eventbase %s, eventid %d", event_base, event_id);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_start(void)
|
||||
{
|
||||
|
||||
// init NVS for WIFI
|
||||
esp_err_t ret;
|
||||
ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
}
|
||||
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
||||
IP_EVENT_STA_GOT_IP,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_got_ip));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = WIFI_SSID,
|
||||
.password = WIFI_PASSWORD,
|
||||
/* Setting a password implies station will connect to all security modes including WEP/WPA.
|
||||
* However these modes are deprecated and not advisable to be used. Incase your Access point
|
||||
* doesn't support WPA2, these mode can be enabled by commenting below line */
|
||||
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||
|
||||
.pmf_cfg = {
|
||||
.capable = true,
|
||||
.required = false},
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||
pdFALSE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||
* happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT)
|
||||
{
|
||||
ESP_LOGV(WIFI_LOG, "connected to ap SSID:%s",
|
||||
WIFI_SSID);
|
||||
}
|
||||
else if (bits & WIFI_FAIL_BIT)
|
||||
{
|
||||
ESP_LOGI(WIFI_LOG, "Failed to connect to SSID:%s",
|
||||
WIFI_SSID);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(WIFI_LOG, "UNEXPECTED EVENT");
|
||||
}
|
||||
|
||||
/* The event will not be processed after unregister */
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
vEventGroupDelete(s_wifi_event_group);
|
||||
}
|
||||
|
||||
bool wifi_is_connected(void)
|
||||
{
|
||||
return connected;
|
||||
}
|
38
main/wifi.h
38
main/wifi.h
@ -1,38 +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.
|
||||
#ifndef _wifi_H_
|
||||
#define _wifi_H_
|
||||
|
||||
#define WIFI_LOG "ESP-ENA-wifi" // TAG for Logging
|
||||
|
||||
#define WIFI_SSID (CONFIG_WIFI_SSID)
|
||||
#define WIFI_PASSWORD (CONFIG_WIFI_PASSWORD)
|
||||
#define WIFI_MAXIMUM_RETRY (CONFIG_WIFI_MAXIMUM_RETRY)
|
||||
|
||||
/**
|
||||
* @brief start wifi connection to configured AP
|
||||
*/
|
||||
void wifi_start(void);
|
||||
|
||||
/**
|
||||
* @brief stop wifi (restart does not work for now!)
|
||||
*/
|
||||
void wifi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief check if a wifi is connected
|
||||
*/
|
||||
bool wifi_is_connected(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user