summaryrefslogtreecommitdiff
path: root/fw
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2022-09-04 18:37:42 +0200
committerUros Majstorovic <majstor@majstor.org>2022-09-04 18:37:42 +0200
commitfc98d3809e0db36d634f290417b9152f87f83e3e (patch)
treed7c0cbb883571dccfcd4028d8b7b2a2144fc2d2b /fw
parent07e6abe5d5a1813298805bea2bf9d62ad895aaaa (diff)
new phone firmware
Diffstat (limited to 'fw')
-rw-r--r--fw/fe310/bsp/openocd_jlink.cfg19
-rw-r--r--fw/fe310/phone/Makefile32
-rw-r--r--fw/fe310/phone/app/Makefile15
-rw-r--r--fw/fe310/phone/app/app.c106
-rw-r--r--fw/fe310/phone/app/app.h27
-rw-r--r--fw/fe310/phone/app/log.h6
-rw-r--r--fw/fe310/phone/app/status.c68
-rw-r--r--fw/fe310/phone/app/status.h6
-rw-r--r--fw/fe310/phone/cell.c64
-rw-r--r--fw/fe310/phone/cell.h2
-rw-r--r--fw/fe310/phone/main.c94
-rw-r--r--fw/fe310/phone/mem.c24
-rw-r--r--fw/fe310/phone/modem.c197
-rw-r--r--fw/fe310/phone/modem.h2
-rw-r--r--fw/fe310/phone/phone.c215
-rw-r--r--fw/fe310/phone/phone.h9
-rw-r--r--fw/fe310/phone/test.c70
-rw-r--r--fw/fe310/phone/test.h2
-rw-r--r--fw/fe310/phone/timer.c47
-rw-r--r--fw/fe310/phone/timer.h2
-rw-r--r--fw/fe310/phone/wifi.c351
-rw-r--r--fw/fe310/phone/wifi.h15
22 files changed, 1373 insertions, 0 deletions
diff --git a/fw/fe310/bsp/openocd_jlink.cfg b/fw/fe310/bsp/openocd_jlink.cfg
new file mode 100644
index 0000000..238279c
--- /dev/null
+++ b/fw/fe310/bsp/openocd_jlink.cfg
@@ -0,0 +1,19 @@
+#write_config_file
+# JTAG adapter setup
+adapter_khz 120
+
+interface jlink
+
+set _CHIPNAME riscv
+jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000913
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
+$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
+
+flash bank spi0 fespi 0x20000000 0 0 0 $_TARGETNAME.0 0x10014000
+init
+halt
+
+# flash protect 0 64 last off
+echo "Ready for Remote Connections"
diff --git a/fw/fe310/phone/Makefile b/fw/fe310/phone/Makefile
new file mode 100644
index 0000000..8624962
--- /dev/null
+++ b/fw/fe310/phone/Makefile
@@ -0,0 +1,32 @@
+include ../common.mk
+DEPS = main.o mem.o wifi.o cell.o phone.o modem.o timer.o test.o
+
+lib_eos = eve eos eos-soc eos-dev eos-net eos-ext eos-bsp
+lib_ecp =
+
+CFLAGS += -I$(bsp_dir)/include -I$(bsp_dir)/drivers -I$(ext_dir)/crypto -I$(ext_dir)/fsfat -I$(ecp_dir)/src -I$(ecp_dir)/src/platform/fe310 -I..
+LDFLAGS = app/*.o $(CFLAGS) -L.. -L$(ecp_dir)/build-fe310 -Wl,--gc-sections -nostartfiles -nostdlib -Wl,--start-group -lc -lm -lgcc $(addprefix -l,$(lib_eos)) $(addprefix -l,$(lib_ecp)) -Wl,--end-group -T../bsp/default.lds
+TARGET = phone
+
+
+all: $(TARGET)
+
+app_:
+ (cd app && $(MAKE)) || exit;
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $<
+
+$(TARGET): app_ $(DEPS)
+ $(CC) $(DEPS) $(LDFLAGS) -o $@
+
+clean:
+ (cd app && $(MAKE) clean) || exit;
+ rm -f *.o *.a $(TARGET) $(TARGET).bin
+
+upload: $(TARGET)
+ ../bsp/upload --elf ./$(TARGET) --openocd $(RISCV_OPENOCD_HOME)/bin/openocd --gdb $(RISCV_HOME)/bin/riscv64-unknown-elf-gdb --openocd-config ../bsp/openocd_jlink.cfg
+
+upload_jlink: $(TARGET)
+ $(OBJCOPY) $(TARGET) -O binary $(TARGET).bin
+ ../bsp/upload --bin ./$(TARGET).bin --addr 0x20000000 --jlink JLinkExe
diff --git a/fw/fe310/phone/app/Makefile b/fw/fe310/phone/app/Makefile
new file mode 100644
index 0000000..8169de3
--- /dev/null
+++ b/fw/fe310/phone/app/Makefile
@@ -0,0 +1,15 @@
+include ../../common.mk
+
+obj = app.o status.o
+
+
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $<
+
+all: $(obj)
+
+clean:
+ rm -f *.o
diff --git a/fw/fe310/phone/app/app.c b/fw/fe310/phone/app/app.c
new file mode 100644
index 0000000..ae25545
--- /dev/null
+++ b/fw/fe310/phone/app/app.c
@@ -0,0 +1,106 @@
+#include <stdlib.h>
+
+#include <dev/net.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "status.h"
+#include "app.h"
+
+#define KBD_X 0
+#define KBD_Y 629
+#define KBD_W 480
+#define KBD_H 225
+
+static EVEKbd kbd;
+static EVEFont font;
+static EVEWindowRoot win_root;
+static EVEWindowKbd win_kbd;
+static EVEWindow win_status;
+static EVEWindow win_main;
+static EVEView view_status;
+static EVEViewStack view_stack;
+
+EVEWindowRoot *app_root(void) {
+ return &win_root;
+}
+
+EVEViewStack *app_stack(void){
+ return &view_stack;
+}
+
+EVEFont *app_font(void) {
+ return &font;
+}
+
+void app_refresh(void) {
+ eve_select();
+ eve_window_root_draw(app_root());
+ eve_deselect();
+}
+
+EVEView *app_search_view(char *name) {
+ EVEWindow *win = eve_window_search(&win_root.w, name);
+
+ if (win) return win->view;
+ return NULL;
+}
+
+eve_view_constructor_t app_current_view(void) {
+ return eve_stack_get(&view_stack);
+}
+
+void app_init(eve_view_constructor_t home_page, int b) {
+ EVERect g;
+
+ eve_select();
+
+ if (b >= 0) eve_brightness(b);
+
+ eve_font_init(&font, APP_FONT_HANDLE);
+
+ g.x = 0;
+ g.y = 0;
+ g.w = APP_SCREEN_W;
+ g.h = APP_SCREEN_H;
+ eve_window_init_root(&win_root, &g, "root", &font);
+
+ g.x = KBD_X;
+ g.y = KBD_Y;
+ g.w = KBD_W;
+ g.h = KBD_H;
+ eve_kbd_init(&kbd, &g, win_root.mem_next, &win_root.mem_next);
+ eve_window_init_kbd(&win_kbd, &g, &win_root, "kbd", &kbd);
+
+ g.x = 0;
+ g.y = 0;
+ g.w = APP_SCREEN_W;
+ g.h = APP_STATUS_H;
+ eve_window_init(&win_status, &g, (EVEWindow *)&win_root, "status");
+ app_status_init(&view_status, &win_status);
+
+ g.x = 0;
+ g.y = APP_STATUS_H;
+ g.w = APP_SCREEN_W;
+ g.h = APP_SCREEN_H - APP_STATUS_H;
+ eve_window_init(&win_main, &g, (EVEWindow *)&win_root, "main");
+
+ eve_stack_init(&view_stack);
+ eve_stack_create_view(&view_stack, &win_main, home_page);
+
+ eve_window_append(&win_status);
+ eve_window_append(&win_main);
+
+ eve_window_root_draw(&win_root);
+
+ eve_deselect();
+
+ eos_net_acquire_for_evt(EOS_EVT_EVE | EVE_ETYPE_INTR, 1);
+ // eos_net_acquire_for_evt(EOS_EVT_TIMER | EOS_TIMER_ETYPE_EVE, 1);
+}
diff --git a/fw/fe310/phone/app/app.h b/fw/fe310/phone/app/app.h
new file mode 100644
index 0000000..1ba2dca
--- /dev/null
+++ b/fw/fe310/phone/app/app.h
@@ -0,0 +1,27 @@
+#include <stdint.h>
+
+#include "log.h"
+
+#define APP_SCREEN_W 480
+#define APP_SCREEN_H 854
+#define APP_STATUS_H 60
+
+#define APP_FONT_HANDLE 31
+
+#define APP_SPEC_SIZE(spec) (sizeof(spec) / sizeof(EVEFormSpec))
+#define APP_SPACERW(__w__,__h__) { \
+ .widget.type = EVE_WIDGET_TYPE_SPACER, \
+ .widget.flags = EVE_WIDGET_FLAG_SKIP, \
+ .widget.g.w = (__w__), \
+ .widget.g.h = (__h__), \
+}
+
+
+EVEWindowRoot *app_root(void);
+EVEViewStack *app_stack(void);
+EVEFont *app_font(void);
+
+void app_refresh(void);
+EVEView *app_search_view(char *name);
+eve_view_constructor_t app_current_view(void);
+void app_init(eve_view_constructor_t home_page, int b);
diff --git a/fw/fe310/phone/app/log.h b/fw/fe310/phone/app/log.h
new file mode 100644
index 0000000..48ac5f0
--- /dev/null
+++ b/fw/fe310/phone/app/log.h
@@ -0,0 +1,6 @@
+#define APP_LOG_DEBUG 1
+#define APP_LOG_INFO 2
+#define APP_LOG_ERR 3
+
+#define APP_LOG_LEVEL APP_LOG_DEBUG
+#define APP_LOG(l, ...) (l >= APP_LOG_LEVEL ? fprintf(stderr, __VA_ARGS__) : 0 )
diff --git a/fw/fe310/phone/app/status.c b/fw/fe310/phone/app/status.c
new file mode 100644
index 0000000..fec391b
--- /dev/null
+++ b/fw/fe310/phone/app/status.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <dev/net.h>
+#include <net/cell.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app.h"
+#include "status.h"
+
+void app_status_init(EVEView *view, EVEWindow *win) {
+ eve_view_init(view, win, app_status_draw, app_status_touch, NULL, NULL);
+ eve_view_set_color_bg(view, 0x20, 0x20, 0x20);
+}
+
+int app_status_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ unsigned char state = 0;
+ int8_t touch_idx;
+
+ /* only first touch */
+ touch_idx = eve_touch_get_idx(touch);
+ if (touch_idx != 0) return 0;
+
+ evt = eve_touch_evt(touch, evt, tag0, view->tag, 2);
+ if (evt & EVE_TOUCH_ETYPE_POINT_UP) {
+ view->param = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+uint8_t app_status_draw(EVEView *view, uint8_t tag0) {
+ uint8_t tag_opt = EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY;
+ char *status_msg = view->param;
+
+ tag0 = eve_view_clear(view, tag0, tag_opt);
+
+ if (tag0 != EVE_NOTAG) {
+ eve_touch_set_opt(tag0, eve_touch_get_opt(tag0) | tag_opt);
+ eve_cmd_dl(TAG(tag0));
+ tag0++;
+ }
+
+ if (status_msg) eve_cmd(CMD_TEXT, "hhhhs", 0, 0, 31, 0, status_msg);
+
+ return tag0;
+}
+
+void app_status_set_msg(char *msg) {
+ EVEView *status;
+
+ status = app_search_view("status");
+ if (status == NULL) return;
+
+ status->param = msg;
+
+ if (!eve_selected()) app_refresh();
+}
diff --git a/fw/fe310/phone/app/status.h b/fw/fe310/phone/app/status.h
new file mode 100644
index 0000000..1350ae6
--- /dev/null
+++ b/fw/fe310/phone/app/status.h
@@ -0,0 +1,6 @@
+#include <stdint.h>
+
+void app_status_init(EVEView *view, EVEWindow *win);
+int app_status_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0);
+uint8_t app_status_draw(EVEView *view, uint8_t tag0);
+void app_status_set_msg(char *msg);
diff --git a/fw/fe310/phone/cell.c b/fw/fe310/phone/cell.c
new file mode 100644
index 0000000..47ce8e5
--- /dev/null
+++ b/fw/fe310/phone/cell.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <dev/net.h>
+#include <net/cell.h>
+
+#include "app/log.h"
+#include "cell.h"
+
+void cell_init(void) {
+ eos_cell_set_handler(EOS_CELL_MTYPE_DEV, cell_msg_handler);
+}
+
+void cell_msg_handler(unsigned char type, unsigned char *buffer, uint16_t len) {
+ switch (type) {
+ case EOS_CELL_MTYPE_STATUS: {
+ uint8_t status, connected;
+ int rv;
+
+ rv = eos_cell_status_parse(buffer, len, &status, &connected);
+ if (rv) {
+ APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv);
+ return;
+ }
+ APP_LOG(APP_LOG_DEBUG, "MODEM STATUS: ");
+ switch (status) {
+ case EOS_CELL_STATUS_RESET: {
+ APP_LOG(APP_LOG_DEBUG, "RESET\n");
+ break;
+ }
+
+ case EOS_CELL_STATUS_IDLE: {
+ APP_LOG(APP_LOG_DEBUG, "IDLE\n");
+ break;
+ }
+
+ case EOS_CELL_STATUS_RELAY: {
+ APP_LOG(APP_LOG_DEBUG, "RELAY\n");
+ break;
+ }
+
+ case EOS_CELL_STATUS_PPP: {
+ APP_LOG(APP_LOG_DEBUG, "PPP, ");
+ if (connected) {
+ APP_LOG(APP_LOG_DEBUG, "CONNECTED\n");
+ } else {
+ APP_LOG(APP_LOG_DEBUG, "NOT CONNECTED\n");
+ }
+ break;
+ }
+
+ default: {
+ APP_LOG(APP_LOG_DEBUG, "BAD STATUS\n");
+ break;
+ }
+ }
+ break;
+ }
+ }
+ eos_net_free(buffer, 0);
+}
diff --git a/fw/fe310/phone/cell.h b/fw/fe310/phone/cell.h
new file mode 100644
index 0000000..2d08d92
--- /dev/null
+++ b/fw/fe310/phone/cell.h
@@ -0,0 +1,2 @@
+void cell_init(void);
+void cell_msg_handler(unsigned char type, unsigned char *buffer, uint16_t len);
diff --git a/fw/fe310/phone/main.c b/fw/fe310/phone/main.c
new file mode 100644
index 0000000..125a9d2
--- /dev/null
+++ b/fw/fe310/phone/main.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <prci_driver.h>
+
+#include <eos.h>
+#include <dev/eve.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+
+#include "wifi.h"
+#include "cell.h"
+#include "phone.h"
+#include "modem.h"
+#include "timer.h"
+#include "test.h"
+
+static const uint32_t touch_matrix[6] = {0xf7ac,0x440,0x3e704,0xfffff718,0x108a3,0xfff76d42};
+
+static int home_page(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ {
+ .widget.type = EVE_WIDGET_TYPE_PAGE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.page.title = "WiFi",
+ .widget.tspec.page.constructor = wifi_app,
+ },
+ {
+ .widget.type = EVE_WIDGET_TYPE_PAGE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.page.title = "Modem",
+ .widget.tspec.page.constructor = modem_app,
+ },
+ {
+ .widget.type = EVE_WIDGET_TYPE_PAGE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.page.title = "Phone",
+ .widget.tspec.page.constructor = phone_app,
+ },
+ {
+ .widget.type = EVE_WIDGET_TYPE_PAGE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.page.title = "Timer",
+ .widget.tspec.page.constructor = timer_app,
+ },
+ {
+ .widget.type = EVE_WIDGET_TYPE_PAGE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.page.title = "Test",
+ .widget.tspec.page.constructor = test_app,
+ },
+ };
+
+ EVEPage *page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), NULL, NULL);
+ if (page == NULL) return EVE_ERR_NOMEM;
+
+ return EVE_OK;
+}
+
+void mem_print(void);
+
+#include <dev/gt911.h>
+
+int main() {
+ uint8_t wakeup_cause;
+
+ wakeup_cause = eos_init();
+ // eos_run_once();
+ eos_eve_set_tmatrix(touch_matrix);
+
+ printf("FREQ:%lu\n", PRCI_get_cpu_freq());
+ printf("\nREADY.\n");
+ mem_print();
+ eos_gt911_cfg_print();
+
+ wifi_init();
+ cell_init();
+ phone_init();
+ app_init(home_page, 0x20);
+
+ eos_run(wakeup_cause);
+
+ eos_evtq_loop();
+}
diff --git a/fw/fe310/phone/mem.c b/fw/fe310/phone/mem.c
new file mode 100644
index 0000000..90bc848
--- /dev/null
+++ b/fw/fe310/phone/mem.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+extern char metal_segment_itim_target_start;
+extern char metal_segment_itim_target_end;
+
+extern char metal_segment_data_target_start;
+extern char metal_segment_data_target_end;
+
+extern char metal_segment_bss_start;
+extern char metal_segment_bss_end;
+
+extern char metal_segment_heap_start;
+extern char metal_segment_heap_end;
+
+extern char metal_segment_stack_start;
+extern char metal_segment_stack_end;
+
+void mem_print(void) {
+ printf("ITIM: %p - %p\n", &metal_segment_itim_target_start, &metal_segment_itim_target_end);
+ printf("DATA: %p - %p\n", &metal_segment_data_target_start, &metal_segment_data_target_end);
+ printf("BSS: %p - %p\n", &metal_segment_bss_start, &metal_segment_bss_end);
+ printf("STACK: %p - %p\n", &metal_segment_stack_start, &metal_segment_stack_end);
+ printf("HEAP: %p - %p\n", &metal_segment_heap_start, &metal_segment_heap_end);
+}
diff --git a/fw/fe310/phone/modem.c b/fw/fe310/phone/modem.c
new file mode 100644
index 0000000..4c8d4e5
--- /dev/null
+++ b/fw/fe310/phone/modem.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <soc/uart.h>
+#include <dev/net.h>
+#include <net/cell.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_text.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+
+#include "cell.h"
+#include "modem.h"
+
+typedef struct {
+ uint32_t mem;
+ EVEText text;
+ EVEViewStack *stack;
+} VParam;
+
+static void key_down(void *p, int c) {
+ EVEView *view = p;
+ VParam *param = view->param;
+ EVEText *text= &param->text;
+ unsigned char *buf;
+ uint16_t offset;
+ int i;
+
+ if (c == 0x11) {
+ modem_close(view);
+ return;
+ }
+
+ buf = eos_cell_uart_data_buffer(&offset);
+ i = 1;
+ if (c == '\n') {
+ buf[0] = '\r';
+ buf[1] = '\n';
+ i++;
+ } else {
+ buf[0] = c;
+ }
+ eos_cell_send_buffer(buf, i, offset, 0);
+
+ eve_text_scroll0(text);
+}
+
+static void handle_uart(unsigned char type) {
+ int i, c;
+ unsigned char *buf;
+ uint16_t offset;
+
+ c = eos_uart_getc(0);
+ if (c == EOS_ERR_EMPTY) return;
+
+ if (c == 0x11) {
+ EVEView *view = app_search_view("main");
+
+ eve_select();
+ modem_close(view);
+ eve_touch_clear_opt();
+ eve_window_root_draw(view->window->root);
+ eve_deselect();
+ return;
+ }
+
+ buf = eos_cell_uart_data_buffer(&offset);
+ buf[0] = c;
+ i = 1;
+ while ((c = eos_uart_getc(0)) != EOS_ERR_EMPTY) {
+ buf[i++] = c;
+ if (i == EOS_NET_SIZE_BUF - offset) break;
+ }
+ eos_cell_send_buffer(buf, i, offset, 0);
+
+ eos_uart_rxwm_set(0);
+}
+
+static void handle_cell_msg(unsigned char type, unsigned char *buffer, uint16_t len) {
+ EVEView *view;
+ VParam *param;
+
+ view = app_search_view("main");
+ param = view->param;
+
+ if (type == EOS_CELL_MTYPE_UART_DATA) {
+ EVEText *text = &param->text;
+ int i;
+
+ eve_select();
+ for (i=1; i<len; i++) {
+ if (buffer[i] != '\r') {
+ eve_text_putc(text, buffer[i]);
+ putchar(buffer[i]);
+ }
+ }
+ if (text->dirty) {
+ text->dirty = 0;
+ eve_window_root_draw(view->window->root);
+ }
+ eve_deselect();
+ eos_net_free(buffer, 0);
+ } else {
+ cell_msg_handler(type, buffer, len);
+ }
+}
+
+static uint8_t modem_draw(EVEView *view, uint8_t tag0) {
+ VParam *param = view->param;
+ EVEText *text = &param->text;
+
+ tag0 = eve_view_clear(view, tag0, 0);
+ return eve_text_draw(text, tag0);
+}
+
+static int modem_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ VParam *param = view->param;
+ EVEText *text = &param->text;
+
+ return eve_text_touch(text, touch, evt, tag0);
+}
+
+int modem_app(EVEWindow *window, EVEViewStack *stack) {
+ unsigned char *buf;
+ EVEWindowRoot *root = window->root;
+ EVEKbd *kbd = eve_window_kbd(window);
+ EVERect g = {0, 60, 480, 512};
+ EVEView *view;
+ VParam *param;
+ int rv;
+
+ view = eve_malloc(sizeof(EVEView));
+ if (view == NULL) {
+ rv = EVE_ERR_NOMEM;
+ APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n");
+ return rv;
+ }
+ param = eve_malloc(sizeof(VParam));
+ if (param == NULL) {
+ rv = EVE_ERR_NOMEM;
+ eve_free(view);
+ APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n");
+ return rv;
+ }
+ param->mem = root->mem_next;
+ param->stack = stack;
+ eve_text_init(&param->text, &g, 30, 16, 200, root->mem_next, &root->mem_next);
+ eve_view_init(view, window, modem_draw, modem_touch, NULL, param);
+
+ eve_kbd_set_handler(kbd, key_down, view);
+ eve_window_kbd_attach(window);
+
+ eos_uart_flush_rx();
+
+ eos_uart_set_handler(EOS_UART_ETYPE_RX, handle_uart);
+ eos_net_acquire_for_evt(EOS_EVT_UART | EOS_UART_ETYPE_RX, 1);
+ eos_uart_rxwm_set(0);
+
+ eos_cell_set_handler(EOS_CELL_MTYPE_DEV, handle_cell_msg);
+ eos_cell_uart_take(NULL, 0);
+
+ return EVE_OK;
+}
+
+void modem_close(EVEView *view) {
+ VParam *param = view->param;
+ EVEWindow *window = view->window;
+ EVEWindowRoot *root = window->root;
+ EVEKbd *kbd = eve_window_kbd(window);
+ EVEViewStack *stack = param->stack;
+
+ eos_cell_uart_give(NULL, 0);
+
+ eos_uart_rxwm_clear();
+ eos_uart_set_handler(EOS_UART_ETYPE_RX, NULL);
+ eos_net_acquire_for_evt(EOS_EVT_UART | EOS_UART_ETYPE_RX, 0);
+
+ eos_cell_set_handler(EOS_CELL_MTYPE_DEV, cell_msg_handler);
+
+ root->mem_next = param->mem;
+ eve_window_kbd_detach(window);
+ eve_kbd_set_handler(kbd, NULL, NULL);
+
+ eve_free(param);
+ eve_free(view);
+ eve_stack_back(stack, window);
+}
diff --git a/fw/fe310/phone/modem.h b/fw/fe310/phone/modem.h
new file mode 100644
index 0000000..1c95d4e
--- /dev/null
+++ b/fw/fe310/phone/modem.h
@@ -0,0 +1,2 @@
+int modem_app(EVEWindow *window, EVEViewStack *stack);
+void modem_close(EVEView *view);
diff --git a/fw/fe310/phone/phone.c b/fw/fe310/phone/phone.c
new file mode 100644
index 0000000..53d36ae
--- /dev/null
+++ b/fw/fe310/phone/phone.c
@@ -0,0 +1,215 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <soc/i2s.h>
+#include <dev/net.h>
+#include <net/cell.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+#include "app/status.h"
+
+#include "phone.h"
+
+#define ABUF_SIZE 256
+#define MIC_WM 128
+
+static uint8_t mic_arr[ABUF_SIZE];
+static uint8_t spk_arr[ABUF_SIZE];
+
+static unsigned char phone_state = 0;
+
+__attribute__ ((section (".itim")))
+static void handle_mic(unsigned char type) {
+ uint16_t offset, size;
+ unsigned char *buf;
+
+ buf = eos_cell_voice_pcm_buffer(&offset);
+ size = eos_i2s_mic_read(buf, MIC_WM);
+ eos_cell_send_buffer(buf, size, offset, 0);
+}
+
+__attribute__ ((section (".itim")))
+static void handle_cell_voice(unsigned char type, unsigned char *buffer, uint16_t len) {
+ switch (type) {
+ case EOS_CELL_MTYPE_VOICE_RING: {
+ app_status_set_msg("RING");
+ APP_LOG(APP_LOG_DEBUG, "RING:%s\n", buffer+1);
+ phone_state = PHONE_STATE_RING;
+ break;
+ }
+
+ case EOS_CELL_MTYPE_VOICE_MISS: {
+ app_status_set_msg("MISS");
+ APP_LOG(APP_LOG_DEBUG, "MISS\n");
+ phone_state = PHONE_STATE_IDLE;
+ break;
+ }
+
+ case EOS_CELL_MTYPE_VOICE_BEGIN: {
+ app_status_set_msg("CALL BEGIN");
+ APP_LOG(APP_LOG_DEBUG, "CALL BEGIN\n");
+ phone_state = PHONE_STATE_CIP;
+ eos_net_acquire_for_evt(EOS_EVT_I2S | EOS_I2S_ETYPE_MIC, 1);
+ eos_i2s_spk_init(spk_arr, ABUF_SIZE);
+ eos_i2s_mic_init(mic_arr, ABUF_SIZE);
+ eos_i2s_mic_set_wm(MIC_WM);
+ eos_i2s_mic_set_handler(handle_mic);
+ eos_i2s_mic_set_vol(4);
+ eos_i2s_start(8000);
+ break;
+ }
+
+ case EOS_CELL_MTYPE_VOICE_END: {
+ app_status_set_msg("HUP");
+ APP_LOG(APP_LOG_DEBUG, "HUP\n");
+ phone_state = PHONE_STATE_IDLE;
+ eos_net_acquire_for_evt(EOS_EVT_I2S | EOS_I2S_ETYPE_MIC, 0);
+ eos_i2s_stop();
+ break;
+ }
+
+ case EOS_CELL_MTYPE_VOICE_PCM: {
+ if (phone_state == PHONE_STATE_CIP) {
+ eos_i2s_spk_write(buffer+1, len-1);
+ }
+ break;
+ }
+ }
+ eos_net_free(buffer, 0);
+}
+
+static void widget_btn_draw(EVEFreeWidget *widget) {
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+ uint8_t tag_up, tag_dn;
+
+ eve_cmd_dl(BEGIN(EVE_POINTS));
+ eve_cmd_dl(POINT_SIZE((_widget->g.h / 2) * 16));
+
+ tag_up = eve_freew_tag(widget);
+ eve_cmd_dl(COLOR_RGB(0x0, 0x255, 0x0));
+ eve_cmd_dl(VERTEX2F(APP_SCREEN_W / 3, _widget->g.y + _widget->g.h / 2));
+
+ tag_dn = eve_freew_tag(widget);
+ eve_cmd_dl(COLOR_RGB(0x255, 0x0, 0x0));
+ eve_cmd_dl(VERTEX2F(APP_SCREEN_W - APP_SCREEN_W / 3, _widget->g.y + _widget->g.h / 2));
+
+ eve_cmd_dl(COLOR_RGBC(page->v.color_fg));
+ eve_cmd_dl(END());
+}
+
+static int widget_btn_touch(EVEFreeWidget *widget, EVETouch *touch, uint16_t evt) {
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ uint8_t tagi;
+ int rv;
+
+ tagi = eve_widget_tag_index(widget, touch->tag_up);
+ if (tagi == 0) {
+ switch (phone_state) {
+ case PHONE_STATE_RING: {
+ app_status_set_msg("ANSWER");
+ rv = eos_cell_voice_answer(NULL, 0);
+ if (rv) APP_LOG(APP_LOG_ERR, "ANSWER ERR:%d\n", rv);
+ break;
+ }
+
+ case PHONE_STATE_IDLE: {
+ EVEPage *page = widget->w.page;
+ EVEStrWidget *strw = (EVEStrWidget *)eve_page_widget(page, 0);
+ char *num = strw->str;
+
+ if (strlen(num)) {
+ app_status_set_msg("DIAL");
+ rv = eos_cell_voice_dial(num, NULL, 0);
+ if (rv) APP_LOG(APP_LOG_ERR, "DIAL ERR:%d\n", rv);
+ }
+ break;
+ }
+ }
+ } else if (tagi == 1) {
+ rv = eos_cell_voice_hangup(NULL, 0);
+ if (rv) APP_LOG(APP_LOG_ERR, "HANGUP ERR:%d\n", rv);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+int phone_app(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ {
+ .label.title = "Phone:",
+
+ .widget.type = EVE_WIDGET_TYPE_STR,
+ .widget.tspec.str.str_size = EOS_CELL_MAX_DIAL_STR,
+ },
+ APP_SPACERW(APP_SCREEN_W, 50),
+ {
+ .widget.type = EVE_WIDGET_TYPE_FREE,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.g.h = 100,
+ .widget.tspec.free.draw = widget_btn_draw,
+ .widget.tspec.free.touch = widget_btn_touch,
+ },
+ };
+
+ EVEPage *page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), NULL, phone_close);
+ if (page == NULL) return EVE_ERR_NOMEM;
+
+ return EVE_OK;
+}
+
+int phone_uievt(EVEPage *page, uint16_t evt, void *param) {
+ int ret = 0;
+
+ switch (evt) {
+ case EVE_UIEVT_WIDGET_FOCUS_OUT: {
+ if (param == eve_page_widget(page, 0)) {
+ EVEStrWidget *strw = param;
+ int rv;
+
+ rv = eos_cell_voice_dial((char *)strw->str, NULL, 0);
+ if (rv) {
+ APP_LOG(APP_LOG_ERR, "DIAL ERR:%d\n", rv);
+ return ret;
+ }
+ app_status_set_msg("DIAL");
+ APP_LOG(APP_LOG_DEBUG, "DIAL:%s\n", strw->str);
+ eos_cell_voice_dial(strw->str, NULL, 0);
+ phone_state = PHONE_STATE_DIAL;
+ }
+ break;
+ }
+
+ default: {
+ ret = eve_form_uievt(page, evt, param);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void phone_close(EVEPage *page) {
+ eve_form_destroy(page);
+}
+
+void phone_init(void) {
+ eos_cell_set_handler(EOS_CELL_MTYPE_VOICE, handle_cell_voice);
+}
+
+unsigned char app_phone_state_get(void) {
+ return phone_state;
+}
diff --git a/fw/fe310/phone/phone.h b/fw/fe310/phone/phone.h
new file mode 100644
index 0000000..c7f8a82
--- /dev/null
+++ b/fw/fe310/phone/phone.h
@@ -0,0 +1,9 @@
+#define PHONE_STATE_IDLE 0
+#define PHONE_STATE_DIAL 1
+#define PHONE_STATE_RING 2
+#define PHONE_STATE_CIP 3
+
+int phone_app(EVEWindow *window, EVEViewStack *stack);
+int phone_uievt(EVEPage *page, uint16_t evt, void *param);
+void phone_close(EVEPage *page);
+void phone_init(void); \ No newline at end of file
diff --git a/fw/fe310/phone/test.c b/fw/fe310/phone/test.c
new file mode 100644
index 0000000..df3871e
--- /dev/null
+++ b/fw/fe310/phone/test.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+
+#include <soc/i2c.h>
+#include <dev/bq25895.h>
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+#include "app/status.h"
+
+#include "test.h"
+
+static int reg_read(uint8_t reg, uint8_t *data) {
+ return eos_i2c_read8(BQ25895_ADDR, reg, data, 1);
+}
+
+static int reg_write(uint8_t reg, uint8_t data) {
+ return eos_i2c_write8(BQ25895_ADDR, reg, &data, 1);
+}
+
+int test_uievt(EVEPage *page, uint16_t evt, void *param) {
+ int ret = 0;
+
+ switch (evt) {
+ case EVE_UIEVT_GEST_TOUCH: {
+ uint8_t data = 0;
+ int rv, i;
+
+ printf("PAGE TOUCH\n");
+ printf("BQ25895:\n");
+ for (i=0; i<0x15; i++) {
+ rv = reg_read(i, &data);
+ if (!rv) printf("REG%02x: %02x\n", i, data);
+ }
+ break;
+ }
+
+ default: {
+ ret = eve_form_uievt(page, evt, param);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int test_app(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ APP_SPACERW(1,1),
+ };
+ EVEPage *page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), test_uievt, test_close);
+ if (page == NULL) return EVE_ERR_NOMEM;
+ app_status_set_msg("TEST!");
+
+ return EVE_OK;
+}
+
+void test_close(EVEPage *page) {
+ eve_form_destroy(page);
+}
diff --git a/fw/fe310/phone/test.h b/fw/fe310/phone/test.h
new file mode 100644
index 0000000..66b380d
--- /dev/null
+++ b/fw/fe310/phone/test.h
@@ -0,0 +1,2 @@
+int test_app(EVEWindow *window, EVEViewStack *stack);
+void test_close(EVEPage *page); \ No newline at end of file
diff --git a/fw/fe310/phone/timer.c b/fw/fe310/phone/timer.c
new file mode 100644
index 0000000..03593ff
--- /dev/null
+++ b/fw/fe310/phone/timer.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <soc/timer.h>
+#include <dev/net.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+
+#include "timer.h"
+
+static void timer(unsigned char evt) {
+ int rv;
+
+ printf("TIMER\n");
+ eos_timer_set(EOS_TIMER_ETYPE_USR, 500);
+}
+
+int timer_app(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ APP_SPACERW(1,1),
+ };
+ EVEPage *page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), NULL, timer_close);
+ if (page == NULL) return EVE_ERR_NOMEM;
+ eos_timer_set_handler(EOS_TIMER_ETYPE_USR, timer);
+ eos_timer_set(EOS_TIMER_ETYPE_USR, 500);
+ eos_net_acquire_for_evt(EOS_EVT_TIMER | EOS_TIMER_ETYPE_USR, 1);
+
+ return EVE_OK;
+}
+
+void timer_close(EVEPage *page) {
+ eos_timer_clear(EOS_TIMER_ETYPE_USR);
+ eos_timer_set_handler(EOS_TIMER_ETYPE_USR, NULL);
+ eos_net_acquire_for_evt(EOS_EVT_TIMER | EOS_TIMER_ETYPE_USR, 0);
+ eve_form_destroy(page);
+}
diff --git a/fw/fe310/phone/timer.h b/fw/fe310/phone/timer.h
new file mode 100644
index 0000000..bac0b20
--- /dev/null
+++ b/fw/fe310/phone/timer.h
@@ -0,0 +1,2 @@
+int timer_app(EVEWindow *window, EVEViewStack *stack);
+void timer_close(EVEPage *page); \ No newline at end of file
diff --git a/fw/fe310/phone/wifi.c b/fw/fe310/phone/wifi.c
new file mode 100644
index 0000000..cb8a816
--- /dev/null
+++ b/fw/fe310/phone/wifi.c
@@ -0,0 +1,351 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <eos.h>
+#include <dev/net.h>
+
+#include <eve/eve.h>
+#include <eve/eve_kbd.h>
+#include <eve/eve_font.h>
+
+#include <eve/screen/window.h>
+#include <eve/screen/page.h>
+#include <eve/screen/form.h>
+
+#include "app/app.h"
+#include "app/status.h"
+
+#include "wifi.h"
+
+#define WIFI_ACTION_NONE -1
+#define WIFI_ACTION_IDLE 0
+#define WIFI_ACTION_START 1
+#define WIFI_ACTION_STOP 2
+#define WIFI_ACTION_SCAN 3
+#define WIFI_ACTION_CONNECT 4
+#define WIFI_ACTION_DISCONNECT 5
+
+static void handle_status(unsigned char type, unsigned char *buffer, uint16_t size) {
+ EVEPage *page;
+ WIFIStatus *status;
+ int action;
+ int rv;
+
+ if (app_current_view() != wifi_app) goto handle_status_fin;
+
+ page = (EVEPage *)app_search_view("main");
+ status = page->v.param;
+
+ rv = eos_wifi_status_parse(buffer, size, &status->status, status->ip_addr, status->ssid);
+ if (rv) {
+ APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv);
+ goto handle_status_fin;
+ }
+
+ action = WIFI_ACTION_NONE;
+ switch (status->action) {
+ case WIFI_ACTION_IDLE: {
+ break;
+ }
+ case WIFI_ACTION_START: {
+ if (status->status == EOS_WIFI_STATUS_DISCONNECTED) {
+ action = WIFI_ACTION_SCAN;
+ }
+ break;
+ }
+ case WIFI_ACTION_STOP: {
+ if (status->status == EOS_WIFI_STATUS_OFF) {
+ action = WIFI_ACTION_IDLE;
+ }
+ break;
+ }
+ case WIFI_ACTION_CONNECT: {
+ if (status->status == EOS_WIFI_STATUS_CONNECTED) {
+ action = WIFI_ACTION_IDLE;
+ } else {
+ app_status_set_msg("CONNECT FAILED");
+ action = WIFI_ACTION_SCAN;
+ }
+ break;
+ }
+ case WIFI_ACTION_DISCONNECT: {
+ if (status->status == EOS_WIFI_STATUS_DISCONNECTED) {
+ action = WIFI_ACTION_SCAN;
+ }
+ break;
+ }
+ case WIFI_ACTION_SCAN: {
+ /* ignore status updates during scan */
+ goto handle_status_fin;
+ }
+ }
+
+ if (action == WIFI_ACTION_SCAN) {
+ rv = eos_wifi_scan(buffer, 0);
+ if (rv) {
+ APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv);
+ goto handle_status_fin;
+ }
+ buffer = NULL;
+ }
+ wifi_update_status(page, action);
+ app_refresh();
+
+handle_status_fin:
+ if (buffer) eos_net_free(buffer, 0);
+}
+
+static void handle_scan(unsigned char type, unsigned char *buffer, uint16_t size) {
+ EVEPage *page;
+ EVESelectWidget *selw;
+
+ if (app_current_view() != wifi_app) goto handle_scan_fin;
+
+ page = (EVEPage *)app_search_view("main");
+ wifi_update_scanr(page, buffer + 1, size - 1);
+ app_refresh();
+
+handle_scan_fin:
+ eos_net_free(buffer, 0);
+}
+
+static void widget_ssid_draw(EVEFreeWidget *widget) {
+ EVEWidget *_widget = &widget->w;
+ WIFIStatus *status = _widget->page->v.param;
+
+ if (_widget->flags & EVE_WIDGET_FLAG_BUSY) {
+ eve_freew_tag(widget);
+ eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, "BUSY!");
+ } else if (status->status >= EOS_WIFI_STATUS_CONNECTED) {
+ char text[51];
+
+ if (status->status == EOS_WIFI_STATUS_CONNECTED) {
+ strcpy(text, status->ssid);
+ } else {
+ sprintf(text, "%s (%d.%d.%d.%d)", status->ssid, status->ip_addr[0], status->ip_addr[1], status->ip_addr[2], status->ip_addr[3]);
+ }
+
+ eve_freew_tag(widget);
+ eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, app_font()->id, 0, text);
+ }
+}
+
+static int widget_ssid_touch(EVEFreeWidget *widget, EVETouch *touch, uint16_t evt) {
+ if (evt & EVE_TOUCH_ETYPE_POINT_UP) {
+ EVEPage *page = widget->w.page;
+ int rv;
+
+ rv = eos_wifi_disconnect(NULL, 0);
+ if (!rv) wifi_update_status(page, WIFI_ACTION_DISCONNECT);
+ return 1;
+ }
+ return 0;
+}
+
+static int widget_enable_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVEToggleWidget *widget = (EVEToggleWidget *)_widget;
+ EVEPage *page = _widget->page;
+ WIFIStatus *status = page->v.param;
+
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ int rv;
+
+ if (widget->state) {
+ rv = eos_wifi_stop(NULL, 0);
+ if (!rv) wifi_update_status(page, WIFI_ACTION_STOP);
+ } else {
+ rv = eos_wifi_start(NULL, 0);
+ if (!rv) wifi_update_status(page, WIFI_ACTION_START);
+ }
+ if (rv) (APP_LOG_ERR, "WIFI START ERR:%d\n", rv);
+ return 1;
+ }
+
+ return 0;
+}
+
+void wifi_init(void) {
+ eos_wifi_set_handler(EOS_WIFI_MTYPE_STATUS, handle_status);
+ eos_wifi_set_handler(EOS_WIFI_MTYPE_SCAN, handle_scan);
+}
+
+int wifi_app(EVEWindow *window, EVEViewStack *stack) {
+ EVEFormSpec spec[] = {
+ APP_SPACERW(APP_SCREEN_W,20),
+ {
+ .label.title = "Enable:",
+ .label.g.w = APP_SCREEN_W - 100,
+
+ .widget.type = EVE_WIDGET_TYPE_TOGGLE,
+ .widget.g.w = 100,
+ .widget.tspec.toggle.labels = "off\xffon",
+ },
+ {
+ .widget.type = EVE_WIDGET_TYPE_FREE,
+ .widget.g.h = eve_font_h(app_font()),
+ .widget.tspec.free.draw = widget_ssid_draw,
+ .widget.tspec.free.touch = widget_ssid_touch,
+ },
+ {
+ .label.g.w = APP_SCREEN_W,
+ .label.title = "Select network:",
+
+ .widget.type = EVE_WIDGET_TYPE_SELECT,
+ .widget.g.w = APP_SCREEN_W,
+ .widget.tspec.select.option_size = EOS_WIFI_MAX_SCAN_RECORDS * EOS_WIFI_SIZE_SSID,
+ },
+ APP_SPACERW(APP_SCREEN_W,50),
+ {
+ .label.title = "Password:",
+
+ .widget.type = EVE_WIDGET_TYPE_STR,
+ .widget.tspec.str.str_size = EOS_WIFI_SIZE_PWD,
+ },
+ };
+ EVEPage *page;
+ EVEWidget *widget;
+ WIFIStatus *status;
+ int rv;
+ int action;
+
+ page = eve_form_create(window, stack, spec, APP_SPEC_SIZE(spec), wifi_uievt, wifi_close);
+ if (page == NULL) {
+ rv = EVE_ERR_NOMEM;
+ APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n");
+ return rv;
+ }
+
+ status = eve_malloc(sizeof(WIFIStatus));
+ if (status == NULL) {
+ rv = EVE_ERR_NOMEM;
+ eve_form_destroy(page);
+ APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n");
+ return rv;
+ }
+
+ page->v.param = status;
+ widget = eve_page_widget(page, 0);
+ widget->touch = widget_enable_touch;
+
+ rv = eos_wifi_status(&status->status, status->ip_addr, status->ssid, NULL);
+ if (rv) {
+ wifi_close(page);
+ APP_LOG(APP_LOG_ERR, "BAD STATUS ERR:%d\n", rv);
+ return rv;
+ }
+
+ action = WIFI_ACTION_IDLE;
+ if (status->status == EOS_WIFI_STATUS_DISCONNECTED) {
+ rv = eos_wifi_scan(NULL, 0);
+ if (rv) {
+ wifi_close(page);
+ APP_LOG(APP_LOG_ERR, "WIFI SCAN ERR:%d\n", rv);
+ return rv;
+ }
+ action = WIFI_ACTION_SCAN;
+ }
+ wifi_update_status(page, action);
+
+ return EVE_OK;
+}
+
+int wifi_uievt(EVEPage *page, uint16_t evt, void *param) {
+ int ret = 0;
+
+ switch (evt) {
+ case EVE_UIEVT_WIDGET_FOCUS_OUT: {
+ if (param == eve_page_widget(page, 3)) {
+ EVESelectWidget *selw;
+ utf8_t *ssid;
+
+ selw = (EVESelectWidget *)eve_page_widget(page, 2);
+ ssid = eve_selectw_option_selected(selw);
+ if (ssid) {
+ EVEStrWidget *strw = param;
+ WIFIStatus *status = page->v.param;
+ int rv;
+
+ rv = eos_wifi_connect((char *)ssid, (char *)strw->str, NULL, 0);
+ if (!rv) wifi_update_status(page, WIFI_ACTION_CONNECT);
+ if (rv) APP_LOG(APP_LOG_ERR, "WIFI CONNECT ERR:%d\n", rv);
+ }
+ }
+ break;
+ }
+
+ default: {
+ ret = eve_form_uievt(page, evt, param);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void wifi_close(EVEPage *page) {
+ eve_free(page->v.param);
+ eve_form_destroy(page);
+}
+
+void wifi_update_status(EVEPage *page, int action) {
+ WIFIStatus *status = page->v.param;
+ EVEWidget *widget;
+ int i;
+
+ /* enable */
+ widget = eve_page_widget(page, 0);
+ if (status->status == EOS_WIFI_STATUS_OFF) {
+ ((EVEToggleWidget *)widget)->state = 0;
+ } else {
+ ((EVEToggleWidget *)widget)->state = 1;
+ }
+
+ /* ssid */
+ widget = eve_page_widget(page, 1);
+ eve_widget_clr_flags(widget, (EVE_WIDGET_FLAG_HIDDEN | EVE_WIDGET_FLAG_BUSY));
+ if (action >= WIFI_ACTION_SCAN) {
+ eve_widget_set_flags(widget, EVE_WIDGET_FLAG_BUSY);
+ }
+ if ((status->status < EOS_WIFI_STATUS_CONNECTED) && !(widget->flags & EVE_WIDGET_FLAG_BUSY)) {
+ eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN);
+ }
+
+ /* select network and password */
+ widget = eve_page_widget(page, 2);
+ for (i=0; i<3; i++) {
+ eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN);
+ widget = eve_widget_next(widget);
+ }
+ if (action != WIFI_ACTION_NONE) status->action = action;
+ eve_form_update_g(page, NULL);
+}
+
+void wifi_update_scanr(EVEPage *page, unsigned char *buffer, size_t size) {
+ WIFIStatus *status = page->v.param;
+ EVEWidget *widget;
+ EVESelectWidget *selw;
+ int i, rv;
+
+ selw = (EVESelectWidget *)eve_page_widget(page, 2);
+ rv = eve_selectw_set_option(selw, buffer, size);
+ if (rv) {
+ APP_LOG(APP_LOG_ERR, "BAD SCAN ERR:%d\n", rv);
+ return;
+ }
+
+ /* ssid */
+ widget = eve_page_widget(page, 1);
+ eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_BUSY);
+ eve_widget_set_flags(widget, EVE_WIDGET_FLAG_HIDDEN);
+
+ /* select network and password */
+ widget = eve_page_widget(page, 2);
+ for (i=0; i<3; i++) {
+ eve_widget_clr_flags(widget, EVE_WIDGET_FLAG_HIDDEN);
+ widget = eve_widget_next(widget);
+ }
+ status->action = WIFI_ACTION_IDLE;
+ eve_form_update_g(page, NULL);
+}
diff --git a/fw/fe310/phone/wifi.h b/fw/fe310/phone/wifi.h
new file mode 100644
index 0000000..9ec668f
--- /dev/null
+++ b/fw/fe310/phone/wifi.h
@@ -0,0 +1,15 @@
+#include <net/wifi.h>
+
+typedef struct WIFIStatus {
+ uint8_t status;
+ uint8_t action;
+ uint8_t ip_addr[4];
+ char ssid[EOS_WIFI_SIZE_SSID];
+} WIFIStatus;
+
+void wifi_init(void);
+int wifi_app(EVEWindow *window, EVEViewStack *stack);
+int wifi_uievt(EVEPage *page, uint16_t evt, void *param);
+void wifi_close(EVEPage *page);
+void wifi_update_status(EVEPage *page, int action);
+void wifi_update_scanr(EVEPage *page, unsigned char *buffer, size_t size);