From fc98d3809e0db36d634f290417b9152f87f83e3e Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Sun, 4 Sep 2022 18:37:42 +0200 Subject: new phone firmware --- fw/fe310/bsp/openocd_jlink.cfg | 19 +++ fw/fe310/phone/Makefile | 32 ++++ fw/fe310/phone/app/Makefile | 15 ++ fw/fe310/phone/app/app.c | 106 +++++++++++++ fw/fe310/phone/app/app.h | 27 ++++ fw/fe310/phone/app/log.h | 6 + fw/fe310/phone/app/status.c | 68 ++++++++ fw/fe310/phone/app/status.h | 6 + fw/fe310/phone/cell.c | 64 ++++++++ fw/fe310/phone/cell.h | 2 + fw/fe310/phone/main.c | 94 +++++++++++ fw/fe310/phone/mem.c | 24 +++ fw/fe310/phone/modem.c | 197 +++++++++++++++++++++++ fw/fe310/phone/modem.h | 2 + fw/fe310/phone/phone.c | 215 +++++++++++++++++++++++++ fw/fe310/phone/phone.h | 9 ++ fw/fe310/phone/test.c | 70 ++++++++ fw/fe310/phone/test.h | 2 + fw/fe310/phone/timer.c | 47 ++++++ fw/fe310/phone/timer.h | 2 + fw/fe310/phone/wifi.c | 351 +++++++++++++++++++++++++++++++++++++++++ fw/fe310/phone/wifi.h | 15 ++ 22 files changed, 1373 insertions(+) create mode 100644 fw/fe310/bsp/openocd_jlink.cfg create mode 100644 fw/fe310/phone/Makefile create mode 100644 fw/fe310/phone/app/Makefile create mode 100644 fw/fe310/phone/app/app.c create mode 100644 fw/fe310/phone/app/app.h create mode 100644 fw/fe310/phone/app/log.h create mode 100644 fw/fe310/phone/app/status.c create mode 100644 fw/fe310/phone/app/status.h create mode 100644 fw/fe310/phone/cell.c create mode 100644 fw/fe310/phone/cell.h create mode 100644 fw/fe310/phone/main.c create mode 100644 fw/fe310/phone/mem.c create mode 100644 fw/fe310/phone/modem.c create mode 100644 fw/fe310/phone/modem.h create mode 100644 fw/fe310/phone/phone.c create mode 100644 fw/fe310/phone/phone.h create mode 100644 fw/fe310/phone/test.c create mode 100644 fw/fe310/phone/test.h create mode 100644 fw/fe310/phone/timer.c create mode 100644 fw/fe310/phone/timer.h create mode 100644 fw/fe310/phone/wifi.c create mode 100644 fw/fe310/phone/wifi.h (limited to 'fw/fe310') 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 + +#include + +#include +#include +#include + +#include +#include +#include + +#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 + +#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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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 + +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 +#include +#include +#include + +#include +#include +#include + +#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 +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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 + +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 + +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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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= ¶m->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 = ¶m->text; + int i; + + eve_select(); + for (i=1; idirty) { + 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 = ¶m->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 = ¶m->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(¶m->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 +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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 +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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 +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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 + +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); -- cgit v1.2.3