#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; 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); } static void handle_cell_voice(unsigned char type, unsigned char *buffer, uint16_t len) { int rv; switch (type) { case EOS_CELL_MTYPE_VOICE_RING: { rv = EOS_OK; if (len > EOS_CELL_MAX_DIAL_STR + 1) rv = EOS_ERR_SIZE; if (rv) { APP_LOG(APP_LOG_ERR, "RING ERROR:%d\n", rv); break; } buffer[len + 1] = '\0'; APP_LOG(APP_LOG_DEBUG, "RING:%s\n", buffer+1); if ((phone_state == PHONE_STATE_IDLE) || (phone_state == PHONE_STATE_RING)) { phone_state = PHONE_STATE_RING; app_status_set_msg("RING"); } break; } case EOS_CELL_MTYPE_VOICE_BUSY: { APP_LOG(APP_LOG_DEBUG, "BUSY\n"); if (phone_state == PHONE_STATE_DIAL) { phone_state = PHONE_STATE_IDLE; app_status_set_msg("BUSY"); } break; } case EOS_CELL_MTYPE_VOICE_MISS: { APP_LOG(APP_LOG_DEBUG, "MISS\n"); if ((phone_state == PHONE_STATE_DIAL) || (phone_state == PHONE_STATE_RING)) { phone_state = PHONE_STATE_IDLE; app_status_set_msg("MISS"); } break; } case EOS_CELL_MTYPE_VOICE_BEGIN: { APP_LOG(APP_LOG_DEBUG, "CALL BEGIN\n"); if ((phone_state == PHONE_STATE_DIAL) || (phone_state == PHONE_STATE_RING)) { phone_state = PHONE_STATE_CIP; app_status_set_msg("CALL BEGIN"); eos_net_acquire_for_evt(EOS_EVT_I2S | EOS_I2S_ETYPE_MIC, 1); eos_i2s_spk_set_buf(spk_arr, ABUF_SIZE); eos_i2s_mic_set_buf(mic_arr, ABUF_SIZE); eos_i2s_mic_set_handler(handle_mic, MIC_WM); eos_i2s_mic_set_vol(4); eos_i2s_start(8000); } break; } case EOS_CELL_MTYPE_VOICE_END: { APP_LOG(APP_LOG_DEBUG, "CALL END\n"); if (phone_state == PHONE_STATE_CIP) { phone_state = PHONE_STATE_IDLE; app_status_set_msg("CALL END"); 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, EOS_I2S_TRANS_MONO2D); } break; } } eos_net_free(buffer, 0); } #define BTN_R 50 #define BTN_SP ((APP_SCREEN_W - 6 * BTN_R) / 4) #define BTN_C1 (BTN_SP + BTN_R) #define BTN_C2 (2 * BTN_SP + 3 * BTN_R) #define BTN_C3 (3 * BTN_SP + 5 * BTN_R) #define BTN_C4 (4 * BTN_SP + 7 * BTN_R) #define BTN_C5 (5 * BTN_SP + 9 * BTN_R) static void widget_btn_draw(EVEFreeWidget *widget) { EVEWidget *_widget = &widget->w; EVEPage *page = _widget->page; uint8_t tag0; eve_cmd_dl(BEGIN(EVE_POINTS)); eve_cmd_dl(POINT_SIZE(BTN_R * 16)); eve_cmd_dl(COLOR_RGB(0x20, 0x20, 0x20)); tag0 = eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C1, _widget->g.y + BTN_C2)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C2, _widget->g.y + BTN_C2)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C3, _widget->g.y + BTN_C2)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C1, _widget->g.y + BTN_C3)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C2, _widget->g.y + BTN_C3)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C3, _widget->g.y + BTN_C3)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C1, _widget->g.y + BTN_C4)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C2, _widget->g.y + BTN_C4)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C3, _widget->g.y + BTN_C4)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C1, _widget->g.y + BTN_C5)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C2, _widget->g.y + BTN_C5)); eve_freew_tag(widget); eve_cmd_dl(VERTEX2F(BTN_C3, _widget->g.y + BTN_C5)); eve_freew_tag(widget); eve_cmd_dl(COLOR_RGB(0x0, 0x255, 0x0)); eve_cmd_dl(VERTEX2F(BTN_C1, _widget->g.y + BTN_C1)); eve_freew_tag(widget); eve_cmd_dl(COLOR_RGB(0x255, 0x0, 0x0)); eve_cmd_dl(VERTEX2F(BTN_C3, _widget->g.y + BTN_C1)); eve_cmd_dl(COLOR_RGBC(page->v.color_fg)); eve_cmd_dl(END()); eve_cmd_dl(TAG(tag0)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C1, _widget->g.y + BTN_C2, app_font()->id, EVE_OPT_CENTER, "1"); eve_cmd_dl(TAG(tag0 + 1)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C2, _widget->g.y + BTN_C2, app_font()->id, EVE_OPT_CENTER, "2"); eve_cmd_dl(TAG(tag0 + 2)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C3, _widget->g.y + BTN_C2, app_font()->id, EVE_OPT_CENTER, "3"); eve_cmd_dl(TAG(tag0 + 3)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C1, _widget->g.y + BTN_C3, app_font()->id, EVE_OPT_CENTER, "4"); eve_cmd_dl(TAG(tag0 + 4)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C2, _widget->g.y + BTN_C3, app_font()->id, EVE_OPT_CENTER, "5"); eve_cmd_dl(TAG(tag0 + 5)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C3, _widget->g.y + BTN_C3, app_font()->id, EVE_OPT_CENTER, "6"); eve_cmd_dl(TAG(tag0 + 6)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C1, _widget->g.y + BTN_C4, app_font()->id, EVE_OPT_CENTER, "7"); eve_cmd_dl(TAG(tag0 + 7)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C2, _widget->g.y + BTN_C4, app_font()->id, EVE_OPT_CENTER, "8"); eve_cmd_dl(TAG(tag0 + 8)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C3, _widget->g.y + BTN_C4, app_font()->id, EVE_OPT_CENTER, "9"); eve_cmd_dl(TAG(tag0 + 9)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C1, _widget->g.y + BTN_C5, app_font()->id, EVE_OPT_CENTER, "*"); eve_cmd_dl(TAG(tag0 + 10)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C2, _widget->g.y + BTN_C5, app_font()->id, EVE_OPT_CENTER, "0"); eve_cmd_dl(TAG(tag0 + 11)); eve_cmd(CMD_TEXT, "hhhhs", BTN_C3, _widget->g.y + BTN_C5, app_font()->id, EVE_OPT_CENTER, "#"); } static void call(char *num) { int rv; if (strlen(num)) { phone_state = PHONE_STATE_DIAL; 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); } } 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 < 12) { EVEPage *page = widget->w.page; EVEStrWidget *strw = (EVEStrWidget *)eve_page_widget(page, 0); int ch; if (tagi < 9) { ch = '0' + tagi + 1; } else { switch (tagi) { case 9: ch = '*'; break; case 10: ch = '0'; break; case 11: ch = '#'; break; } } printf("PUTC CH:%d\n", ch); eve_strw_putc(strw, ch); } else if (tagi == 12) { 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); call(strw->str); break; } } } else if (tagi == 13) { if (phone_state != PHONE_STATE_IDLE) { if (phone_state != PHONE_STATE_CIP) { phone_state = PHONE_STATE_IDLE; } rv = eos_cell_voice_hangup(NULL, 0); if (rv) APP_LOG(APP_LOG_ERR, "HANGUP ERR:%d\n", rv); } } return 1; } return 0; } void phone_init(void) { eos_cell_set_handler(EOS_CELL_MTYPE_VOICE, handle_cell_voice); } 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 + 1, }, APP_SPACERW(APP_SCREEN_W, 10), { .widget.type = EVE_WIDGET_TYPE_FREE, .widget.g.w = APP_SCREEN_W, .widget.g.h = APP_SCREEN_H, .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) { APP_LOG(APP_LOG_ERR, "OUT OF MEMORY\n"); return EVE_ERR_NOMEM; } EVEStrWidget *strw = (EVEStrWidget *)eve_page_widget(page, 0); strw->w.putc = NULL; eve_widget_set_focus(&strw->w); 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; if (phone_state == PHONE_STATE_IDLE) { call(strw->str); } } break; } default: { ret = eve_form_uievt(page, evt, param); break; } } return ret; } void phone_close(EVEPage *page) { eve_form_destroy(page); } unsigned char phone_get_state(void) { return phone_state; }