Add card acceptance animation
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,6 +2,6 @@ bin/
|
||||
obj/
|
||||
.cache
|
||||
.build
|
||||
.config.old
|
||||
build.log
|
||||
include
|
||||
.config.old
|
||||
|
||||
14
inc/idle.h
Normal file
14
inc/idle.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/**********************************************************
|
||||
* File: idle.h
|
||||
*
|
||||
* Description: Idle screen for standby
|
||||
*********************************************************/
|
||||
#ifndef IDLE_H_CGT5FQUY
|
||||
#define IDLE_H_CGT5FQUY
|
||||
|
||||
#include "lvgl/lvgl.h" // IWYU pragma: keep
|
||||
|
||||
void screen_idle_create(lv_obj_t *screen);
|
||||
void screen_idle_update();
|
||||
|
||||
#endif /* end of include guard: IDLE_H_CGT5FQUY */
|
||||
168
src/idle.c
Normal file
168
src/idle.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/**********************************************************
|
||||
* File: idle.c
|
||||
*
|
||||
* Description: Idle screen for standby
|
||||
*********************************************************/
|
||||
#include "lvgl/lvgl.h" // IWYU pragma: keep
|
||||
#include "lvgl/src/misc/lv_anim.h"
|
||||
#include "lvgl/src/widgets/label/lv_label.h"
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ARROW_DURATION 395
|
||||
#define CARDS_DURATION 4000
|
||||
#define CARDS_RATE 3.0
|
||||
#define CARDS_MID 0.5
|
||||
#define CARDS_DELAY 0.09
|
||||
#define WHITE lv_color_hex(0xffffff)
|
||||
|
||||
LV_FONT_DECLARE(montserrat_15);
|
||||
LV_FONT_DECLARE(dejavu_28);
|
||||
LV_FONT_DECLARE(dejavu_bold_10);
|
||||
LV_FONT_DECLARE(dejavu_cbold_52);
|
||||
LV_IMG_DECLARE(hop_arrow);
|
||||
LV_IMG_DECLARE(hop_logo);
|
||||
LV_IMG_DECLARE(hop_cards);
|
||||
|
||||
static lv_anim_t arrow_anim_template;
|
||||
static lv_anim_t *running_arrow_anim;
|
||||
|
||||
static lv_anim_t cards_anim_template;
|
||||
static lv_anim_t *running_cards_anim;
|
||||
|
||||
lv_obj_t *label_time;
|
||||
lv_obj_t *label_date;
|
||||
lv_obj_t *label_tap;
|
||||
lv_obj_t *label_sku;
|
||||
lv_obj_t *label_contactless;
|
||||
lv_obj_t *img_arrow;
|
||||
lv_obj_t *img_logo;
|
||||
lv_obj_t *img_cards;
|
||||
|
||||
time_t curr_time;
|
||||
struct tm *local_time;
|
||||
char buf[100];
|
||||
|
||||
double clamp(double d, double min, double max)
|
||||
{
|
||||
const double t = d < min ? min : d;
|
||||
return t > max ? max : t;
|
||||
}
|
||||
|
||||
void set_opa(void *var, int32_t value)
|
||||
{
|
||||
lv_obj_t *obj = (lv_obj_t *)var;
|
||||
lv_obj_set_style_image_opa(obj, value, 0);
|
||||
}
|
||||
|
||||
void cards_anim_cb(void *var, int32_t value)
|
||||
{
|
||||
double progress = (double)value / 0x7fff;
|
||||
double prompt_opa = progress - (CARDS_MID - CARDS_DELAY / 2);
|
||||
prompt_opa *= CARDS_RATE;
|
||||
prompt_opa = clamp(prompt_opa, 0.0, 1.0) * 255;
|
||||
double cards_opa = -progress + (CARDS_MID - CARDS_DELAY / 2);
|
||||
cards_opa *= CARDS_RATE;
|
||||
cards_opa = clamp(cards_opa, 0.0, 1.0) * 255;
|
||||
lv_obj_set_style_text_opa(label_tap, (int32_t)prompt_opa, 0);
|
||||
lv_obj_set_style_image_opa(img_cards, (int32_t)cards_opa, 0);
|
||||
lv_obj_set_style_text_opa(label_contactless, (int32_t)cards_opa, 0);
|
||||
}
|
||||
|
||||
void screen_idle_create(lv_obj_t *screen)
|
||||
{
|
||||
/*Change the active screen's background color*/
|
||||
lv_obj_set_style_bg_color(screen, lv_color_hex(0), LV_PART_MAIN);
|
||||
|
||||
// hop logo
|
||||
img_logo = lv_img_create(screen);
|
||||
lv_img_set_src(img_logo, &hop_logo);
|
||||
lv_obj_align(img_logo, LV_ALIGN_CENTER, 0, -98);
|
||||
|
||||
// flickering arrow
|
||||
img_arrow = lv_img_create(screen);
|
||||
lv_img_set_src(img_arrow, &hop_arrow);
|
||||
lv_obj_align(img_arrow, LV_ALIGN_CENTER, 0, 155);
|
||||
lv_obj_set_style_img_opa(img_arrow, 100, 0);
|
||||
|
||||
lv_anim_init(&arrow_anim_template);
|
||||
lv_anim_set_exec_cb(&arrow_anim_template, set_opa);
|
||||
lv_anim_set_values(&arrow_anim_template, 0, 255);
|
||||
lv_anim_set_duration(&arrow_anim_template, ARROW_DURATION);
|
||||
lv_anim_set_path_cb(&arrow_anim_template, lv_anim_path_ease_out);
|
||||
lv_anim_set_reverse_duration(&arrow_anim_template, ARROW_DURATION);
|
||||
lv_anim_set_repeat_count(&arrow_anim_template, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_var(&arrow_anim_template, img_arrow);
|
||||
|
||||
running_arrow_anim = lv_anim_start(&arrow_anim_template);
|
||||
|
||||
// tap prompt
|
||||
label_tap = lv_label_create(screen);
|
||||
lv_label_set_text(label_tap, "Tap card or phone below");
|
||||
lv_obj_set_style_text_font(label_tap, &dejavu_cbold_52, 0);
|
||||
lv_obj_set_style_text_color(label_tap, WHITE, 0);
|
||||
lv_obj_align(label_tap, LV_ALIGN_CENTER, 0, 83);
|
||||
|
||||
// card acceptance logos
|
||||
img_cards = lv_img_create(screen);
|
||||
lv_img_set_src(img_cards, &hop_cards);
|
||||
lv_obj_align(img_cards, LV_ALIGN_CENTER, 0, 75);
|
||||
|
||||
// contactless payments note
|
||||
label_contactless = lv_label_create(screen);
|
||||
lv_label_set_text(label_contactless, "Contactless payment only");
|
||||
lv_obj_set_style_text_font(label_contactless, &montserrat_15, 0);
|
||||
lv_obj_set_style_text_color(label_contactless, WHITE, 0);
|
||||
lv_obj_align(label_contactless, LV_ALIGN_CENTER, 0, 118);
|
||||
|
||||
// animation for tap prompt/card acceptance
|
||||
lv_anim_init(&cards_anim_template);
|
||||
lv_anim_set_exec_cb(&cards_anim_template, cards_anim_cb);
|
||||
lv_anim_set_values(&cards_anim_template, 0, 0x7fff);
|
||||
lv_anim_set_duration(&cards_anim_template, CARDS_DURATION);
|
||||
lv_anim_set_path_cb(&cards_anim_template, lv_anim_path_linear);
|
||||
lv_anim_set_reverse_duration(&cards_anim_template, CARDS_DURATION);
|
||||
lv_anim_set_repeat_count(&cards_anim_template, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_var(&cards_anim_template, label_contactless);
|
||||
running_cards_anim = lv_anim_start(&cards_anim_template);
|
||||
|
||||
// device number at bottom
|
||||
label_sku = lv_label_create(screen);
|
||||
lv_label_set_text(label_sku, "DEMO-DEV-LVGL");
|
||||
lv_obj_set_style_text_font(label_sku, &dejavu_bold_10, 0);
|
||||
lv_obj_set_style_text_color(label_sku, WHITE, 0);
|
||||
lv_obj_align(label_sku, LV_ALIGN_CENTER, 0, 233);
|
||||
|
||||
// date in bottom left
|
||||
label_date = lv_label_create(screen);
|
||||
lv_label_set_text(label_date, "01-01-99");
|
||||
lv_obj_set_style_text_font(label_date, &dejavu_28, 0);
|
||||
lv_obj_set_style_text_color(label_date, WHITE, 0);
|
||||
lv_obj_align(label_date, LV_ALIGN_CENTER, -275, 226);
|
||||
|
||||
// time in bottom right
|
||||
label_time = lv_label_create(screen);
|
||||
lv_label_set_text(label_time, "12:59 a.m.");
|
||||
lv_obj_set_style_text_font(label_time, &dejavu_28, 0);
|
||||
lv_obj_set_style_text_color(label_time, WHITE, 0);
|
||||
lv_obj_align(label_time, LV_ALIGN_CENTER, 275, 226);
|
||||
}
|
||||
|
||||
void screen_idle_update()
|
||||
{
|
||||
time(&curr_time);
|
||||
local_time = localtime(&curr_time);
|
||||
strftime(buf, 100, "%m-%d-%y", local_time);
|
||||
lv_label_set_text(label_date, buf);
|
||||
strftime(buf, 90, "%l:%M %P", local_time);
|
||||
int i = 0;
|
||||
while (buf[i])
|
||||
i++;
|
||||
if (i > 0) {
|
||||
buf[i - 1] = '.';
|
||||
buf[i] = 'm';
|
||||
buf[i + 1] = '.';
|
||||
buf[i + 2] = '\0';
|
||||
}
|
||||
lv_label_set_text(label_time, buf);
|
||||
}
|
||||
@@ -1,88 +1,12 @@
|
||||
#include "lvgl/lvgl.h" // IWYU pragma: keep
|
||||
#include "lvgl/src/misc/lv_anim.h"
|
||||
#include "lvgl/src/widgets/label/lv_label.h"
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ARROW_DELAY 395
|
||||
|
||||
LV_FONT_DECLARE(dejavu_28);
|
||||
LV_FONT_DECLARE(dejavu_bold_10);
|
||||
LV_FONT_DECLARE(dejavu_cbold_52);
|
||||
LV_IMG_DECLARE(hop_arrow);
|
||||
LV_IMG_DECLARE(hop_logo);
|
||||
|
||||
static lv_anim_t anim_template;
|
||||
static lv_anim_t *running_anim;
|
||||
#include "idle.h"
|
||||
|
||||
lv_display_t *display;
|
||||
lv_obj_t *label_time;
|
||||
lv_obj_t *label_date;
|
||||
|
||||
void set_opa(void *var, int32_t value)
|
||||
{
|
||||
lv_obj_t *obj = (lv_obj_t *)var;
|
||||
lv_obj_set_style_image_opa(obj, value, 0);
|
||||
}
|
||||
|
||||
void create_screen()
|
||||
{
|
||||
/*Change the active screen's background color*/
|
||||
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0),
|
||||
LV_PART_MAIN);
|
||||
|
||||
lv_obj_t *logo = lv_img_create(lv_screen_active());
|
||||
lv_img_set_src(logo, &hop_logo);
|
||||
lv_obj_align(logo, LV_ALIGN_CENTER, 0, -98);
|
||||
|
||||
lv_obj_t *arrow = lv_img_create(lv_screen_active());
|
||||
lv_img_set_src(arrow, &hop_arrow);
|
||||
lv_obj_align(arrow, LV_ALIGN_CENTER, 0, 155);
|
||||
lv_obj_set_style_img_opa(arrow, 100, 0);
|
||||
|
||||
lv_anim_init(&anim_template);
|
||||
lv_anim_set_exec_cb(&anim_template, set_opa);
|
||||
lv_anim_set_values(&anim_template, 0, 255);
|
||||
lv_anim_set_duration(&anim_template, ARROW_DELAY);
|
||||
lv_anim_set_path_cb(&anim_template, lv_anim_path_ease_out);
|
||||
lv_anim_set_reverse_duration(&anim_template, ARROW_DELAY);
|
||||
lv_anim_set_repeat_count(&anim_template, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_set_var(&anim_template, arrow);
|
||||
|
||||
running_anim = lv_anim_start(&anim_template);
|
||||
|
||||
lv_obj_t *label_tap = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label_tap, "Tap card or phone below");
|
||||
lv_obj_set_style_text_font(label_tap, &dejavu_cbold_52, 0);
|
||||
lv_obj_set_style_text_color(label_tap, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_align(label_tap, LV_ALIGN_CENTER, 0, 83);
|
||||
|
||||
lv_obj_t *label_sku = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label_sku, "DEMO-DEV-LVGL");
|
||||
lv_obj_set_style_text_font(label_sku, &dejavu_bold_10, 0);
|
||||
lv_obj_set_style_text_color(label_sku, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_align(label_sku, LV_ALIGN_CENTER, 0, 233);
|
||||
|
||||
label_date = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label_date, "01-01-99");
|
||||
lv_obj_set_style_text_font(label_date, &dejavu_28, 0);
|
||||
lv_obj_set_style_text_color(label_date, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_align(label_date, LV_ALIGN_CENTER, -275, 226);
|
||||
|
||||
label_time = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label_time, "12:59 a.m.");
|
||||
lv_obj_set_style_text_font(label_time, &dejavu_28, 0);
|
||||
lv_obj_set_style_text_color(label_time, lv_color_hex(0xffffff), 0);
|
||||
lv_obj_align(label_time, LV_ALIGN_CENTER, 275, 226);
|
||||
}
|
||||
uint32_t idle_time;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32_t idle_time;
|
||||
time_t curr_time;
|
||||
struct tm *local_time;
|
||||
char buf[100];
|
||||
|
||||
lv_init();
|
||||
#ifdef LV_TARGET_FB
|
||||
display = lv_linux_fbdev_create();
|
||||
@@ -91,26 +15,12 @@ int main(int argc, char *argv[])
|
||||
display = lv_x11_window_create("LVGL X11 Simulation", 800, 480);
|
||||
#endif
|
||||
|
||||
create_screen();
|
||||
screen_idle_create(lv_screen_active());
|
||||
|
||||
while (true) {
|
||||
/* Returns the time to the next timer execution */
|
||||
idle_time = lv_timer_handler();
|
||||
time(&curr_time);
|
||||
local_time = localtime(&curr_time);
|
||||
strftime(buf, 100, "%m-%d-%y", local_time);
|
||||
lv_label_set_text(label_date, buf);
|
||||
strftime(buf, 90, "%l:%M %P", local_time);
|
||||
int i = 0;
|
||||
while (buf[i])
|
||||
i++;
|
||||
if (i > 0) {
|
||||
buf[i - 1] = '.';
|
||||
buf[i] = 'm';
|
||||
buf[i + 1] = '.';
|
||||
buf[i + 2] = '\0';
|
||||
}
|
||||
lv_label_set_text(label_time, buf);
|
||||
screen_idle_update();
|
||||
usleep(idle_time * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
92
src/res/hop_cards.c
Normal file
92
src/res/hop_cards.c
Normal file
File diff suppressed because one or more lines are too long
1516
src/res/montserrat_15.c
Normal file
1516
src/res/montserrat_15.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user