From 5af54304a161eb0a713e21344c26fab8ee36f410 Mon Sep 17 00:00:00 2001 From: "freddy.li" Date: Wed, 8 Dec 2021 13:35:15 +0800 Subject: [PATCH] update Micropython --- extmod/vfs_efs.c | 15 +- lib/utils/interrupt_char.c | 5 +- lib/utils/interrupt_char.h | 32 +- lib/utils/pyexec.c | 17 +- microPython.mk | 17 +- ports/quectel/core/Makefile | 25 +- ports/quectel/core/_boot.py | 7 +- ports/quectel/core/_boot_Qualcomm.py | 18 +- ports/quectel/core/checkNet.py | 6 +- ports/quectel/core/dataCall.py | 7 +- ports/quectel/core/gnss.py | 27 +- ports/quectel/core/log.py | 8 + ports/quectel/core/ql_fs.py | 5 +- ports/quectel/core/request.py | 21 +- ports/quectel/core/source/audio_audio.c | 253 +++- ports/quectel/core/source/audio_queue.c | 13 +- ports/quectel/core/source/audio_record.c | 81 +- ports/quectel/core/source/audio_tts.c | 104 +- ports/quectel/core/source/callbackdeal.c | 207 +++ ports/quectel/core/source/callbackdeal.h | 61 + ports/quectel/core/source/camera_capture.c | 19 +- ports/quectel/core/source/devreport.c | 532 ++++++++ ports/quectel/core/source/machine_extint.c | 44 +- ports/quectel/core/source/machine_iic.c | 4 +- .../core/source/machine_iic_simulation.c | 516 ++++++++ ports/quectel/core/source/machine_keypad.c | 4 +- ports/quectel/core/source/machine_lcd.c | 4 - ports/quectel/core/source/machine_uart.c | 8 +- ports/quectel/core/source/misc_pwm.c | 54 +- ports/quectel/core/source/misc_temperature.c | 78 ++ ports/quectel/core/source/misc_usb.c | 3 +- ports/quectel/core/source/misc_usbnet.c | 46 +- ports/quectel/core/source/modaudio.c | 161 ++- ports/quectel/core/source/modaudio.h | 14 + ports/quectel/core/source/moddatacall.c | 115 +- ports/quectel/core/source/modexample.c | 2 + ports/quectel/core/source/modlpm.c | 39 +- ports/quectel/core/source/modlvgl.c | 36 +- ports/quectel/core/source/modmachine.c | 3 +- ports/quectel/core/source/modmachine.h | 3 +- ports/quectel/core/source/modmisc.c | 7 +- ports/quectel/core/source/modmisc.h | 5 +- ports/quectel/core/source/modnet.c | 226 +++- ports/quectel/core/source/modquecIot.c | 1134 ----------------- ports/quectel/core/source/modsim.c | 134 +- ports/quectel/core/source/modvoicecall.c | 1039 +++++++++------ ports/quectel/core/source/modwifilocator.c | 902 +++++++++++++ ports/quectel/core/source/modwifilocator.h | 235 ++++ ports/quectel/core/source/mpconfigport.h | 12 + ports/quectel/core/source/mphalport.c | 29 +- ports/quectel/core/source/mpthreadport.c | 14 + ports/quectel/core/source/mpthreadport.h | 1 + ports/quectel/core/source/quecpython.c | 36 +- ports/quectel/core/umqtt.py | 2 +- ports/quectel/core/wifilocator.py | 67 + py/objboundmeth.c | 5 + py/profile.c | 4 + py/runtime.c | 6 + py/scheduler.c | 37 +- py/vm.c | 8 + 60 files changed, 4713 insertions(+), 1804 deletions(-) create mode 100644 ports/quectel/core/source/callbackdeal.c create mode 100644 ports/quectel/core/source/callbackdeal.h create mode 100644 ports/quectel/core/source/devreport.c create mode 100644 ports/quectel/core/source/machine_iic_simulation.c create mode 100644 ports/quectel/core/source/misc_temperature.c delete mode 100644 ports/quectel/core/source/modquecIot.c create mode 100644 ports/quectel/core/source/modwifilocator.c create mode 100644 ports/quectel/core/source/modwifilocator.h create mode 100644 ports/quectel/core/wifilocator.py diff --git a/extmod/vfs_efs.c b/extmod/vfs_efs.c index 5f1491c..45ed634 100644 --- a/extmod/vfs_efs.c +++ b/extmod/vfs_efs.c @@ -362,6 +362,7 @@ typedef struct _vfs_efs_ilistdir_it_t { mp_fun_1_t iternext; bool is_str; void *dir; + char ilist_path[64]; bool readonly; } vfs_efs_ilistdir_it_t; @@ -402,14 +403,8 @@ STATIC mp_obj_t vfs_efs_ilistdir_it_iternext(mp_obj_t self_in) { { t->items[0] = mp_obj_new_bytes((const byte *)iter_entry.file_Path, strlen(iter_entry.file_Path)); } - if(self->readonly) - { - sprintf(real_file_path, "%s%s", "/bak/", iter_entry.file_Path); - } - else - { - sprintf(real_file_path, "%s%s", "/usr/", iter_entry.file_Path); - } + + sprintf(real_file_path, "%s%s", self->ilist_path, iter_entry.file_Path); Helios_fstat(real_file_path, &sb); memset (real_file_path, 0, sizeof(real_file_path)); t->items[1] = MP_OBJ_NEW_SMALL_INT(((sb.st_Mode) & EFS_IFMT) == EFS_IFDIR ? MP_S_IFDIR : MP_S_IFREG); @@ -433,6 +428,7 @@ STATIC mp_obj_t vfs_efs_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; const char *path = mp_obj_str_get_str(path_in); char f_path[64] = ""; + int len = 0; if (path[0] == '\0') { path = "."; @@ -448,6 +444,9 @@ STATIC mp_obj_t vfs_efs_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { sprintf(f_path, "%s%s", "/usr", path); iter->readonly = false; } + len = (strlen(f_path) < 60) ? strlen(f_path) : 60; + memset (iter->ilist_path, 0, sizeof(iter->ilist_path)); + strncpy(iter->ilist_path, f_path, len); iter->dir = Helios_fdiropen(f_path); if (iter->dir == NULL) { diff --git a/lib/utils/interrupt_char.c b/lib/utils/interrupt_char.c index c1d1a0a..e1ed646 100644 --- a/lib/utils/interrupt_char.c +++ b/lib/utils/interrupt_char.c @@ -29,11 +29,14 @@ #include "py/mpstate.h" #if MICROPY_KBD_EXCEPTION - +#include "interrupt_char.h" int mp_interrupt_char = -1; void mp_hal_set_interrupt_char(int c) { mp_interrupt_char = c; } +SET_MAINPY_RUNNING_TIMER_CALLBACK_DEF +#else +void mp_hal_set_interrupt_char(int c) {(void)c;return;} #endif diff --git a/lib/utils/interrupt_char.h b/lib/utils/interrupt_char.h index 1b0c97f..453e4de 100644 --- a/lib/utils/interrupt_char.h +++ b/lib/utils/interrupt_char.h @@ -27,11 +27,14 @@ #ifndef MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H #define MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H +#include "helios_os.h" typedef int Helios_Thread_t; extern int mainpy_running_flag; extern int mainpy_interrupt_by_kbd_flag; extern int repl_protect_enable; extern Helios_Thread_t ql_micropython_task_ref; +extern Helios_OSTimer_t set_mainpy_running_timer; +extern void set_mainpy_running_timer_callback(void *para); #define RET_KBD_INTERRUPT (0x00FA00FA) @@ -39,12 +42,15 @@ extern Helios_Thread_t ql_micropython_task_ref; #define MAINPY_RUNNING_FLAG mainpy_running_flag #define MAINPY_INTERRUPT_BY_KBD_FLAG mainpy_interrupt_by_kbd_flag +#define SET_MAINPY_RUNNING_TIMER set_mainpy_running_timer #define MAINPY_RUNNING_FLAG_DEF int MAINPY_RUNNING_FLAG = 0; #define MAINPY_INTERRUPT_BY_KBD_FLAG_DEF int MAINPY_INTERRUPT_BY_KBD_FLAG = 0; +#define SET_MAINPY_RUNNING_TIMER_DEF Helios_OSTimer_t SET_MAINPY_RUNNING_TIMER = 0; -#define MAINPY_RUNNING_FLAG_SET() MAINPY_RUNNING_FLAG = 1; -#define MAINPY_RUNNING_FLAG_CLEAR() MAINPY_RUNNING_FLAG = 0; + +#define MAINPY_RUNNING_FLAG_SET() SET_MAINPY_RUNNING_TIMER_START() +#define MAINPY_RUNNING_FLAG_CLEAR() SET_MAINPY_RUNNING_TIMER_STOP(); MAINPY_RUNNING_FLAG = 0; #define IS_MAINPY_RUNNING_FLAG_TRUE() (1 == MAINPY_RUNNING_FLAG) #define IS_MAINPY_RUNNING_FLAG_FALSE() (0 == MAINPY_RUNNING_FLAG) #define MAINPY_INTERRUPT_BY_KBD_FLAG_SET() MAINPY_INTERRUPT_BY_KBD_FLAG = 1; @@ -52,6 +58,28 @@ extern Helios_Thread_t ql_micropython_task_ref; #define MAINPY_INTERRUPT_BY_KBD_FLAG_TRUE() (1 == MAINPY_INTERRUPT_BY_KBD_FLAG) #define MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE() (0 == MAINPY_INTERRUPT_BY_KBD_FLAG) +#define SET_MAINPY_RUNNING_TIMER_INITIALTIMER (1000)//ms + +#define SET_MAINPY_RUNNING_TIMER_CALLBACK set_mainpy_running_timer_callback +#define SET_MAINPY_RUNNING_TIMER_CALLBACK_DEF void set_mainpy_running_timer_callback(void *para) { \ + (void)para; \ + MAINPY_RUNNING_FLAG = 1; \ + } +#define SET_MAINPY_RUNNING_TIMER_INIT() do{if(0 == SET_MAINPY_RUNNING_TIMER){SET_MAINPY_RUNNING_TIMER = Helios_OSTimer_Create();}}while(0) +#define SET_MAINPY_RUNNING_TIMER_START() do{if(0 != SET_MAINPY_RUNNING_TIMER){ \ + Helios_OSTimerAttr OSTimerAttr = { \ + .ms = (uint32_t)SET_MAINPY_RUNNING_TIMER_INITIALTIMER, \ + .cycle_enable = 0, \ + .cb = SET_MAINPY_RUNNING_TIMER_CALLBACK, \ + .argv = (void *)NULL \ + }; \ + Helios_OSTimer_Start(SET_MAINPY_RUNNING_TIMER, &OSTimerAttr);}}while(0) +#define SET_MAINPY_RUNNING_TIMER_STOP() do{if(0 != SET_MAINPY_RUNNING_TIMER){Helios_OSTimer_Stop(SET_MAINPY_RUNNING_TIMER);}}while(0) +#define SET_MAINPY_RUNNING_TIMER_DEINIT() do{if(0 != SET_MAINPY_RUNNING_TIMER){Helios_OSTimer_Stop(SET_MAINPY_RUNNING_TIMER); \ + Helios_OSTimer_Delete(SET_MAINPY_RUNNING_TIMER); \ + SET_MAINPY_RUNNING_TIMER = (Helios_OSTimer_t)0;}}while(0) + + #define IS_PYTHON_MAIN_THREAD() (Helios_Thread_GetID() == ql_micropython_task_ref) #define IS_OBJ_KBD_INTERRUPT_TYPE() (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) #define CHECK_MAINPY_KBD_INTERRUPT_ENTER() if(IS_MAINPY_RUNNING_FLAG_FALSE() || !IS_OBJ_KBD_INTERRUPT_TYPE() || IS_PYTHON_MAIN_THREAD()) { diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index f66e6e7..8bc32d3 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -147,9 +147,11 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // at the moment, the value of SystemExit is unused ret = pyexec_system_exit; + #if MICROPY_KBD_EXCEPTION } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); ret = RET_KBD_INTERRUPT; + #endif } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); ret = 0; @@ -561,11 +563,8 @@ raw_repl_reset: //extern const char mob_model_id[]; int pyexec_friendly_repl(void) { -#if !defined(PLAT_RDA) char mob_model_id[64] = {0}; char printf_info[256] = {0}; -#endif - vstr_t line; vstr_init(&line, 32); @@ -578,13 +577,12 @@ int pyexec_friendly_repl(void) { friendly_repl_reset: //mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); //mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"); -#if !defined(PLAT_RDA) + #if !defined(PLAT_Qualcomm) Helios_Dev_GetModel((void *)mob_model_id, sizeof(mob_model_id)); #endif sprintf(printf_info, "Quecpython %s on %s ; %s with %s \r\n ", MICROPY_GIT_TAG, MICROPY_BUILD_DATE, mob_model_id, MICROPY_HW_MCU_NAME); mp_hal_stdout_tx_str(printf_info); -#endif #if MICROPY_PY_BUILTINS_HELP mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); @@ -704,9 +702,13 @@ friendly_repl_reset: } } } + #if MICROPY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_SET(); + #endif ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR); + #if MICROPY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_CLEAR(); + #endif if (ret & PYEXEC_FORCED_EXIT) { return ret; } @@ -729,10 +731,7 @@ int pyexec_file_if_exists(const char *filename) { if (mp_import_stat(filename) != MP_IMPORT_STAT_FILE) { return 1; // success (no file is the same as an empty file executing without fail) } - if(IS_PYTHON_MAIN_THREAD()) {MAINPY_RUNNING_FLAG_SET();} - int ret = pyexec_file(filename); - if(IS_PYTHON_MAIN_THREAD()) {MAINPY_RUNNING_FLAG_CLEAR();} - return ret; + return pyexec_file(filename); } #if MICROPY_MODULE_FROZEN diff --git a/microPython.mk b/microPython.mk index ad4537f..f305fe5 100644 --- a/microPython.mk +++ b/microPython.mk @@ -56,12 +56,15 @@ $(NAME)_SRCS = \ ports/quectel/core/source/modsim.c \ ports/quectel/core/source/modnet.c \ ports/quectel/core/source/machine_iic.c \ + ports/quectel/core/source/machine_iic_simulation.c \ ports/quectel/core/source/modfota.c \ ports/quectel/core/source/moddev.c \ ports/quectel/core/source/modostimer.c \ ports/quectel/core/source/machine_timer.c \ ports/quectel/core/source/misc_powerkey.c \ ports/quectel/core/source/modlpm.c \ + ports/quectel/core/source/devreport.c \ + ports/quectel/core/source/callbackdeal.c \ py/argcheck.c \ py/asmarm.c \ py/asmbase.c \ @@ -199,7 +202,8 @@ $(NAME)_SRCS += \ ports/quectel/core/source/modnb.c \ ports/quectel/core/source/nb_oc.c \ ports/quectel/core/source/nb_aep.c \ - ports/quectel/core/source/nb_onenet.c + ports/quectel/core/source/nb_onenet.c \ + ports/quectel/core/source/misc_temperature.c endif ifneq ($(strip $(PLAT)),RDA) @@ -220,7 +224,9 @@ $(NAME)_SRCS += \ ports/quectel/core/source/audio_record.c \ ports/quectel/core/source/misc_pwm.c \ ports/quectel/core/source/misc_usb.c \ - ports/quectel/core/source/audio_queue.c \ + ports/quectel/core/source/audio_queue.c \ + ports/quectel/core/source/modwifilocator.c \ + ports/quectel/core/source/machine_keypad.c ifeq ($(strip $(PLAT)),ASR) $(NAME)_SRCS += \ @@ -228,7 +234,6 @@ $(NAME)_SRCS += \ ports/quectel/core/source/misc_usbnet.c \ ports/quectel/core/source/modslipif.c \ ports/quectel/core/source/modethernet.c \ - ports/quectel/core/source/machine_keypad.c \ ports/quectel/core/source/modethernet_dm9051.c endif @@ -237,7 +242,8 @@ endif ifeq ($(strip $(PLAT)),Unisoc) $(NAME)_SRCS += \ - ports/quectel/core/source/modgnss.c + ports/quectel/core/source/modgnss.c \ + ports/quectel/core/source/misc_usbnet.c endif ifeq ($(CONFIG_TTS), y) @@ -390,7 +396,8 @@ endif ifeq ($(CONFIG_QUECTHING), y) ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR Unisoc)) -$(NAME)_SRCS += ports/quectel/core/source/modquecIot.c +#$(NAME)_SRCS += ports/quectel/core/source/modquecIot.c +$(NAME)_SRCS += ../../components/quecsdk/cloud/python/modquecIot.c $(NAME)_INCS += ../../components/quecsdk $(NAME)_COMPONENTS += components/quecsdk endif diff --git a/ports/quectel/core/Makefile b/ports/quectel/core/Makefile index cc9c36f..f6fead4 100644 --- a/ports/quectel/core/Makefile +++ b/ports/quectel/core/Makefile @@ -294,7 +294,10 @@ SRC_QSTR += source/quecpython.c \ source/modlpm.c \ source/machine_extint.c \ source/machine_hw_spi.c \ - source/machine_iic.c + source/machine_iic.c \ + source/machine_iic_simulation.c \ + source/callbackdeal.c \ + source/devreport.c else SRC_QSTR += source/quecpython.c \ source/moduos.c \ @@ -319,16 +322,18 @@ SRC_QSTR += source/quecpython.c \ source/modsim.c \ source/modnet.c \ source/machine_iic.c \ + source/machine_iic_simulation.c \ source/moddev.c \ source/misc_powerkey.c \ - source/modlpm.c + source/modlpm.c \ + source/callbackdeal.c \ + source/devreport.c endif ifeq ($(strip $(PLAT)),ASR) SRC_QSTR += source/modsecuredata.c \ source/misc_usbnet.c \ - source/machine_keypad.c \ source/modslipif.c \ source/modethernet.c \ source/modethernet_dm9051.c @@ -338,7 +343,8 @@ ifeq ($(strip $(PLAT)),RDA) SRC_QSTR += source/modnb.c \ source/nb_oc.c \ source/nb_aep.c \ - source/nb_onenet.c + source/nb_onenet.c \ + source/misc_temperature.c endif ifneq ($(strip $(PLAT)),RDA) @@ -356,12 +362,14 @@ SRC_QSTR += source/modsms.c \ source/modsensor.c \ source/misc_usb.c \ source/misc_pwm.c \ - source/modvoicecall.c + source/modwifilocator.c \ + source/modvoicecall.c \ + source/machine_keypad.c #quecthing ifeq ($(CONFIG_QUECTHING), y) ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR Unisoc)) -SRC_QSTR += source/modquecIot.c +SRC_QSTR += $(ROOT)/components/quecsdk/cloud/python/modquecIot.c endif endif @@ -402,7 +410,8 @@ endif endif ifeq ($(strip $(PLAT)),Unisoc) -SRC_QSTR += source/modgnss.c +SRC_QSTR += source/modgnss.c \ + source/misc_usbnet.c endif ifeq ($(CONFIG_BT), y) @@ -733,6 +742,7 @@ $(BUILD)/_frozen_mpy.c: \ $(BUILD)/sys_bus.mpy \ $(BUILD)/event_message.mpy \ $(BUILD)/hls.mpy \ + $(BUILD)/wifilocator.mpy \ $(BUILD)/bak_util.mpy \ $(HEADER_BUILD)/qstrdefs.generated.h @$(ECHO) "MISC freezing bytecode" @@ -765,6 +775,7 @@ $(BUILD)/_frozen_mpy.c: \ $(BUILD)/sys_bus.mpy \ $(BUILD)/event_message.mpy \ $(BUILD)/hls.mpy \ + $(BUILD)/wifilocator.mpy \ $(BUILD)/bak_util.mpy \ > $@ endif diff --git a/ports/quectel/core/_boot.py b/ports/quectel/core/_boot.py index e985475..274d2d4 100644 --- a/ports/quectel/core/_boot.py +++ b/ports/quectel/core/_boot.py @@ -15,6 +15,7 @@ import gc import uos import ujson +import dial import dataCall import backup_restore import app_fota @@ -76,7 +77,11 @@ def _auto_data_call(): def _check_data_call(): - for pdp in range(1, 8): + retval = dial.getPdpRange() + min = retval[0] + max = retval[1] + # print('min={},max={}'.format(min, max)) + for pdp in range(min, max+1): nw_sta = dataCall.getInfo(pdp, 2) if (nw_sta != -1) and (nw_sta[2][0] == 0) and (nw_sta[3][0] == 0): continue diff --git a/ports/quectel/core/_boot_Qualcomm.py b/ports/quectel/core/_boot_Qualcomm.py index 2968fed..90af9f8 100644 --- a/ports/quectel/core/_boot_Qualcomm.py +++ b/ports/quectel/core/_boot_Qualcomm.py @@ -54,20 +54,20 @@ def _call_by_user_apn(): dataCall.setAutoConnect(int(pdp), 1) dataCall.recordApn(int(pdp), int(ipv), apn, usr, pwd, int(ath), 1) - dataCall.setAsynMode(1) + #dataCall.setAsynMode(1) ret = -1 repeat_count = 2 while (ret == -1) and (repeat_count >= 0): repeat_count -= 1 ret = dataCall.start(int(pdp), int(ipv), apn, usr, pwd, int(ath)) - dataCall.setAsynMode(0) + #dataCall.setAsynMode(0) def _auto_data_call(): - _call_by_default_apn() - #try: - #_call_by_user_apn() - #except OSError as e: + try: + _call_by_user_apn() + except OSError as e: + _call_by_default_apn() #if e.args[0] == 2: # print('######user_apn.json not found!') #_call_by_default_apn() @@ -89,7 +89,7 @@ def _repl_enable(): json_data = ujson.load(fd) repl_flag = json_data.get("replFlag", 0) datacall_flag = json_data.get("datacallFlag",1) - misc.replEnable(repl_flag) + #misc.replEnable(repl_flag) else: with open("/usr/system_config.json", "w+", encoding='utf-8') as fd: repl_data = ujson.dumps({"replFlag": 0}) @@ -107,11 +107,9 @@ except Exception: print('error ocurs in boot step.') finally: - #global datacall_flag - #_repl_enable() + _repl_enable() if datacall_flag == 1: ret = _check_data_call() if ret == 0: _auto_data_call() - diff --git a/ports/quectel/core/checkNet.py b/ports/quectel/core/checkNet.py index e809b5f..3542153 100644 --- a/ports/quectel/core/checkNet.py +++ b/ports/quectel/core/checkNet.py @@ -91,7 +91,7 @@ class CheckNetwork(): if timeout_ms <= 0: return stage_code, -1 else: - if net_sta[1][0] == 1: + if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): break else: utime.sleep_ms(100) @@ -140,7 +140,7 @@ def wait_network_connected(timeout_s=60): if timeout_ms <= 0: return stage_code, -1 else: - if net_sta[1][0] == 1: + if (net_sta[1][0] == 1) or (net_sta[1][0] == 5): break else: utime.sleep_ms(100) @@ -157,4 +157,4 @@ def wait_network_connected(timeout_s=60): utime.sleep_ms(100) timeout_ms -= 100 if timeout_ms <= 0: - return stage_code, datacall_sta \ No newline at end of file + return stage_code, datacall_sta diff --git a/ports/quectel/core/dataCall.py b/ports/quectel/core/dataCall.py index 237a61f..b2bc27d 100644 --- a/ports/quectel/core/dataCall.py +++ b/ports/quectel/core/dataCall.py @@ -76,5 +76,8 @@ def setCallback(usrfun): def setAutoConnect(profileidx, enable): return dial.setAutoConnect(profileidx, enable) -def getApn(simid): - return dial.getApn(simid) \ No newline at end of file +def getApn(*args): + return dial.getApn(*args) + +def setDnsserver(profileidx, simid, new_pri, new_sec): + return dial.setDnsserver(profileidx, simid, new_pri, new_sec) \ No newline at end of file diff --git a/ports/quectel/core/gnss.py b/ports/quectel/core/gnss.py index cdc812a..6ce82d8 100644 --- a/ports/quectel/core/gnss.py +++ b/ports/quectel/core/gnss.py @@ -45,10 +45,13 @@ class GnssGetData: self.r2 = ure.search("GPGSV(.+?)M", gps_data) self.r3 = ure.search("GNVTG(.+?)M", gps_data) global fixFlag - if self.r1.group(0).split(",")[2] == 'A': #有效定位 - fixFlag=1 + if self.r1 is None: + fixFlag = 0 else: - fixFlag=0 + if self.r1.group(0).split(",")[2] == 'A': #有效定位 + fixFlag=1 + else: + fixFlag=0 except: print("Exception:read gnss data error!!!!!!!!") raise @@ -59,18 +62,24 @@ class GnssGetData: #获取GPS模块定位的经纬度信息 def getLocation(self): if self.isFix() is 1: + if self.r is None: + return -1 lat=float(self.r.group(0).split(",")[2])//100 +float(float(float(self.r.group(0).split(",")[2])%100)/60) # lat_d=self.r.group(0).split(",")[3] # log=float(self.r.group(0).split(",")[4])//100 +float(float(float(self.r.group(0).split(",")[4])%100)/60) # log_d=self.r.group(0).split(",")[5] # return lat,lat_d,log,log_d else: - return None + return -1 #获取GPS模块授时的UTC时间 def getUtcTime(self): + if self.r is None: + return -1 return self.r.group(0).split(",")[1] #获取GPS模块定位模式 def getLocationMode(self): + if self.r is None: + return -1 if self.r.group(0).split(",")[6] is '0': #print('定位不可用或者无效') return 0 @@ -83,21 +92,31 @@ class GnssGetData: #获取GPS模块定位使用卫星数量 def getUsedSateCnt(self): + if self.r is None: + return -1 return self.r.group(0).split(",")[7] #获取GPS模块定位可见卫星数量 def getViewedSateCnt(self): + if self.r2 is None: + return -1 return self.r2.group(0).split(",")[3] #获取GPS模块定位方位角 范围:0~359。以真北为参考平面。 def getCourse(self): + if self.r2 is None: + return -1 return self.r2.group(0).split(",")[6] #获取GPS模块对地速度(单位:KM/h) def getSpeed(self): + if self.r1 is None: + return -1 if self.r1.group(0).split(",")[7] == '': return None else: return float(self.r1.group(0).split(",")[7]) * 1.852 #获取GPS模块定位大地高(单位:米) def getGeodeticHeight(self): + if self.r is None: + return -1 return self.r.group(0).split(",")[9] diff --git a/ports/quectel/core/log.py b/ports/quectel/core/log.py index b9c3880..0aa57d3 100644 --- a/ports/quectel/core/log.py +++ b/ports/quectel/core/log.py @@ -100,6 +100,14 @@ def getLogger(name="root"): _loggers[name] = l return l +def set_output(out): + global _stream + from machine import UART + if isinstance(out, UART): + _stream = out + else: + raise Exception("{} must extend UART".format(out)) + def basicConfig(level=INFO, filename=None, stream=None, format=None): global _level, _stream _level = level diff --git a/ports/quectel/core/ql_fs.py b/ports/quectel/core/ql_fs.py index 73d045c..975fb93 100644 --- a/ports/quectel/core/ql_fs.py +++ b/ports/quectel/core/ql_fs.py @@ -98,7 +98,10 @@ def rmdirs(dir): else: for item in ls: item = dir + '/' + item - rmdirs(item) + if int(uos.stat(item)[0]) & 0x4000: + rmdirs(item) + else: + uos.remove(item) rmdirs(dir) diff --git a/ports/quectel/core/request.py b/ports/quectel/core/request.py index 256c455..9f89cff 100644 --- a/ports/quectel/core/request.py +++ b/ports/quectel/core/request.py @@ -166,7 +166,7 @@ def request(method, url, data=None, json=None, files=None, stream=None, decode=T if headers: if files: boundary = str(utime.time()) - if not (files.get("filepath") and files.get("filepath")): + if not (files.get("filepath") and files.get("filename")): raise ValueError("Missing key parameters 'filepath' and 'filename'") if headers.get('Content-Type') == "multipart/form-data": headers['Content-Type'] = headers['Content-Type'] + '; boundary={}'.format(boundary) @@ -195,11 +195,24 @@ def request(method, url, data=None, json=None, files=None, stream=None, decode=T with open('{}'.format(files.get("filepath")), 'r') as f: content = f.read() if files.get("name") is not None: - datas = '--{0}{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}--{1}'. \ + datas = '--{0}{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ format(boundary, '\r\n', files.get("name"), content) else: - datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}--{1}'. \ + datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}'. \ format(boundary, '\r\n', files.get("filename"), content) + + if files.get("filepath1") is not None: + with open('{}'.format(files.get("filepath1")), 'r') as f1: + content1 = f1.read() + if files.get("name1") is not None: + datas += '{1}Content-Disposition: form-data; {2}{1}{1}{3}{1}--{0}'. \ + format(boundary, '\r\n', files.get("name1"), content1) + else: + if files.get("filename1") is None: + raise ValueError("Missing key parameters 'filename1' ") + datas += '{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}'. \ + format(boundary, '\r\n', files.get("filename1"), content1) + datas += "--\r\n" s.write(b"Content-Length: %d\r\n" % len(datas)) s.write(b"\r\n") s.write(datas) @@ -259,4 +272,4 @@ def patch(url, **kw): def delete(url, **kw): - return request("DELETE", url, **kw) \ No newline at end of file + return request("DELETE", url, **kw) diff --git a/ports/quectel/core/source/audio_audio.c b/ports/quectel/core/source/audio_audio.c index 66cf662..b31341e 100644 --- a/ports/quectel/core/source/audio_audio.c +++ b/ports/quectel/core/source/audio_audio.c @@ -28,11 +28,13 @@ typedef struct _audio_obj_t { #define HELIOS_AUDIO_LOG(fmt, ...) custom_log(audio_audio, fmt, ##__VA_ARGS__) +#define AUDIO_CHANNEL_MAX 3 extern const mp_obj_type_t audio_audio_type; static c_callback_t *g_audio_callback; static c_callback_t *g_audio_speakerpa_callback; static int g_gpio_pa = -1; +static audio_obj_t *audio_obj[AUDIO_CHANNEL_MAX] = {NULL}; STATIC void delay_us(unsigned int us) { @@ -164,7 +166,7 @@ int audio_play_callback(char *ptr, size_t lens, Helios_EnumAudPlayerState state) Helios_Mutex_Unlock(audio.queue_mutex); } - if ((g_audio_callback != NULL) && (audio_state != AUDIO_IDLE)) + if ((g_audio_callback != NULL) /*&& (audio_state != AUDIO_IDLE)*/) { HELIOS_AUDIO_LOG("[Audio] callback start.\r\n"); mp_sched_schedule_ex(g_audio_callback, mp_obj_new_int(audio_event)); @@ -214,8 +216,16 @@ STATIC mp_obj_t audio_make_new(const mp_obj_type_t *type, size_t n_args, size_t if (device < 0 || device > 2) { mp_raise_ValueError("invalid device index, the value of device should be in[0,2]"); } - - audio_obj_t *self = m_new_obj_with_finaliser(audio_obj_t); + + if (!audio_channel_check(device)) + { + mp_raise_msg_varg(&mp_type_ValueError, "The current platform does not support device %d.", device); + } + if(audio_obj[device] == NULL) + { + audio_obj[device] = m_new_obj_with_finaliser(audio_obj_t); + } + audio_obj_t *self = audio_obj[device]; self->base.type = &audio_audio_type; self->device = device; //self->inited = 0; @@ -317,6 +327,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); if (audio.audio_state == AUDIO_IDLE) { + //HELIOS_AUDIO_LOG("----- audio 1-----\r\n"); audio.cur_priority = new_priority; audio.cur_breakin = new_breakin; audio.cur_type = AUDIO_FILE; @@ -334,22 +345,28 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m if (!audio_queue_is_full(&audio.audio_queue[new_priority])) { //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); + HELIOS_AUDIO_LOG("----- audio 2[%d,%d]-----\r\n", new_priority, audio.cur_priority); uint8_t rear = audio.audio_queue[new_priority].rear; uint8_t front = audio.audio_queue[new_priority].front; if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; } else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) { - if (front == 0) + if (front == rear) { - front = QUEUE_SIZE - 1; - } - else - { - front = (front - 1) % QUEUE_SIZE; + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; } } @@ -361,7 +378,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, strlen(new_data)); audio.audio_queue[new_priority].rear = rear; audio.audio_queue[new_priority].front = front; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -369,14 +386,25 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m Helios_Mutex_Unlock(audio.queue_mutex); return mp_obj_new_int(-2); } - - uint8_t audio_msg = AUDIO_STOP_EVENT; - if (Helios_MsgQ_Put(audio.queue_msg, (const void *)&audio_msg, sizeof(uint8_t), HELIOS_NO_WAIT) == -1) + + if (audio.cur_type == AUDIO_TTS) + { + HELIOS_AUDIO_LOG("---- stop tts play. ----\r\n"); + #if defined(PLAT_ASR) + Helios_TTS_Stop(); + #endif + } + else if (audio.cur_type == AUDIO_FILE) + { + HELIOS_AUDIO_LOG("---- stop audio file play. ----\r\n"); + Helios_Audio_FilePlayStop(); + } + else { - HELIOS_AUDIO_LOG("send audio msg failed.\r\n"); + HELIOS_AUDIO_LOG("Unknown audio type.\r\n"); return mp_obj_new_int(-1); } - HELIOS_AUDIO_LOG("send audio stop signal successed.\r\n"); + return mp_obj_new_int(0); } else if (audio.cur_breakin == 0) @@ -385,9 +413,27 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m { //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); uint8_t rear = audio.audio_queue[new_priority].rear; + uint8_t front = audio.audio_queue[new_priority].front; + if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; + } + else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) + { + if (front == rear) + { + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; + } } audio.audio_queue[new_priority].audio_data[rear].audio_type = AUDIO_FILE; @@ -397,7 +443,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m memset(audio.audio_queue[new_priority].audio_data[rear].data, 0, 500); strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, strlen(new_data)); audio.audio_queue[new_priority].rear = rear; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -405,6 +451,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m Helios_Mutex_Unlock(audio.queue_mutex); return mp_obj_new_int(-2); } + return mp_obj_new_int(1); } } @@ -419,16 +466,21 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; } else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) { - if (front == 0) + if (front == rear) { - front = QUEUE_SIZE - 1; - } - else - { - front = (front - 1) % QUEUE_SIZE; + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; } } @@ -440,7 +492,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, strlen(new_data)); audio.audio_queue[new_priority].rear = rear; audio.audio_queue[new_priority].front = front; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -448,6 +500,7 @@ STATIC mp_obj_t helios_play_file_start(size_t n_args, const mp_obj_t *args, mp_m Helios_Mutex_Unlock(audio.queue_mutex); return mp_obj_new_int(-2); } + return mp_obj_new_int(1); } } @@ -694,10 +747,158 @@ STATIC mp_obj_t helios_play_stream_seek(size_t n_args, const mp_obj_t *args, mp_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(helios_play_stream_seek_obj, 1, helios_play_stream_seek); #endif +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) +STATIC const mp_arg_t tone_allowed_args[] = { + { MP_QSTR_tone, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_time, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, +}; + +static Helios_OSTimer_t aud_tone_timer = 0; +static Helios_Thread_t aud_tone_thread_id = 0; +static Helios_MsgQ_t aud_tone_queue_msg = 0; + +static void helios_aud_tone_play_cb(void *argv) { + uint8_t audio_msg = 1; + Helios_MsgQ_Put(aud_tone_queue_msg, (const void *)&audio_msg, sizeof(uint8_t), HELIOS_NO_WAIT); +} + +static void helios_aud_tone_stop_task(void *argv) +{ + HELIOS_AUDIO_LOG("helios_aud_tone_dtmf_stop_task start...\r\n"); + uint8_t audio_msg = 0; + int ret = 0; + while (1) + { + ret = Helios_MsgQ_Get(aud_tone_queue_msg, (void *)&audio_msg, sizeof(uint8_t), HELIOS_WAIT_FOREVER); + if (ret == 0) + { + switch (audio_msg) + { + case 1: + HELIOS_AUDIO_LOG("----Aud Tone Stop---\r\n"); + Helios_Audio_Stop_Tone(); + break; + default: + break; + } + } + } +} + + +//dial tone,ring back tone +STATIC mp_obj_t helios_aud_tone_play(size_t n_args, const mp_obj_t *p_args, mp_map_t *kw_args) +{ + enum { ARG_tone, ARG_time}; + + mp_arg_val_t args[MP_ARRAY_SIZE(tone_allowed_args)]; + mp_arg_parse_all(n_args - 1, p_args + 1, kw_args, + MP_ARRAY_SIZE(tone_allowed_args), tone_allowed_args, args); + + unsigned int time = 0; + int ret = 0; + int tone = 0; + + audio_obj_t *self = MP_OBJ_TO_PTR(p_args[0]); + + tone = args[ARG_tone].u_int; + time = args[ARG_time].u_int; + + if(tone > 22 || tone < 0) + { + mp_raise_ValueError("Parameter error\n"); + return mp_obj_new_int(-1); + } + +#if defined (PLAT_ASR) + if(aud_tone_timer == 0) + { + aud_tone_timer = Helios_OSTimer_Create(); + } + + if(aud_tone_timer == 0) + { + return mp_obj_new_int(-1); + } + + if(0 != time) + { + Helios_OSTimerAttr OSTimerAttr = { + .ms = (uint32_t)time, + .cycle_enable = 0, + .cb = helios_aud_tone_play_cb, + .argv = (void *)self + }; + ret = Helios_OSTimer_Start(aud_tone_timer, &OSTimerAttr); + } + + if(ret) + { + HELIOS_AUDIO_LOG("Timer starte failed\r\n"); + } + HELIOS_AUDIO_LOG("Timer started\r\n"); + + if(ret != 0) + { + Helios_Audio_Stop_Tone(); + if(aud_tone_timer != 0) + { + ret = Helios_OSTimer_Stop(aud_tone_timer); + } + return mp_obj_new_int(-1); + } + + if(0 != time && 0 == aud_tone_thread_id) + { + Helios_ThreadAttr attr = {0}; + attr.name = "aud_tone_stop"; + attr.stack_size = 4096; + attr.priority = 95; + attr.entry = helios_aud_tone_stop_task; + + aud_tone_queue_msg = Helios_MsgQ_Create(10, sizeof(uint8_t)); + if (!aud_tone_queue_msg) + { + return mp_obj_new_int(-1); + } + + aud_tone_thread_id = Helios_Thread_Create(&attr); + if (aud_tone_thread_id == 0) + { + Helios_MsgQ_Delete(aud_tone_queue_msg); + return mp_obj_new_int(-1); + } + } +#endif + + ret = Helios_Audio_Play_Tone(tone, (uint32_t)time); + if(ret != 0) + { + return mp_obj_new_int(-1); + } + + return mp_obj_new_int(0); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_helios_aud_tone_play_obj, 1, helios_aud_tone_play); + +STATIC mp_obj_t helios_aud_tone_play_stop(mp_obj_t self_in) +{ + int ret = Helios_Audio_Stop_Tone(); + if(aud_tone_timer != 0) + ret = Helios_OSTimer_Stop(aud_tone_timer); + return mp_obj_new_int(ret); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_aud_tone_play_stop_obj, helios_aud_tone_play_stop); + +#endif + STATIC mp_obj_t helios_audio___del__(mp_obj_t self_in) { uint8_t i = 0; + audio_obj_t *self = MP_OBJ_TO_PTR(self_in); Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); for (i=0; idevice] = NULL; int ret = Helios_Audio_FilePlayStop(); return mp_obj_new_int(ret); @@ -732,13 +934,14 @@ STATIC const mp_rom_map_elem_t audio_locals_dict_table[] = { #if defined (PLAT_ASR) || defined (PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_set_pa), MP_ROM_PTR(&helios_set_pa_obj) }, { MP_ROM_QSTR(MP_QSTR_setSpeakerpaCallback), MP_ROM_PTR(&helios_set_speakerpa_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_aud_tone_play), MP_ROM_PTR(&mp_helios_aud_tone_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_aud_tone_play_stop), MP_ROM_PTR(&helios_aud_tone_play_stop_obj) }, #endif #if defined (PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_StreamJump), MP_ROM_PTR(&helios_play_stream_jump_obj) }, { MP_ROM_QSTR(MP_QSTR_StreamPause), MP_ROM_PTR(&helios_play_stream_pause_obj) }, { MP_ROM_QSTR(MP_QSTR_StreamContinue), MP_ROM_PTR(&helios_play_stream_continue_obj) }, { MP_ROM_QSTR(MP_QSTR_StreamSeek), MP_ROM_PTR(&helios_play_stream_seek_obj) }, - #endif }; STATIC MP_DEFINE_CONST_DICT(audio_locals_dict, audio_locals_dict_table); diff --git a/ports/quectel/core/source/audio_queue.c b/ports/quectel/core/source/audio_queue.c index 0a598aa..e0e6bb3 100644 --- a/ports/quectel/core/source/audio_queue.c +++ b/ports/quectel/core/source/audio_queue.c @@ -119,7 +119,7 @@ int audio_queue_is_full(AUDIO_QUEUE_T *Q) void helios_audio_play_queue(void) { int i = 0, ret = 0; - + HELIOS_AUDIO_QUEUE_LOG("---- enter queue. ----\r\n"); for (i=QUEUE_NUMS-1; i>=0; i--) { if (!audio_queue_is_empty(&audio.audio_queue[i])) @@ -138,7 +138,7 @@ void helios_audio_play_queue(void) audio.audio_state = AUDIO_PLAYING; Helios_Mutex_Unlock(audio.queue_mutex); - HELIOS_AUDIO_QUEUE_LOG("total nums : %d, data : %s\r\n", nums, data); + HELIOS_AUDIO_QUEUE_LOG("###total nums : %d, pri=%d, data: %s\r\n", nums, audio.cur_priority, data); if (audio_type == AUDIO_TTS) { @@ -189,14 +189,11 @@ void helios_audio_queue_play_task(void *argv) case AUDIO_START_EVENT: break; case AUDIO_STOP_EVENT: - #if defined(PLAT_ASR) - Helios_TTS_Stop(); - #endif - Helios_Audio_FilePlayStop(); - helios_audio_play_queue(); + HELIOS_AUDIO_QUEUE_LOG("----AUDIO_STOP_EVENT---\r\n"); break; case AUDIO_FINISH_EVENT: - HELIOS_AUDIO_QUEUE_LOG("start queue paly...\r\n"); + HELIOS_AUDIO_QUEUE_LOG("----AUDIO_FINISH_EVENT---\r\n"); + //HELIOS_AUDIO_QUEUE_LOG("start queue paly...\r\n"); helios_audio_play_queue(); break; default: diff --git a/ports/quectel/core/source/audio_record.c b/ports/quectel/core/source/audio_record.c index 076b6d9..60c73a3 100644 --- a/ports/quectel/core/source/audio_record.c +++ b/ports/quectel/core/source/audio_record.c @@ -34,6 +34,7 @@ #include "helios_os.h" #include "py/objstr.h" #include "helios_ringbuf.h" +#include "callbackdeal.h" #define RECORD_BUFFER_MAX (uint)10*1024 @@ -98,6 +99,11 @@ STATIC mp_obj_t audio_record_make_new(const mp_obj_type_t *type, size_t n_args, { mp_raise_ValueError("invalid device index, the value of device should be in[0,2]"); } + + if (!audio_channel_check(self->device)) + { + mp_raise_msg_varg(&mp_type_ValueError, "The current platform does not support device %d.", self->device); + } } audio_record_printf("create record obj, n_args = %d, device = %d\r\n", n_args, self->device); @@ -122,12 +128,30 @@ static int helios_file_record_cb(char *p_data, int len, Helios_EnumAudRecordStat { audio_record_printf("[audio_record] callback start.\r\n"); //ret = mp_sched_schedule_ex(g_record_callback, mp_obj_new_int(res)); +#if MICROPY_ENABLE_CALLBACK_DEAL + st_CallBack_AudioRecord *record = malloc(sizeof(st_CallBack_AudioRecord)); + if(NULL != record) { + record->record_type = RECORE_TYPE_FILE; + record->p_data = malloc(strlen(p_data) + 1); + if(NULL == record->p_data) + { + return -1; + } + memcpy(record->p_data, p_data, strlen(p_data)); + record->p_data[strlen(p_data)] = 0; + record->len = len; + record->res = res; + record->callback = *g_record_callback; + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_AUDIO_RECORD, record); + } +#else mp_obj_t audio_cb[3] = { mp_obj_new_str(p_data,strlen(p_data)), mp_obj_new_int(len), mp_obj_new_int(res), }; - ret = mp_sched_schedule_ex(g_record_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(3, audio_cb))); + ret = mp_sched_schedule_ex(g_record_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(3, audio_cb))); +#endif audio_record_printf("[audio_record] callback end.\r\n"); } else @@ -184,7 +208,7 @@ static int check_format(char *path) { } else if(strncmp(st_old, "mp3", 3)==0) { return FORMAT_MP3; } else { - return FORMAT_AMR; + return -3; } } @@ -223,15 +247,26 @@ static int helios_stream_record_cb(char *p_data, int len, Helios_EnumAudRecordSt if(callback_cur == NULL) { return -1; } - char* p_data_buf = "stream"; if(res == HELIOS_AUD_RECORD_CLOSE) send_len = pcm_data_size; + #if MICROPY_ENABLE_CALLBACK_DEAL + st_CallBack_AudioRecord *record = malloc(sizeof(st_CallBack_AudioRecord)); + if(NULL != record) { + record->record_type = RECORE_TYPE_STREAM; + record->p_data = "stream"; + record->len = send_len; + record->res = res; + record->callback = *callback_cur; + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_AUDIO_RECORD, record); + } + #else + char* p_data_buf = "stream"; mp_obj_t audio_cb[3] = { mp_obj_new_str(p_data_buf,strlen(p_data_buf)), mp_obj_new_int(send_len), mp_obj_new_int(res), }; - mp_sched_schedule_ex(callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_list(3, audio_cb))); + #endif } return 0; @@ -283,7 +318,7 @@ STATIC mp_obj_t helios_audio_record_stream_start(size_t n_args, const mp_obj_t * callback_cur = self->callback; - if(format > HELIOS_AUDIO_FORMAT_MAX || !(samplerate == 8000 || samplerate == 16000)) { + if((format != HELIOS_AUDIO_FORMAT_AMRNB && format != HELIOS_AUDIO_FORMAT_AMRWB) || !(samplerate == 8000 || samplerate == 16000)) { mp_raise_ValueError("Parameter error\n"); return mp_obj_new_int(-1); } @@ -767,6 +802,36 @@ STATIC mp_obj_t helios_audio_record_gain(size_t n_args, const mp_obj_t *args) return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_helios_record_file_gain_obj,3,3, helios_audio_record_gain); + +/*=============================================================================*/ +/* FUNCTION: helios_amrenc_dtx_enable */ +/*=============================================================================*/ +/*!@brief : amr record dtx enable. + * @param[in] : + * @param[out] : + * @return : + */ +/*=============================================================================*/ +STATIC mp_obj_t helios_amrenc_dtx_enable(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + int enable = 0; + if(1 == n_args) { + Helios_Audio_AmrEnc_Dtx_Enable(&enable, 1); + return mp_obj_new_int(enable); + } + + int on_off = mp_obj_get_int(args[1]); + if (on_off < 0 || on_off > 1) + { + mp_raise_ValueError("invalid value, on_off must be 0 or 1."); + return mp_obj_new_int(-1); + } + + Helios_Audio_AmrEnc_Dtx_Enable(&on_off, 0); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(helios_amrenc_dtx_enable_obj, 1, 2, helios_amrenc_dtx_enable); #endif static int play_callback(char *p_data, int len, Helios_EnumAudPlayerState state) @@ -838,7 +903,10 @@ STATIC mp_obj_t helios_audio_deinit(mp_obj_t self_in) record_state = 0; ret = Helios_Audio_FileRecordStop(); ret = Helios_Audio_StreamRecordStop(); - +#if defined(PLAT_ASR) + int enable = 0; + Helios_Audio_AmrEnc_Dtx_Enable(&enable, 0); +#endif return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_record_deinit_obj, helios_audio_deinit); @@ -863,6 +931,7 @@ STATIC const mp_rom_map_elem_t audio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_WAV), MP_ROM_INT(HELIOS_AUDIO_FORMAT_WAVPCM) }, { MP_ROM_QSTR(MP_QSTR_AMRNB), MP_ROM_INT(HELIOS_AUDIO_FORMAT_AMRNB) }, { MP_ROM_QSTR(MP_QSTR_AMRWB), MP_ROM_INT(HELIOS_AUDIO_FORMAT_AMRWB) }, + { MP_ROM_QSTR(MP_QSTR_amrEncDtx_enable), MP_ROM_PTR(&helios_amrenc_dtx_enable_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&mp_helios_record_file_play_obj) }, #ifdef PLAT_Unisoc diff --git a/ports/quectel/core/source/audio_tts.c b/ports/quectel/core/source/audio_tts.c index 1041813..ce11c16 100644 --- a/ports/quectel/core/source/audio_tts.c +++ b/ports/quectel/core/source/audio_tts.c @@ -114,9 +114,9 @@ void app_helios_tts_callback(Helios_TTSENvent event) case HELIOS_TTS_EVT_DEINIT: case HELIOS_TTS_EVT_PLAY_STOP: case HELIOS_TTS_EVT_PLAY_FAILED: - Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); - audio.audio_state = AUDIO_IDLE; - Helios_Mutex_Unlock(audio.queue_mutex); + //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); + //audio.audio_state = AUDIO_IDLE; + //Helios_Mutex_Unlock(audio.queue_mutex); break; default: break; @@ -136,6 +136,11 @@ STATIC mp_obj_t audio_tts_make_new(const mp_obj_type_t *type, if (device < 0 || device > 2) { mp_raise_ValueError("invalid device index, the value of device should be in[0,2]"); } + + if (!audio_channel_check(device)) + { + mp_raise_msg_varg(&mp_type_ValueError, "The current platform does not support device %d.", device); + } Helios_Audio_SetAudioChannle(device); @@ -270,6 +275,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); if (audio.audio_state == AUDIO_IDLE) { + //HELIOS_TTS_LOG("----- TTS 1-----\r\n"); audio.cur_priority = new_priority; audio.cur_breakin = new_breakin; audio.cur_type = AUDIO_TTS; @@ -287,24 +293,31 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw if (!audio_queue_is_full(&audio.audio_queue[new_priority])) { //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); + HELIOS_TTS_LOG("----- [TTS-1][%d,%d]-----\r\n", new_priority, audio.cur_priority); uint8_t rear = audio.audio_queue[new_priority].rear; uint8_t front = audio.audio_queue[new_priority].front; - + //HELIOS_TTS_LOG("[TTS-1][1] front=%d, rear=%d \r\n", front, rear); if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { - rear = (rear + 1) % QUEUE_SIZE; + rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; } else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) { - if (front == 0) - { - front = QUEUE_SIZE - 1; - } - else + if (front == rear) { - front = (front - 1) % QUEUE_SIZE; + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; } } + HELIOS_TTS_LOG("[TTS-1][2] front=%d, rear=%d \r\n", front, rear); audio.audio_queue[new_priority].audio_data[rear].audio_type = AUDIO_TTS; audio.audio_queue[new_priority].audio_data[rear].priority = new_priority; @@ -314,7 +327,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw strncpy(audio.audio_queue[new_priority].audio_data[rear].data, bufinfo.buf, bufinfo.len); audio.audio_queue[new_priority].rear = rear; audio.audio_queue[new_priority].front = front; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -323,13 +336,24 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw return mp_obj_new_int(-2); } - uint8_t audio_msg = AUDIO_STOP_EVENT; - if (Helios_MsgQ_Put(audio.queue_msg, (const void *)&audio_msg, sizeof(uint8_t), HELIOS_NO_WAIT) == -1) + if (audio.cur_type == AUDIO_TTS) + { + HELIOS_TTS_LOG("---- stop tts play. ----\r\n"); + #if defined(PLAT_ASR) + Helios_TTS_Stop(); + #endif + } + else if (audio.cur_type == AUDIO_FILE) { - HELIOS_TTS_LOG("send audio msg failed[%u].\r\n", audio_msg); + HELIOS_TTS_LOG("---- stop audio file play. ----\r\n"); + Helios_Audio_FilePlayStop(); + } + else + { + HELIOS_TTS_LOG("Unknown audio type.\r\n"); return mp_obj_new_int(-1); } - HELIOS_TTS_LOG("send audio stop signal successed[%u].\r\n", audio_msg); + return mp_obj_new_int(0);//forrest.liu@20210427 reopen for TTS and Audio_file playing break function correctly } @@ -339,10 +363,30 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw { //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); uint8_t rear = audio.audio_queue[new_priority].rear; + uint8_t front = audio.audio_queue[new_priority].front; + + //HELIOS_TTS_LOG("[TTS-2][1] front=%d, rear=%d \r\n", front, rear); if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; } + else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) + { + if (front == rear) + { + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; + } + } + HELIOS_TTS_LOG("[TTS-2][2] front=%d, rear=%d \r\n", front, rear); audio.audio_queue[new_priority].audio_data[rear].audio_type = AUDIO_TTS; audio.audio_queue[new_priority].audio_data[rear].priority = new_priority; @@ -351,7 +395,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw memset(audio.audio_queue[new_priority].audio_data[rear].data, 0, 500); strncpy(audio.audio_queue[new_priority].audio_data[rear].data, bufinfo.buf, bufinfo.len); audio.audio_queue[new_priority].rear = rear; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -359,6 +403,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw Helios_Mutex_Unlock(audio.queue_mutex); return mp_obj_new_int(-2); } + return mp_obj_new_int(1); } } @@ -369,23 +414,29 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw //Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); uint8_t rear = audio.audio_queue[new_priority].rear; uint8_t front = audio.audio_queue[new_priority].front; - + HELIOS_TTS_LOG("----- [TTS-3][%d,%d]-----\r\n", new_priority, audio.cur_priority); + //HELIOS_TTS_LOG("[TTS-3][1] front=%d, rear=%d \r\n", front, rear); if (audio.audio_queue[new_priority].audio_data[rear].breakin == 0) { rear = (rear + 1) % QUEUE_SIZE; + audio.total_nums++; } else if (audio.audio_queue[new_priority].audio_data[rear].breakin == 1) { - if (front == 0) - { - front = QUEUE_SIZE - 1; - } - else + if (front == rear) { - front = (front - 1) % QUEUE_SIZE; + if (front == 0) + { + front = QUEUE_SIZE - 1; + } + else + { + front = (front - 1) % QUEUE_SIZE; + } + audio.total_nums++; } } - + HELIOS_TTS_LOG("[TTS-3][2] front=%d, rear=%d \r\n", front, rear); audio.audio_queue[new_priority].audio_data[rear].audio_type = AUDIO_TTS; audio.audio_queue[new_priority].audio_data[rear].priority = new_priority; audio.audio_queue[new_priority].audio_data[rear].breakin = new_breakin; @@ -394,7 +445,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw strncpy(audio.audio_queue[new_priority].audio_data[rear].data, bufinfo.buf, bufinfo.len); audio.audio_queue[new_priority].rear = rear; audio.audio_queue[new_priority].front = front; - audio.total_nums++; + Helios_Mutex_Unlock(audio.queue_mutex); } else @@ -402,6 +453,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw Helios_Mutex_Unlock(audio.queue_mutex); return mp_obj_new_int(-2); } + return mp_obj_new_int(1); } } diff --git a/ports/quectel/core/source/callbackdeal.c b/ports/quectel/core/source/callbackdeal.c new file mode 100644 index 0000000..4c9cf75 --- /dev/null +++ b/ports/quectel/core/source/callbackdeal.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + ****************************************************************************** + * @file callbackdeal.c + * @author freddy.li + * @version V1.0.0 + * @date 2021/11/25 + * @brief xxx + ****************************************************************************** + */ +#include +#include +#include "helios_os.h" +#include "stackctrl.h" +#include "py/runtime.h" +#include "callbackdeal.h" + +#if MICROPY_ENABLE_CALLBACK_DEAL + +#define QPY_CALLBACK_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) +#define QPY_CALLBACK_DEAL_THREAD_STACK_SIZE (16 *1024) +static Helios_MsgQ_t qpy_callback_deal_queue = 0; +Helios_Thread_t qpy_callback_deal_task_ref = 0; + +typedef struct _callback_deal_thread_entry_args_t { + mp_obj_dict_t *dict_locals; + mp_obj_dict_t *dict_globals; +} callback_deal_thread_entry_args_t; + + +/* + * Create a task&queue that handles callback tasks exclusively + */ +void qpy_callback_deal_thread(void * args_in); +void qpy_callback_deal_init(void) +{ + qpy_callback_deal_queue = Helios_MsgQ_Create(QPY_CALLBACK_DEAL_MSG_MAX_NUM, sizeof(st_CallBack_Deal)); + // create thread + callback_deal_thread_entry_args_t *th_args; + th_args = m_new_obj(callback_deal_thread_entry_args_t); + // pass our locals and globals into the new thread + th_args->dict_locals = mp_locals_get(); + th_args->dict_globals = mp_globals_get(); + + Helios_ThreadAttr ThreadAttr = { + .name = "cb_deal", + .stack_size = QPY_CALLBACK_DEAL_THREAD_STACK_SIZE, + .priority = (MP_THREAD_PRIORITY - 1), + .entry = (void*)qpy_callback_deal_thread, + .argv = (void*)th_args + }; + qpy_callback_deal_task_ref = Helios_Thread_Create(&ThreadAttr); + //add thread to python_thread link list, the thread is automatically deleted after the VM restarts. + mp_new_thread_add((uint32_t)qpy_callback_deal_task_ref, QPY_CALLBACK_DEAL_THREAD_STACK_SIZE); +} + +/* + * delete callback_deal task&queue + */ +void qpy_callback_deal_deinit(void) +{ + Helios_MsgQ_Delete(qpy_callback_deal_queue); qpy_callback_deal_queue = (Helios_MsgQ_t)0; + //Just set it to null and the thread will be deleted automatically when the vm restarts + qpy_callback_deal_task_ref = (Helios_Thread_t)0; +} + + +//Added by Freddy @20211124 发送消息至deal task的queue +void qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg) +{ + if((Helios_MsgQ_t)0 != qpy_callback_deal_queue) + { + st_CallBack_Deal cb_msg = {0}; + cb_msg.callback_type_id = id; + cb_msg.msg = msg; + Helios_MsgQ_Put(qpy_callback_deal_queue, (void*)(&cb_msg), sizeof(st_CallBack_Deal), HELIOS_NO_WAIT); + } +} + +/* + * Resolve the crash issue when non-Python threads apply for GC memory and throw exceptions when memory application fails + */ +void qpy_callback_deal_thread(void * args_in) +{ + callback_deal_thread_entry_args_t *args = (callback_deal_thread_entry_args_t *)args_in; + mp_state_thread_t ts; + mp_thread_set_state(&ts); + st_CallBack_Deal msg = {0}; + + mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan + mp_stack_set_limit(QPY_CALLBACK_DEAL_THREAD_STACK_SIZE); + + #if MICROPY_ENABLE_PYSTACK + // TODO threading and pystack is not fully supported, for now just make a small stack + mp_obj_t mini_pystack[128]; + mp_pystack_init(mini_pystack, &mini_pystack[128]); + #endif + + // set locals and globals from the calling context + mp_locals_set(args->dict_locals); + mp_globals_set(args->dict_globals); + m_del_obj(callback_deal_thread_entry_args_t, args); + + // signal that we are set up and running + mp_thread_start(); + + MP_THREAD_GIL_ENTER(); + + while(1) + { + nlr_buf_t nlr; + mp_obj_t arg = NULL; + if (nlr_push(&nlr) == 0) + { + MP_THREAD_GIL_EXIT(); + //Wait for an underlying callback to process the message + int ret = Helios_MsgQ_Get(qpy_callback_deal_queue, (void*)&msg, sizeof(msg), HELIOS_WAIT_FOREVER); + MP_THREAD_GIL_ENTER(); + if(ret != 0) + { + nlr_pop(); + continue; + } + //Each is processed according to the callback ID + switch(msg.callback_type_id) + { + case CALLBACK_TYPE_ID_EXTINT: + { + st_CallBack_Extint *cb_msg = (st_CallBack_Extint *)msg.msg; + mp_obj_t extint_list[2] = { + mp_obj_new_int(cb_msg->pin_no), + mp_obj_new_int(cb_msg->edge), + }; + arg = mp_obj_new_list(2, extint_list); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + case CALLBACK_TYPE_ID_AUDIO_RECORD: + { + st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; + mp_obj_t audio_cb[3] = { + mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), + mp_obj_new_int(cb_msg->len), + mp_obj_new_int(cb_msg->res), + }; + if(RECORE_TYPE_FILE == cb_msg->record_type && NULL != cb_msg->p_data) { + free(cb_msg->p_data); + } + arg = mp_obj_new_list(3, audio_cb); + mp_sched_schedule_ex(&cb_msg->callback, arg); + #if defined(PLAT_Unisoc) + if (RECORE_TYPE_STREAM == cb_msg->record_type) + { + Helios_msleep(10); + } + #endif + } + break; + case CALLBACK_TYPE_ID_VOICECALL_RECORD: + { + st_CallBack_AudioRecord *cb_msg = (st_CallBack_AudioRecord *)msg.msg; + mp_obj_t audio_cb[3] = { + mp_obj_new_str(cb_msg->p_data,strlen(cb_msg->p_data)), + mp_obj_new_int(cb_msg->len), + mp_obj_new_int(cb_msg->res), + }; + + arg = mp_obj_new_list(3, audio_cb); + mp_sched_schedule_ex(&cb_msg->callback, arg); + } + break; + case CALLBACK_TYPE_ID_NONE: + default: + break; + } + + MICROPY_EVENT_POLL_HOOK + + if(msg.msg) { + free(msg.msg); + } + memset(&msg, 0, sizeof(st_CallBack_Deal)); + nlr_pop(); + } + else + { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + } +} + +#endif diff --git a/ports/quectel/core/source/callbackdeal.h b/ports/quectel/core/source/callbackdeal.h new file mode 100644 index 0000000..edd2c4e --- /dev/null +++ b/ports/quectel/core/source/callbackdeal.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// empty file +#ifndef __CALLBACKDEAL_H__ +#define __CALLBACKDEAL_H__ + +#include "py/runtime.h" + +#if MICROPY_ENABLE_CALLBACK_DEAL +typedef struct{ + uint8_t callback_type_id; + void *msg; +}st_CallBack_Deal; + +enum { + CALLBACK_TYPE_ID_NONE, + CALLBACK_TYPE_ID_EXTINT, + CALLBACK_TYPE_ID_OSTIMER, + CALLBACK_TYPE_ID_HWTIMER, + CALLBACK_TYPE_ID_AUDIO_AUDIO, + CALLBACK_TYPE_ID_AUDIO_RECORD, + CALLBACK_TYPE_ID_AUDIO_TTS, + CALLBACK_TYPE_ID_CAM_CAP, + CALLBACK_TYPE_ID_VOICECALL_RECORD, +}; + +typedef struct{ + uint8_t pin_no; + uint8_t edge; + c_callback_t callback; +}st_CallBack_Extint; + +enum {RECORE_TYPE_FILE,RECORE_TYPE_STREAM}; +typedef struct{ + int record_type; + char * p_data; + int len; + int res; + c_callback_t callback; +}st_CallBack_AudioRecord; + +void qpy_callback_deal_init(void); +void qpy_callback_deal_deinit(void); +void qpy_send_msg_to_callback_deal_thread(uint8_t id, void *msg); + +#endif +#endif //__CALLBACKDEAL_H__ \ No newline at end of file diff --git a/ports/quectel/core/source/camera_capture.c b/ports/quectel/core/source/camera_capture.c index aa54a42..900718e 100644 --- a/ports/quectel/core/source/camera_capture.c +++ b/ports/quectel/core/source/camera_capture.c @@ -67,13 +67,15 @@ typedef struct _preview_obj_t { unsigned char perview; unsigned char decbufcnt; c_callback_t *callback; - //int inited; + bool is_open; } preview_obj_t; static preview_obj_t *capture_obj = NULL; static Helios_CAMConfig camconfig = {0}; +#define CHECK_CMAERA_IS_OPEN (capture_obj->is_open ? TRUE:FALSE) + static unsigned short *g_lcd_buffer = NULL; @@ -185,6 +187,7 @@ STATIC mp_obj_t caputre_make_new(const mp_obj_type_t *type, size_t n_args, size_ self->lcd_h = lcdpreheight; self->lcd_w = lcdprewidth; self->prebufcnt = prebufcnt; + self->is_open = FALSE; camconfig.model = model; camconfig.camheight = camheight; @@ -207,8 +210,12 @@ STATIC mp_obj_t caputre_make_new(const mp_obj_type_t *type, size_t n_args, size_ STATIC mp_obj_t camera_open(mp_obj_t self_in) { + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); CAPTURE_LOG("open %d,%d,%d,%d,%d\n",camconfig.camheight,camconfig.camwidth,camconfig.lcdpreheight,camconfig.lcdprewidth,camconfig.prebufcnt); int error = Helios_camera_open(&camconfig);//ql_start_preview(data); + if(0 == error) { + self->is_open = TRUE; + } return mp_obj_new_int(error); } @@ -216,8 +223,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture_open_obj, camera_open); STATIC mp_obj_t camera_close(mp_obj_t self_in) { - + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); int error = Helios_camera_close(); + if(0 == error) { + self->is_open = FALSE; + } return mp_obj_new_int(error); } @@ -240,6 +250,11 @@ STATIC mp_obj_t camera_capture_start(size_t n_args, const mp_obj_t *pos_args, mp MP_ARRAY_SIZE(capture_open_allowed_args), capture_open_allowed_args, args); char *picname = NULL; + + if(!CHECK_CMAERA_IS_OPEN) { + mp_raise_ValueError("camera is not open"); + } + if (mp_obj_is_str(args[ARG_picture_name].u_obj)) { picname = (char*)mp_obj_str_get_str(args[ARG_picture_name].u_obj); } diff --git a/ports/quectel/core/source/devreport.c b/ports/quectel/core/source/devreport.c new file mode 100644 index 0000000..b532756 --- /dev/null +++ b/ports/quectel/core/source/devreport.c @@ -0,0 +1,532 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "py/runtime.h" +#if MICROPY_ENABLE_DEVICE_REPORT + +#include "helios.h" +#include "helios_debug.h" +#include "helios_os.h" +#include "helios_dev.h" +#include "helios_nw.h" +#include "helios_sim.h" +#if !defined (PLAT_Qualcomm) +#include "sockets.h" +#include "netif.h" +#include "netdb.h" +#include "inet.h" +#endif +#include "helios_datacall.h" + +#include + +#define DEVREPORT_STACK_SIZE 3 +#define app_debug(fmt, ...) custom_log(DEVREPORT, fmt, ##__VA_ARGS__) + + +#define STATION_CODE_CN "460" // 国内识别码 + +#define DEVICE_INFO_REPORT_SERVER_CN "iot-south.quectel.com" // 平台地址 +#define DEVICE_INFO_REPORT_PORT 6789 // 平台端口号 + +#define DEVICE_REPORT_TRY_CNT 3 // 上报重试次数 +#define DEVICE_MSG_HEAD 0x8001 // 上报数据定义头 + +// 失败次数计数 +static int g_failure_cnt = 0; +// 轮询等待时间,单位秒 +static int g_loop_sleep_sec = 5; + + +typedef enum { + SSS_DEVICE_IMSI = 0, // 读取imsi状态 + SSS_DEVICE_IMEI, // 读取imei状态 + SSS_DEVICE_NETWORK_CHECK, // 检查网络状态 + SSS_DEVICE_REPORT, // 设备信息上报 + SSS_DEVICE_STATION_END // 状态结束 +} REPORT_STATUS; + +struct device_config { + char imei[32]; + char imsi[32]; + int profile_idx; + REPORT_STATUS status; +}; +struct device_config devConfig; + +#pragma pack(1) +struct report_msg { + unsigned short head; + unsigned short len; + unsigned char value[32]; +}; +#pragma pack() + + +#define DR_HASH256_ENABLE 1 +#if DR_HASH256_ENABLE +typedef struct { + uint8_t buf[64]; + uint32_t hash[8]; + uint32_t bits[2]; + uint32_t len; +} dr_sha256_context; + + +#define FN_ inline static + +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#ifdef MINIMIZE_STACK_IMPACT +static uint32_t W[64]; +#endif + +/* -------------------------------------------------------------------------- */ +FN_ uint8_t _shb(uint32_t x, uint32_t n) +{ + return ( (x >> (n & 31)) & 0xff ); +} /* _shb */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _shw(uint32_t x, uint32_t n) +{ + return ( (x << (n & 31)) & 0xffffffff ); +} /* _shw */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _r(uint32_t x, uint8_t n) +{ + return ( (x >> n) | _shw(x, 32 - n) ); +} /* _r */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _Ch(uint32_t x, uint32_t y, uint32_t z) +{ + return ( (x & y) ^ ((~x) & z) ); +} /* _Ch */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _Ma(uint32_t x, uint32_t y, uint32_t z) +{ + return ( (x & y) ^ (x & z) ^ (y & z) ); +} /* _Ma */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _S0(uint32_t x) +{ + return ( _r(x, 2) ^ _r(x, 13) ^ _r(x, 22) ); +} /* _S0 */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _S1(uint32_t x) +{ + return ( _r(x, 6) ^ _r(x, 11) ^ _r(x, 25) ); +} /* _S1 */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _G0(uint32_t x) +{ + return ( _r(x, 7) ^ _r(x, 18) ^ (x >> 3) ); +} /* _G0 */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _G1(uint32_t x) +{ + return ( _r(x, 17) ^ _r(x, 19) ^ (x >> 10) ); +} /* _G1 */ + +/* -------------------------------------------------------------------------- */ +FN_ uint32_t _word(uint8_t *c) +{ + return ( _shw(c[0], 24) | _shw(c[1], 16) | _shw(c[2], 8) | (c[3]) ); +} /* _word */ + +/* -------------------------------------------------------------------------- */ +FN_ void _addbits(dr_sha256_context *ctx, uint32_t n) +{ + if ( ctx->bits[0] > (0xffffffff - n) ) + ctx->bits[1] = (ctx->bits[1] + 1) & 0xFFFFFFFF; + ctx->bits[0] = (ctx->bits[0] + n) & 0xFFFFFFFF; +} /* _addbits */ + +/* -------------------------------------------------------------------------- */ +static void _hash(dr_sha256_context *ctx) +{ + register uint32_t a, b, c, d, e, f, g, h, i; + uint32_t t[2]; +#ifndef MINIMIZE_STACK_IMPACT + uint32_t W[64]; +#endif + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + f = ctx->hash[5]; + g = ctx->hash[6]; + h = ctx->hash[7]; + + for (i = 0; i < 64; i++) { + if ( i < 16 ) + W[i] = _word(&ctx->buf[_shw(i, 2)]); + else + W[i] = _G1(W[i - 2]) + W[i - 7] + _G0(W[i - 15]) + W[i - 16]; + + t[0] = h + _S1(e) + _Ch(e, f, g) + K[i] + W[i]; + t[1] = _S0(a) + _Ma(a, b, c); + h = g; + g = f; + f = e; + e = d + t[0]; + d = c; + c = b; + b = a; + a = t[0] + t[1]; + } + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; + ctx->hash[5] += f; + ctx->hash[6] += g; + ctx->hash[7] += h; +} /* _hash */ + +/* -------------------------------------------------------------------------- */ +static void dr_sha256_init(dr_sha256_context *ctx) +{ + if ( ctx != NULL ) { + ctx->bits[0] = ctx->bits[1] = 0; + ctx->len = 0; + ctx->hash[0] = 0x6a09e667; + ctx->hash[1] = 0xbb67ae85; + ctx->hash[2] = 0x3c6ef372; + ctx->hash[3] = 0xa54ff53a; + ctx->hash[4] = 0x510e527f; + ctx->hash[5] = 0x9b05688c; + ctx->hash[6] = 0x1f83d9ab; + ctx->hash[7] = 0x5be0cd19; + } +} /* sha256_init */ + +/* -------------------------------------------------------------------------- */ +static void dr_sha256_hash(dr_sha256_context *ctx, const void *data, size_t len) +{ + register size_t i; + const uint8_t *bytes = (const uint8_t *)data; + + if ( (ctx != NULL) && (bytes != NULL) ) + for (i = 0; i < len; i++) { + ctx->buf[ctx->len] = bytes[i]; + ctx->len++; + if (ctx->len == sizeof(ctx->buf) ) { + _hash(ctx); + _addbits(ctx, sizeof(ctx->buf) * 8); + ctx->len = 0; + } + } +} /* sha256_hash */ + +/* -------------------------------------------------------------------------- */ +static void dr_sha256_done(dr_sha256_context *ctx, uint8_t *hash) +{ + register uint32_t i, j; + + if ( ctx != NULL ) { + j = ctx->len % sizeof(ctx->buf); + ctx->buf[j] = 0x80; + for (i = j + 1; i < sizeof(ctx->buf); i++) + ctx->buf[i] = 0x00; + + if ( ctx->len > 55 ) { + _hash(ctx); + for (j = 0; j < sizeof(ctx->buf); j++) + ctx->buf[j] = 0x00; + } + + _addbits(ctx, ctx->len * 8); + ctx->buf[63] = _shb(ctx->bits[0], 0); + ctx->buf[62] = _shb(ctx->bits[0], 8); + ctx->buf[61] = _shb(ctx->bits[0], 16); + ctx->buf[60] = _shb(ctx->bits[0], 24); + ctx->buf[59] = _shb(ctx->bits[1], 0); + ctx->buf[58] = _shb(ctx->bits[1], 8); + ctx->buf[57] = _shb(ctx->bits[1], 16); + ctx->buf[56] = _shb(ctx->bits[1], 24); + _hash(ctx); + + if ( hash != NULL ) + for (i = 0, j = 24; i < 4; i++, j -= 8) { + hash[i ] = _shb(ctx->hash[0], j); + hash[i + 4] = _shb(ctx->hash[1], j); + hash[i + 8] = _shb(ctx->hash[2], j); + hash[i + 12] = _shb(ctx->hash[3], j); + hash[i + 16] = _shb(ctx->hash[4], j); + hash[i + 20] = _shb(ctx->hash[5], j); + hash[i + 24] = _shb(ctx->hash[6], j); + hash[i + 28] = _shb(ctx->hash[7], j); + } + } +} /* sha256_done */ +// sha256算法实现 +static void dr_sha256(const void *data, size_t len, uint8_t *hash) +{ + dr_sha256_context ctx; + + dr_sha256_init(&ctx); + dr_sha256_hash(&ctx, data, len); + dr_sha256_done(&ctx, hash); +} /* sha256 */ +#endif +// 建立udp连接,上报数据 +static int dr_udp_client_send(int cid, const char *host, unsigned char *sendData, int sendLength) +{ + int ret = 0; + struct netif *netif_cfg = NULL; + struct sockaddr_in server_addr; + struct addrinfo hints; + struct sockaddr_in * sin_pres; + struct addrinfo *dev_pres = NULL; + int sockfd; + char recvUdpData[128]; + + socklen_t len; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + // 域名解析 + ret = getaddrinfo_with_pcid(host, NULL, &hints, &dev_pres, cid); + if ( ret != 0 || dev_pres == NULL ) { + return -1; + } +#if !defined (PLAT_Qualcomm) + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +#else + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); +#endif + if(sockfd < 0) { + freeaddrinfo(dev_pres); + return -1; + } + struct timeval tv; + tv.tv_sec = 3; + tv.tv_usec = 0; + // 设置接收超时,3s + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); +#if defined(PLAT_RDA) + int pdp = 1; + netif_cfg = netif_get_by_cid(pdp); +#else + int pdp = Helios_DataCall_GetCurrentPDP(); +#if defined (PLAT_Unisoc) + netif_cfg = netif_get_by_cid(pdp); +#elif defined (PLAT_ASR) + netif_cfg = netif_get_by_cid(pdp - 1); +#elif defined (PLAT_Qualcomm) + netif_cfg = NULL; + (void)pdp; +#endif +#endif +#if !defined (PLAT_Qualcomm) + struct sockaddr_in local4; + if(netif_cfg) { + local4.sin_family = AF_INET; + local4.sin_port = DEVICE_INFO_REPORT_PORT; +#if defined (PLAT_Unisoc) || defined(PLAT_RDA) + local4.sin_addr.s_addr = netif_cfg->ip_addr.u_addr.ip4.addr; +#elif defined (PLAT_ASR) + local4.sin_addr.s_addr = netif_cfg->ip_addr.addr; +#endif + if(bind(sockfd,(struct sockaddr *)&local4,sizeof(struct sockaddr))) { + freeaddrinfo(dev_pres); + return -1; + } + } +#endif + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(DEVICE_INFO_REPORT_PORT); + sin_pres = (struct sockaddr_in *)dev_pres->ai_addr; + server_addr.sin_addr = sin_pres->sin_addr; + len = sizeof(server_addr); + ret = sendto(sockfd, sendData, sendLength, 0, (struct sockaddr *)(&server_addr), len); + if(ret < 0) { + close(sockfd); + freeaddrinfo(dev_pres); + return -1; + } + ret = recvfrom(sockfd, recvUdpData, 100, 0, (struct sockaddr *)&server_addr, &len); + if( ret != 5 || recvUdpData[4] != 0x30 ) { + close(sockfd); + freeaddrinfo(dev_pres); + return -1; + } + close(sockfd); + freeaddrinfo(dev_pres); + return 0; +} +// 大端对齐转换为小端对齐 +static short _big2littles(short be) +{ + short swapped = (0xff00 & be << 8) | (0x00ff & be >> 8); + return swapped; +} +// 上报设备信息 +static void dr_report_dev_info(int profile_idx) +{ + struct report_msg msg; + msg.head = DEVICE_MSG_HEAD; + int data_length = 0; + int i = 0; + //char sendhex[256] = {0}; + int ret = 0; +#if DR_HASH256_ENABLE + unsigned char imei_hash[32] = {0}; + dr_sha256(devConfig.imei, strlen(devConfig.imei), imei_hash); + data_length = 32; + msg.len = data_length; + memcpy(msg.value, imei_hash, msg.len); +#else + data_length = strlen(devConfig.imei); + msg.len = data_length; + memcpy(msg.value, devConfig.imei, data_length); +#endif + msg.head = _big2littles(msg.head); + msg.len = _big2littles(msg.len); + for( i = 0; i < DEVICE_REPORT_TRY_CNT; i++ ) { + ret = dr_udp_client_send(profile_idx, DEVICE_INFO_REPORT_SERVER_CN, (unsigned char *)&msg, data_length+4); + if( ret == 0 ) { + break; + } + Helios_sleep(1); + } + devConfig.status = SSS_DEVICE_STATION_END; +} +// 读取设备imsi +static void dr_read_device_imsi() +{ + int ret = 0; + int i = 0; + for( i = 0; i < 2; i++ ) { + ret = Helios_SIM_GetIMSI(i, devConfig.imsi, sizeof(devConfig.imsi)-1); +#if !defined (PLAT_Qualcomm) + if( ret == 0 ) { +#else + if( ret == 0 && strncmp(devConfig.imsi, "NULL", 4)) { +#endif + if( !strncmp(devConfig.imsi, STATION_CODE_CN, 3) ) { + devConfig.status = SSS_DEVICE_IMEI; + } else { + devConfig.status = SSS_DEVICE_STATION_END; + } + g_failure_cnt = 0; + g_loop_sleep_sec = 5; + return; + } + } + g_failure_cnt += 1; + if( g_failure_cnt == 6 ) g_loop_sleep_sec = 30; + Helios_sleep(g_loop_sleep_sec); +} +// 读取设备imei +static void dr_read_device_imei() +{ + int ret = 0; + ret = Helios_Dev_GetIMEI(devConfig.imei, sizeof(devConfig.imei)-1); + if( ret != 0 ) { + devConfig.status = SSS_DEVICE_STATION_END; + return; + } + devConfig.status = SSS_DEVICE_NETWORK_CHECK; +} +// 检查网络连接 +static void dr_network_check() +{ + int i; + int ret = 0; + Helios_DataCallInfoStruct info; + memset(&info, 0x00, sizeof(info)); + for(i = (int)HELIOS_PROFILE_IDX_MIN; i < (int)HELIOS_PROFILE_IDX_MAX + 1; i++) { + ret = Helios_DataCall_GetInfo(i, 0, &info); + if( ret == 0 ) { + if( info.v4.state == 1 && info.v4.addr.ip.s_addr != 0 ) { + devConfig.profile_idx = info.profile_idx; + devConfig.status = SSS_DEVICE_REPORT; + return; + } + } + } + g_failure_cnt += 1; + if( g_failure_cnt == 6 ) g_loop_sleep_sec = 30; + Helios_sleep(g_loop_sleep_sec); +} + +/* +* 设备信息上报状态机 +* 读取imsi-> 读取imei -> 检查网络状态 -> 设备信息上报 -> 结束 +*/ +static void devReport(void *argv) +{ + (void)argv; + Helios_sleep(15); + memset(&devConfig, 0x00, sizeof(devConfig)); + do { + switch( devConfig.status ) { + case SSS_DEVICE_IMSI: + dr_read_device_imsi(); + break; + case SSS_DEVICE_IMEI: + dr_read_device_imei(); + break; + case SSS_DEVICE_NETWORK_CHECK: + dr_network_check(); + break; + case SSS_DEVICE_REPORT: + dr_report_dev_info(devConfig.profile_idx); + break; + case SSS_DEVICE_STATION_END: + default: + Helios_Thread_Exit(); + } + } while(1); + Helios_Thread_Exit(); +} + +application_init(devReport, "devReport", DEVREPORT_STACK_SIZE, 0); +#endif diff --git a/ports/quectel/core/source/machine_extint.c b/ports/quectel/core/source/machine_extint.c index 5824e97..2d2efd4 100644 --- a/ports/quectel/core/source/machine_extint.c +++ b/ports/quectel/core/source/machine_extint.c @@ -24,6 +24,7 @@ #include "helios_extint.h" #include "helios_debug.h" +#include "callbackdeal.h" #define EXTINT_LOG(msg, ...) custom_log("extint", msg, ##__VA_ARGS__) @@ -62,22 +63,39 @@ enum { ** Jayceon-20200908: ** Replace function mp_call_function_1_protected() with mp_sched_schedule_ex to slove the dump problem. */ +#if MICROPY_ENABLE_CALLBACK_DEAL +#define EXTINT_CALLBACK_OP(X, edge) do{ \ + st_CallBack_Extint *extint = malloc(sizeof(st_CallBack_Extint)); \ + if(NULL != extint) { \ + extint->pin_no = X; \ + extint->edge = edge; \ + extint->callback = extint_obj[X]->callback; \ + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_EXTINT, extint); \ + } \ + }while(0) +#else +#define EXTINT_CALLBACK_OP(X, edge) do{ \ + mp_obj_t extint_list[2] = { \ + mp_obj_new_int(X), \ + mp_obj_new_int(edge), \ + }; \ + mp_sched_schedule_ex(&extint_obj[X]->callback, mp_obj_new_list(2, extint_list)); \ + }while(0) + +#endif + #define HANDLER_FUN(X) \ -static void handler##X(void) \ +static void handler##X(void) \ { \ int edge = HELIOS_EXTINT_RISING; \ if(Helios_GPIO_GetLevel((Helios_GPIONum)X) == 0) \ {edge = HELIOS_EXTINT_FALLING; extint_count[X].falling_count++;} \ else {extint_count[X].rising_count++;} \ - if (extint_obj[X]->callback.cb != mp_const_none && \ + if (extint_obj[X]->callback.cb != mp_const_none && \ ((mp_sched_num_pending() < MICROPY_SCHEDULER_DEPTH))) { \ - mp_obj_t extint_list[2] = { \ - mp_obj_new_int(X), \ - mp_obj_new_int(edge), \ - }; \ - mp_sched_schedule_ex(&extint_obj[X]->callback, mp_obj_new_list(2, extint_list)); \ + EXTINT_CALLBACK_OP(X, edge); \ } \ - Helios_ExtInt_Enable(extint_obj[X]->line); \ + Helios_ExtInt_Enable(extint_obj[X]->line); \ } @@ -123,6 +141,16 @@ HANDLER_FUN(38) HANDLER_FUN(39) HANDLER_FUN(40) HANDLER_FUN(41) +HANDLER_FUN(42) +HANDLER_FUN(43) +HANDLER_FUN(44) +HANDLER_FUN(45) +HANDLER_FUN(46) +HANDLER_FUN(47) +HANDLER_FUN(48) +HANDLER_FUN(49) +HANDLER_FUN(50) + eint_handler_t eint_handler[HELIOS_GPIOMAX] = { diff --git a/ports/quectel/core/source/machine_iic.c b/ports/quectel/core/source/machine_iic.c index 416a556..6bd71fd 100644 --- a/ports/quectel/core/source/machine_iic.c +++ b/ports/quectel/core/source/machine_iic.c @@ -148,11 +148,11 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_i2c_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) }, // class constants - { MP_ROM_QSTR(MP_QSTR_I2C0), MP_ROM_INT(HELIOS_I2C0) }, -#if !defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_I2C0), MP_ROM_INT(HELIOS_I2C0) }, { MP_ROM_QSTR(MP_QSTR_I2C1), MP_ROM_INT(HELIOS_I2C1) }, #if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_I2C2), MP_ROM_INT(HELIOS_I2C2) }, +#if !defined(PLAT_Qualcomm) { MP_ROM_QSTR(MP_QSTR_I2C3), MP_ROM_INT(HELIOS_I2C3) }, #endif #endif diff --git a/ports/quectel/core/source/machine_iic_simulation.c b/ports/quectel/core/source/machine_iic_simulation.c new file mode 100644 index 0000000..a45a0b0 --- /dev/null +++ b/ports/quectel/core/source/machine_iic_simulation.c @@ -0,0 +1,516 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "runtime.h" +#include "gc.h" +#include "mphal.h" +#include "mperrno.h" +#include "helios_os.h" + +#include "helios_gpio.h" +#include "mphalport.h" +#include "helios_iic.h" +#include "helios_debug.h" + +#define HELIOS_IIC_SIMULATION_LOG(msg, ...) custom_log("machine_iic_simu", msg, ##__VA_ARGS__) + +#if defined (PLAT_ASR) +#define MS_REFERENCE_VALUE 43 //ASR时间 该时间由EC600NCN_LC实际测试所得 + +#elif defined (PLAT_Unisoc) +#define MS_REFERENCE_VALUE 76 //展锐时间,该时间由EC600UCN_LB实际测试所得 76 + +#elif defined (PLAT_RDA) +#define MS_REFERENCE_VALUE 6 //NB时间,该时间由BC25PA实际测试所得 + +#elif defined (PLAT_Qualcomm) +#define MS_REFERENCE_VALUE 122 //高通时间,该时间由BG95M3实际测试所得 (不可靠) + + +#else + #error "This platform does not support" +#endif + +const mp_obj_type_t machine_simulation_i2c_type; + +typedef struct _machine_simu_i2c_obj_t +{ + mp_obj_base_t base; + Helios_GPIONum scl_gpio; + Helios_GPIONum sda_gpio; + uint32_t i2c_freq; + uint32_t sleep_us; + + +} machine_simu_i2c_obj_t; + +STATIC machine_simu_i2c_obj_t *cur_i2c = NULL; + +#define IIC_SDA(X) (Helios_GPIO_SetLevel((Helios_GPIONum)cur_i2c->sda_gpio, X)) +#define IIC_SCL(X) (Helios_GPIO_SetLevel((Helios_GPIONum)cur_i2c->scl_gpio, X)) + +#define READ_SCL (Helios_GPIO_GetLevel((Helios_GPIONum)cur_i2c->scl_gpio)) +#define READ_SDA (Helios_GPIO_GetLevel((Helios_GPIONum)cur_i2c->sda_gpio)) + +#define SDA_IN (Helios_GPIO_SetDirection((Helios_GPIONum) cur_i2c->sda_gpio, HELIOS_GPIO_INPUT)) +#define SDA_OUT (Helios_GPIO_SetDirection((Helios_GPIONum) cur_i2c->sda_gpio, HELIOS_GPIO_OUTPUT)) +#define SCL_OUT (Helios_GPIO_SetDirection((Helios_GPIONum) cur_i2c->scl_gpio, HELIOS_GPIO_OUTPUT)) + + + +STATIC void uudelay(uint32_t us) +{ + volatile uint32_t i; + for (i = 0; i < us * MS_REFERENCE_VALUE; i++) { + i = i + 1; + } + +} + +#define SLEEP (uudelay(cur_i2c->sleep_us)) + + + + + +//产生IIC起始信号 +//1.先拉高SDA,再拉高SCL,空闲状态 +//2.拉低SDA +STATIC void IIC_Start() //启动信号 + +{ + SDA_OUT; + SCL_OUT; + IIC_SDA(1); //确保SDA线为高电平 + IIC_SCL(1); //确保SCL高电平 + + SLEEP; + + IIC_SDA(0); //在SCL为高时拉低SDA线,即为起始信号 + + SLEEP; +} + +//产生IIC停止信号 +//1.先拉低SDA,再拉低SCL +//2.拉高SCL +//3.拉高SDA +//4.停止接收数据 +STATIC void IIC_Stop(void) +{ + SDA_OUT; + IIC_SCL(0); + IIC_SDA(0); //STOP:当SCL高时,数据由低变高 + SLEEP; + IIC_SCL(1); + IIC_SDA(1); //发送I2C总线结束信号 + SLEEP; +} + +//主机产生应答信号ACK +//1.先拉低SCL,再拉低SDA +//2.拉高SCL +//3.拉低SCL## 标题 +STATIC void I2C_Ack(void) +{ + SDA_OUT; + IIC_SCL(0); //先拉低SCL,使得SDA数据可以发生改变 + IIC_SDA(0); + SLEEP; + IIC_SCL(1); + SLEEP; + IIC_SCL(0); + SLEEP; +} + +//主机不产生应答信号NACK +//1.先拉低SCL,再拉高SDA +//2.拉高SCL +//3.拉低SCL +STATIC void I2C_NAck(void) +{ + SDA_OUT; + IIC_SCL(0); //先拉低SCL,使得SDA数据可以发生改变 + IIC_SDA(1); //拉高SDA,不产生应答信号 + SLEEP; + IIC_SCL(1); + SLEEP; + IIC_SCL(0); + SLEEP; +} + +STATIC uint8_t I2C_Wait_Ack(void) +{ + int ErrTime=0; + int ReadAck=0; + SDA_IN; // Config SDA GPIO as Input + SLEEP; + IIC_SCL(1); // Set the SCL and wait for ACK + while(1) + { + ReadAck = READ_SDA ; // Read the input + if(ReadAck) + { + ErrTime++; + if(ErrTime>1000) + { + //Error handler:Set error flag, retry or stop. + //Define by users + return 1; + } + } + if(ReadAck==0) // Receive a ACK + { + SLEEP; + IIC_SCL(0); // Clear the SCL for Next Transmit + return 0; + } + } +} + +STATIC uint8_t I2C_read_ack() +{ + uint8_t r; + SDA_IN; //设置SDA方向为输入 + IIC_SCL(0); // SCL变低 + r = READ_SDA; //读取ACK信号 + SLEEP; + IIC_SCL(1); // SCL变高 + SLEEP; + return r; +} + + +//IIC发送一个字节 +//返回从机有无应答 +//1,有应答 +//0,无应答 + +//IIC_SCL=0; +//在SCL上升沿时准备好数据,进行传送数据时,拉高拉低SDA,因为传输一个字节,一个SCL脉冲里传输一个位。 +//数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变) +//只有当SCL被拉低后,SDA才能被改变 +//总结:在SCL为高电平期间,发送数据,发送8次数据,数据为1,SDA被拉高,数据为0,SDA被拉低。 +//传输期间保持传输稳定,所以数据线仅可以在时钟SCL为低电平时改变。 +STATIC uint8_t IIC_Send_Byte(uint8_t txd) +{ + uint8_t t; + SLEEP; + SDA_OUT; + + IIC_SCL(0); + SLEEP; + for (t = 0; t < 8; t++) + { + //IIC_SDA=(txd&0x80)>>7; //获取最高位 + //获取数据的最高位,然后左移7位 + //如果某位为1,则SDA为1,否则相反 + //IIC_SCL(0); + //SLEEP; + if ((txd & 0x80) >> 7) + IIC_SDA(1); + else + IIC_SDA(0); + txd <<= 1; + SLEEP; + + + IIC_SCL(1); + SLEEP; + IIC_SCL(0); + //SLEEP; + } + + return I2C_Wait_Ack(); +} + +//读1个字节,ack=1时,发送ACK,ack=0,发送nACK +STATIC uint8_t IIC_Read_Byte(uint8_t ack) +{ + uint8_t i, receive = 0; + SLEEP; + SDA_IN; //SDA设置为输入 + SLEEP; + for (i = 0; i < 8; i++) + { + IIC_SCL(1); + + receive <<= 1; + if (READ_SDA) { + receive++; + } + SLEEP; + IIC_SCL(0); + SLEEP; + } + if (!ack) + I2C_NAck(); //发送nACK + else + I2C_Ack(); //发送ACK + //SLEEP; + return receive; +} + +/* +I2C读操作 +addr:目标设备地址 +buf:读缓冲区 +len:读入字节的长度 +*/ +/* 通过模拟I2C向从站写数据 */ + +#define IIC_SEND_BYTE(x) do { \ + if(0 != IIC_Send_Byte(x)) { \ + return -1; \ + } \ +}while(0) + +STATIC int i2c_read(uint8_t slaveaddress, uint8_t *regaddr, size_t addrlen, uint8_t *data, size_t datalen,uint32_t wait_times) +{ + uint32_t i; + uint8_t t; + + if(addrlen > 0) { + IIC_Start(); //起始条件,开始数据通信 + //发送地址和数据读写方向 + t = (slaveaddress << 1) | 0; //低位为0,表示写数据 + IIC_SEND_BYTE(t); + //写入数据 + for (i = 0; i < addrlen; i++) + IIC_SEND_BYTE(regaddr[i]); + } + + //Helios_msleep(5); + + IIC_Start(); //起始条件,开始数据通信 + //发送地址和数据读写方向 + t = (slaveaddress << 1) | 1; //低位为1,表示读数据 + IIC_SEND_BYTE(t); + //读入数据 + for (i = 0; i < datalen-1; i++) { + data[i] = IIC_Read_Byte(1); + } + data[i] = IIC_Read_Byte(0); + IIC_Stop(); //终止条件,结束数据通信 + return 0; +} +/* +I2C写操作 +addr:目标设备地址 +buf:写缓冲区 +len:写入字节的长度 +*/ +STATIC int i2c_write(uint8_t slaveaddress, uint8_t *regaddr,size_t addrlen,uint8_t *data, size_t datalen) +{ + uint32_t i; + uint8_t t; + HELIOS_IIC_SIMULATION_LOG("i2c_write1\n"); + IIC_Start(); //起始条件,开始数据通信 + HELIOS_IIC_SIMULATION_LOG("i2c_write14\n"); + //发送地址和数据读写方向 + t = (slaveaddress << 1) | 0; //低位为0,表示写数据 + IIC_SEND_BYTE(t); + HELIOS_IIC_SIMULATION_LOG("i2c_write2\n"); + //写入数据 + for (i = 0; i < addrlen; i++) + IIC_SEND_BYTE(regaddr[i]); + HELIOS_IIC_SIMULATION_LOG("i2c_write3\n"); + + for (i = 0; i < datalen; i++) + IIC_SEND_BYTE(data[i]); + HELIOS_IIC_SIMULATION_LOG("i2c_write4\n"); + IIC_Stop(); //终止条件,结束数据通信 + return 0; +} + +STATIC void machine_simu_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + machine_simu_i2c_obj_t *self = self_in; + mp_printf(print, "I2C scl_gpio:%d, sda_gpio:%d, freq:%dHz\n", self->scl_gpio, self->sda_gpio, self->i2c_freq); +} + +mp_obj_t machine_simu_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum + { + ARG_scl, + ARG_sda, + ARG_freq + }; + static const mp_arg_t allowed_args[] = { + {MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = HELIOS_GPIO1}}, + {MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = HELIOS_GPIO2}}, + {MP_QSTR_frq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 100}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint32_t i2c_sda = args[ARG_sda].u_int; + uint32_t i2c_scl = args[ARG_scl].u_int; + uint32_t freq = args[ARG_freq].u_int; + + HELIOS_IIC_SIMULATION_LOG("i2c_sda:%d, i2c_scl:%d, freq:%d\n", i2c_sda, i2c_scl, freq); + + if (freq > 1000000 || freq == 0 ||i2c_sda >= HELIOS_GPIOMAX || i2c_scl >= HELIOS_GPIOMAX) + { + mp_raise_ValueError("Parameter setting error, please check"); + } + + Helios_GPIOInitStruct gpio_struct = {0}; + gpio_struct.dir = HELIOS_GPIO_OUTPUT; + gpio_struct.pull = HELIOS_PULL_NONE; + gpio_struct.value = HELIOS_LVL_HIGH; + if(0 != Helios_GPIO_Init((Helios_GPIONum)i2c_sda, &gpio_struct)) { + mp_raise_ValueError("GPIO(SDA) initialization failed. Please try again or replace another GPIO"); + } + Helios_msleep(5); + if (0 != Helios_GPIO_Init((Helios_GPIONum)i2c_scl, &gpio_struct)) + { + mp_raise_ValueError("GPIO(SCL) initialization failed. Please try again or replace another GPIO"); + } + + machine_simu_i2c_obj_t *self = m_new_obj(machine_simu_i2c_obj_t); + cur_i2c = self; + + self->base.type = &machine_simulation_i2c_type; + self->scl_gpio = i2c_scl; + self->sda_gpio = i2c_sda; + self->i2c_freq = freq; + + self->sleep_us = (uint32_t)(500000/freq); + + HELIOS_IIC_SIMULATION_LOG("sleep_us:%d\n", self->sleep_us); + + return MP_OBJ_FROM_PTR(self); +} +STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = { + {MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8}}, +}; +STATIC mp_obj_t machine_i2c_write_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_slaveaddr, + ARG_regaddr, + ARG_regaddr_len, + ARG_databuf, + ARG_datasize + }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); + + machine_simu_i2c_obj_t *self = (machine_simu_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + mp_buffer_info_t regaddr_bufinfo; + mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); + int regaddr_length = args[ARG_regaddr_len].u_int; + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_READ); + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + //uart_printf("i2c wirte: busid:%x slaveddr:%x, regaddr:%x, data:%s datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, + // bufinfo.buf, args[ARG_datasize].u_int); + // do the transfer + + int ret = i2c_write((uint8_t)args[ARG_slaveaddr].u_int, (uint8_t *)regaddr_bufinfo.buf, (size_t)regaddr_length, (void *)bufinfo.buf, (size_t)length); + if (ret < 0) + { + ret = -1; + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_write_obj, 1, machine_i2c_write_mem); + +STATIC const mp_arg_t machine_i2c_mem_allowed_read_args[] = { + {MP_QSTR_slaveaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_regaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_regaddr_len, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_databuf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_datasize, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8}}, + {MP_QSTR_dalay, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 8}}, +}; +STATIC mp_obj_t machine_i2c_read_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_slaveaddr, + ARG_regaddr, + ARG_regaddr_len, + ARG_databuf, + ARG_datasize, + ARG_dalay + }; + mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(machine_i2c_mem_allowed_read_args), machine_i2c_mem_allowed_read_args, args); + + machine_simu_i2c_obj_t *self = (machine_simu_i2c_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + + mp_buffer_info_t regaddr_bufinfo; + mp_get_buffer_raise(args[ARG_regaddr].u_obj, ®addr_bufinfo, MP_BUFFER_READ); + int regaddr_length = args[ARG_regaddr_len].u_int; + + // get the buffer to read the data into + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_databuf].u_obj, &bufinfo, MP_BUFFER_WRITE); + + int length = (size_t)args[ARG_datasize].u_int > bufinfo.len ? bufinfo.len : (size_t)args[ARG_datasize].u_int; + + //uart_printf("i2c read: busid:%x slaveddr:%x, regaddr:%x, datalen:%d\n", self->bus_id, args[ARG_slaveaddr].u_int, args[ARG_regaddr].u_int, + // args[ARG_datasize].u_int); + // do the transfer + int ret = i2c_read((uint8_t)args[ARG_slaveaddr].u_int, (uint8_t *)regaddr_bufinfo.buf, (size_t)regaddr_length, (uint8_t *)bufinfo.buf, (size_t)length, (uint32_t)args[ARG_dalay].u_int); + if (ret < 0) + { + ret = -1; + return mp_obj_new_int(ret); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_read_obj, 1, machine_i2c_read_mem); + +STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table1[] = { + {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_i2c_read_obj)}, + {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj)}, + // class constants + {MP_ROM_QSTR(MP_QSTR_STANDARD_MODE), MP_ROM_INT(HELIOS_STANDARD_MODE)}, + {MP_ROM_QSTR(MP_QSTR_FAST_MODE), MP_ROM_INT(HELIOS_FAST_MODE)}, + PLAT_GPIO_DEF(PLAT_GPIO_NUM), +}; + +MP_DEFINE_CONST_DICT(mp_machine_simu_i2c_locals_dict, machine_i2c_locals_dict_table1); + +const mp_obj_type_t machine_simulation_i2c_type = { + {&mp_type_type}, + .name = MP_QSTR_I2C_SIMU, + .print = machine_simu_i2c_print, + .make_new = machine_simu_i2c_make_new, + .locals_dict = (mp_obj_dict_t *)&mp_machine_simu_i2c_locals_dict, +}; diff --git a/ports/quectel/core/source/machine_keypad.c b/ports/quectel/core/source/machine_keypad.c index 43ea459..79670c2 100644 --- a/ports/quectel/core/source/machine_keypad.c +++ b/ports/quectel/core/source/machine_keypad.c @@ -24,7 +24,7 @@ ****************************************************************************** */ -#if defined(PLAT_ASR) +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) #include #include #include @@ -169,4 +169,4 @@ STATIC mp_obj_t machine_keypad_make_new(const mp_obj_type_t *type, size_t n_args } #endif -#endif /* MICROPY_PY_KEYPAD && PLAT_ASR */ +#endif /* MICROPY_PY_KEYPAD && PLAT_ASR || PLAT_Unisoc*/ \ No newline at end of file diff --git a/ports/quectel/core/source/machine_lcd.c b/ports/quectel/core/source/machine_lcd.c index c9fa7f6..f6841ce 100644 --- a/ports/quectel/core/source/machine_lcd.c +++ b/ports/quectel/core/source/machine_lcd.c @@ -311,10 +311,6 @@ STATIC mp_obj_t machine_lcd_make_new(const mp_obj_type_t *type, size_t n_args, s { // mp_arg_check_num(n_args, n_kw, 0, 0, true); - if(self_lcd != NULL) { - m_del_obj(machine_lcd_obj_t,self_lcd); - self_lcd = NULL; - } self_lcd = m_new_obj(machine_lcd_obj_t); memset(self_lcd,0,sizeof(machine_lcd_obj_t)); diff --git a/ports/quectel/core/source/machine_uart.c b/ports/quectel/core/source/machine_uart.c index 20f2d99..30edd45 100644 --- a/ports/quectel/core/source/machine_uart.c +++ b/ports/quectel/core/source/machine_uart.c @@ -237,7 +237,7 @@ STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); -#if defined (PLAT_ASR) +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) STATIC mp_obj_t machine_uart_485_control(mp_obj_t self_in,mp_obj_t gpio_n,mp_obj_t direc) { int ret = -1; machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -327,11 +327,13 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { #if defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, #endif -#if defined (PLAT_ASR) +#if defined (PLAT_ASR) || defined (PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_control_485), MP_ROM_PTR(&machine_uart_485_control_obj) }, - { MP_ROM_QSTR(MP_QSTR_UART0), MP_ROM_INT(HELIOS_UART0) }, PLAT_GPIO_DEF(PLAT_GPIO_NUM), #endif +#if defined (PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_UART0), MP_ROM_INT(HELIOS_UART0) }, +#endif #if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, diff --git a/ports/quectel/core/source/misc_pwm.c b/ports/quectel/core/source/misc_pwm.c index 507fd09..2716874 100644 --- a/ports/quectel/core/source/misc_pwm.c +++ b/ports/quectel/core/source/misc_pwm.c @@ -65,39 +65,43 @@ STATIC void misc_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k STATIC void misc_pwm_init_helper(misc_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_high_time, ARG_cycle_time }; + enum { ARG_cycle_range, ARG_high_time, ARG_cycle_time }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_high_time, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_cycle_time, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cycle_range, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_high_time, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cycle_time, MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - PWM_LOG("self->cycle_range = %d\n",self->cycle_range); - if(self->cycle_range != HELIOS_PWM_CYCLE_ABOVE_1US && self->cycle_range != HELIOS_PWM_CYCLE_ABOVE_1MS && self->cycle_range != HELIOS_PWM_CYCLE_ABOVE_10US && self->cycle_range != HELIOS_PWM_CYCLE_ABOVE_BELOW_US ) { - - mp_raise_ValueError("invalid cycle_range value, must be in {0:us or 1:ms or 2:10us}"); - } - + //PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",args[ARG_cycle_range].u_int, args[ARG_high_time].u_int, args[ARG_cycle_time].u_int); + + if ((args[ARG_cycle_range].u_int < HELIOS_PWM_CYCLE_ABOVE_1US) || (args[ARG_cycle_range].u_int > HELIOS_PWM_CYCLE_ABOVE_BELOW_US)) + { + mp_raise_ValueError("invalid cycle_range value, must be in {0:us, 1:ms, 2:10us, 3:below us}."); + } // get high time - if (args[ARG_high_time].u_int > 0 && args[ARG_high_time].u_int < 65535) { - self->high_time = args[ARG_high_time].u_int; - } else { + if ((args[ARG_high_time].u_int < 0) || (args[ARG_high_time].u_int > 65535)) + { mp_raise_ValueError("invalid high_time value, must be in {0~65535}"); } - // get cycle time - if (args[ARG_cycle_time].u_int > 0 && args[ARG_cycle_time].u_int < 65535) { - self->cycle_time = args[ARG_cycle_time].u_int; - } else { + if ((args[ARG_cycle_time].u_int < 0) || (args[ARG_cycle_time].u_int > 65535)) + { mp_raise_ValueError("invalid cycle_time value, must be in {0~65535}"); } - if(self->high_time > self->cycle_time) { + if(args[ARG_high_time].u_int > args[ARG_cycle_time].u_int) + { mp_raise_ValueError("invalid high_time value, must less more cycle_time or be equal to cycle_time"); } + self->cycle_range = args[ARG_cycle_range].u_int; + self->high_time = args[ARG_high_time].u_int; + self->cycle_time = args[ARG_cycle_time].u_int; + PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); + if(Helios_PWM_Init(self->pin) != 0) { mp_raise_ValueError("fail"); } @@ -107,16 +111,15 @@ STATIC void misc_pwm_init_helper(misc_pwm_obj_t *self, STATIC mp_obj_t misc_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 4, 4, true); - unsigned int pin_id = mp_obj_get_int(args[0]); - unsigned int cycle_range_id = mp_obj_get_int(args[1]); + int pin_id = mp_obj_get_int(args[0]); PWM_LOG("n_args = %d\n",n_args); - int pwm_num = pin_id; - if ((pwm_num < 0) || (pwm_num > PWMMAX-1)) + if ((pin_id < 0) || (pin_id > PWMMAX-1)) { mp_raise_ValueError("invalid PWMn value, must be in {0~3}."); } + // create PWM object from the given pin if (misc_pwm_obj[pin_id] == NULL) { @@ -125,14 +128,10 @@ STATIC mp_obj_t misc_pwm_make_new(const mp_obj_type_t *type, misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; self->base.type = &misc_pwm_type; self->pin = pin_id; - self->high_time = 0; - self->cycle_time = 0; - self->cycle_range = cycle_range_id; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - misc_pwm_init_helper(self, n_args - 2, args + 2, &kw_args); - + misc_pwm_init_helper(self, n_args - 1, args + 1, &kw_args); return MP_OBJ_FROM_PTR(self); } @@ -146,7 +145,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(misc_pwm_init_obj, 1, misc_pwm_init); STATIC mp_obj_t misc_pwm_enable(mp_obj_t self_in) { misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - + + PWM_LOG("cycle_range=%d, high_time=%d, cycle_time=%d\n",self->cycle_range, self->high_time, self->cycle_time); double frequency = 0; float duty = 0; if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1US || self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_10US) { diff --git a/ports/quectel/core/source/misc_temperature.c b/ports/quectel/core/source/misc_temperature.c new file mode 100644 index 0000000..21f015b --- /dev/null +++ b/ports/quectel/core/source/misc_temperature.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if defined(PLAT_RDA) +#include "stdio.h" +#include "stdlib.h" +//#include "timer.h" +#include "obj.h" +#include +#include "runtime.h" +#include "mphalport.h" + +#include "helios_adc.h" + +typedef struct _misc_tempr_obj_t { + mp_obj_base_t base; + int temper; +} misc_tempr_obj_t; + + +/*=============================================================================*/ +/* FUNCTION: Helios_adc_deinit */ +/*=============================================================================*/ +/*!@brief : adc deinit + * @param[in] : + * @param[out] : + * @return : 0 + * + */ +/*=============================================================================*/ +STATIC mp_obj_t Helios_Get_temperature(mp_obj_t self_in) +{ + int ret = Helios_Get_Temperature(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_Get_temperature_obj, Helios_Get_temperature); + +STATIC const mp_rom_map_elem_t misc_temper_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_temperature), MP_ROM_PTR(&Helios_Get_temperature_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(misc_temper_locals_dict, misc_temper_locals_dict_table); + +STATIC mp_obj_t misc_temper_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) ; + +const mp_obj_type_t machine_temperature_type = { + { &mp_type_type }, + .name = MP_QSTR_Temperature, + .make_new = misc_temper_make_new, + .locals_dict = (mp_obj_dict_t *)&misc_temper_locals_dict, +}; + +STATIC mp_obj_t misc_temper_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + //unsigned int pin_id = mp_obj_get_int(args[0]); + + // create ADC object + misc_tempr_obj_t *self = m_new_obj(misc_tempr_obj_t); + self->base.type = &machine_temperature_type; + //self->pin = pin_id; + + return MP_OBJ_FROM_PTR(self); +} + +#endif + diff --git a/ports/quectel/core/source/misc_usb.c b/ports/quectel/core/source/misc_usb.c index 6f0cbd6..357c188 100644 --- a/ports/quectel/core/source/misc_usb.c +++ b/ports/quectel/core/source/misc_usb.c @@ -53,7 +53,8 @@ STATIC mp_obj_t misc_usb_register_cb(mp_obj_t self_in, mp_obj_t usr_callback) memset(&cb, 0, sizeof(c_callback_t)); g_py_callback = &cb; mp_sched_schedule_callback_register(g_py_callback, usr_callback); - + + Helios_USB_DeInit(); Helios_USBInitStruct info = {ql_usb_detect_handler}; int ret = Helios_USB_Init(&info); return mp_obj_new_int(ret); diff --git a/ports/quectel/core/source/misc_usbnet.c b/ports/quectel/core/source/misc_usbnet.c index 43ef4a5..b714b68 100644 --- a/ports/quectel/core/source/misc_usbnet.c +++ b/ports/quectel/core/source/misc_usbnet.c @@ -39,6 +39,32 @@ STATIC mp_obj_t misc_usbnet_set_type(mp_obj_t type_in) STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_type_obj, misc_usbnet_set_type); +STATIC mp_obj_t misc_usbnet_get_type(void) +{ + Helios_USBNET_Type_e type = 0; + int ret = Helios_USBNET_GetType(&type); + if (ret == 0) + { + ret = type; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_type_obj, misc_usbnet_get_type); + + +STATIC mp_obj_t misc_usbnet_get_status(void) +{ + uint8_t status = 0; + int ret = Helios_USBNET_GetStatus(&status); + if (ret == 0) + { + ret = status; + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_get_status_obj, misc_usbnet_get_status); + + STATIC mp_obj_t misc_usbnet_open(void) { int ret = Helios_USBNET_Open(); @@ -47,14 +73,24 @@ STATIC mp_obj_t misc_usbnet_open(void) STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_open_obj, misc_usbnet_open); +STATIC mp_obj_t misc_usbnet_close(void) +{ + int ret = Helios_USBNET_Close(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_close_obj, misc_usbnet_close); + STATIC const mp_rom_map_elem_t misc_usbnet_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_USBNET) }, - { MP_ROM_QSTR(MP_QSTR_set_worktype), MP_ROM_PTR(&misc_usbnet_set_type_obj) }, - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_usbnet_open_obj) }, - { MP_ROM_QSTR(MP_QSTR_Type_ECM), MP_ROM_INT(HELIOS_USBNET_TYPE_ECM) }, - { MP_ROM_QSTR(MP_QSTR_Type_RNDIS), MP_ROM_INT(HELIOS_USBNET_TYPE_RNDIS) }, + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_USBNET) }, + { MP_ROM_QSTR(MP_QSTR_set_worktype), MP_ROM_PTR(&misc_usbnet_set_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_worktype), MP_ROM_PTR(&misc_usbnet_get_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_status), MP_ROM_PTR(&misc_usbnet_get_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_usbnet_open_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_usbnet_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_Type_ECM), MP_ROM_INT(HELIOS_USBNET_TYPE_ECM) }, + { MP_ROM_QSTR(MP_QSTR_Type_RNDIS), MP_ROM_INT(HELIOS_USBNET_TYPE_RNDIS) }, }; STATIC MP_DEFINE_CONST_DICT(misc_usbnet_locals_dict, misc_usbnet_locals_dict_table); diff --git a/ports/quectel/core/source/modaudio.c b/ports/quectel/core/source/modaudio.c index ad435c2..2e4c60a 100644 --- a/ports/quectel/core/source/modaudio.c +++ b/ports/quectel/core/source/modaudio.c @@ -16,17 +16,169 @@ #include #include +#include #include "mpconfigport.h" #include "compile.h" #include "runtime.h" #include "repl.h" #include "mperrno.h" +#include "modaudio.h" +#include "helios_debug.h" +#include "helios_audio.h" + +#define HELIOS_MODAUDIO_LOG(msg, ...) custom_log("mod_audio", msg, ##__VA_ARGS__) + +static AudioChannelSupport_t audio_channel_tab = { +#if defined(BOARD_EC600NCN_LA) + {1, 0, 0} +#elif defined(BOARD_EC600NCN_LC) + {1, 0, 0} +#elif defined(BOARD_EC600NCN_LD) + {1, 0, 0} +#elif defined(BOARD_EC600SCN_LA) + {1, 0, 0} +#elif defined(BOARD_EC600SCN_LB) + {1, 0, 0} +#elif defined(BOARD_EC800NCN_LA) + {1, 0, 0} +#elif defined(BOARD_EC200UCN_AA) + {1, 1, 1} +#elif defined(BOARD_EC200UCN_LB) + {1, 1, 1} +#elif defined(BOARD_EC200UEU_AB) + {1, 1, 1} +#elif defined(BOARD_EC600UCN_LB) || defined(BOARD_EC600UCN_LB_VOLTE) + {1, 1, 1} +#elif defined(BOARD_EC600UCN_LC) + {1, 1, 1} +#elif defined(BOARD_EC600UEU_AB) || defined(BOARD_EC600UEU_AB_VOLTE) + {1, 1, 1} +#elif defined(BOARD_BG95M3) + {0, 0, 0} +#elif defined(BOARD_BC25PA) + {0, 0, 0} +#else + #error "Please add the corresponding platform configuration items in audio_channel_tab." +#endif +}; -#include -#include "modaudio.h" +/* + return value: + 0 - The current platform does not support this channel + 1 - The current platform support this channel + -1 - error +*/ +int audio_channel_check(int channel) +{ + if ((channel < 0) || (channel > 2)) + { + return 0; + } + + return (int)audio_channel_tab.channel_support[channel]; +} + +#if defined (PLAT_ASR) + +#define CHECK_PROFILE_ID(id) (((HELIOS_VC_HANDSET <= id && HELIOS_VC_MAXCOUNT > id) || (HELIOS_AC_HANDSET <= id && HELIOS_AC_MAXCOUNT > id))) +#define CHECK_LEVLE(x) () + +STATIC mp_obj_t helios_set_DSPGain(mp_obj_t profile_id, mp_obj_t dsp_gain_table) +{ + int id = mp_obj_get_int(profile_id); + int i = 0; + int16_t dsp_gain[12] = {0}; + mp_obj_t *items = NULL; + mp_buffer_info_t dsp_table_data; + if (!CHECK_PROFILE_ID(id)) + { + mp_raise_ValueError("The ID parameter is wrong. The value is [0,4] or [64,69]"); + return mp_obj_new_int(-1); + } + + mp_obj_get_array_fixed_n(dsp_gain_table, 12, &items); + + for (i = 0; i < 12; i++) { + dsp_gain[i] = (int16_t)mp_obj_get_int(items[i]); + HELIOS_MODAUDIO_LOG("table[%d]: %d\n",i, dsp_gain[i]); + } + + int ret = Helios_Audio_SetDSPGainTable((uint32_t)id, dsp_gain); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(audio_DSPGain_obj, helios_set_DSPGain); + +static int codec_gain_num(unsigned int profile_id, signed int level, uint32_t* data) +{ + if(CHECK_PROFILE_ID((int)profile_id)); + else{ + return -1; + } + if(level < 0 || level > HELIOS_AUDIOHAL_SPK_VOL_11){ + return -1; + } + if(data[0] > 38){ + return -1; + } + if(data[1] > 4){ + return -1; + } + if(data[2] > 4){ + return -1; + } + if(data[3] > 1){ + return -1; + } + if(data[4] > 2){ + return -1; + } + return 0; +} + + +STATIC mp_obj_t helios_set_CodecGain(mp_obj_t profile_id, mp_obj_t level, mp_obj_t codec_gain_table) +{ + int id = mp_obj_get_int(profile_id); + int32_t codec_level = mp_obj_get_int(level); + int i = 0; + uint32_t codec_gain[5] = {0}; + mp_obj_t *items = NULL; + int8_t *data = NULL; + + mp_obj_get_array_fixed_n(codec_gain_table, 5, &items); + + for (i = 0; i < 5; i++) { + codec_gain[i] = (uint32_t)mp_obj_get_int(items[i]); + HELIOS_MODAUDIO_LOG("table[%d]: %d\n",i, codec_gain[i]); + } + + if( -1 == codec_gain_num(id, codec_level, codec_gain)) { + mp_raise_ValueError("Parameter error, please check whether the parameter meets the value range"); + } + + int ret = Helios_Audio_SetCodecGainTable((uint32_t)id, codec_level, codec_gain); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(audio_CodecGain_obj, helios_set_CodecGain); + +STATIC mp_obj_t helios_get_current_ID() +{ + int ret = -1; + uint32_t id = Helios_get_current_profileID(); + HELIOS_MODAUDIO_LOG("profile ID = %d\n", id); + if(0xffff != id) { + ret = (int)id; + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(audio_get_current_ID_obj, helios_get_current_ID); + +#endif + STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = { @@ -36,6 +188,11 @@ STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_Audio), MP_ROM_PTR(&audio_audio_type) }, { MP_ROM_QSTR(MP_QSTR_Record), MP_ROM_PTR(&audio_record_type) }, +#if defined (PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_set_DSPGain), MP_ROM_PTR(&audio_DSPGain_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_CodecGain), MP_ROM_PTR(&audio_CodecGain_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_CurrentID), MP_ROM_PTR(&audio_get_current_ID_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_audio_globals, mp_module_audio_globals_table); diff --git a/ports/quectel/core/source/modaudio.h b/ports/quectel/core/source/modaudio.h index 55aea7b..3e494b6 100644 --- a/ports/quectel/core/source/modaudio.h +++ b/ports/quectel/core/source/modaudio.h @@ -30,6 +30,20 @@ extern const mp_obj_type_t audio_audio_type; extern const mp_obj_type_t audio_record_type; +typedef struct +{ + //char *model; + /* + ** channel_support[0]-recever + ** channel_support[1]-headphone + ** channel_support[2]-speaker + ** + ** channel_support[n] is 0, non-support + ** channel_support[n] is 1, support + */ + uint8_t channel_support[3]; +}AudioChannelSupport_t; + #ifdef __cplusplus } #endif diff --git a/ports/quectel/core/source/moddatacall.c b/ports/quectel/core/source/moddatacall.c index 60b014f..a02dc27 100644 --- a/ports/quectel/core/source/moddatacall.c +++ b/ports/quectel/core/source/moddatacall.c @@ -58,13 +58,12 @@ STATIC mp_obj_t qpy_datacall_start(size_t n_args, const mp_obj_t *args) mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); - if ((profile_id < (int)HELIOS_PROFILE_IDX_MIN) || (profile_id > (int)HELIOS_PROFILE_IDX_MAX)) + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) { -#if defined (PLAT_ASR) - mp_raise_ValueError("invalid value, profileIdx should be in [1,8]."); -#elif defined (PLAT_Unisoc) - mp_raise_ValueError("invalid value, profileIdx should be in [1,7]."); -#endif + mp_raise_msg_varg(&mp_type_ValueError, "invalid value, profileIdx should be in [%d,%d].", min_profile_id, max_profile_id); } if ((ip_type < 0) || (ip_type > 2)) { @@ -96,7 +95,11 @@ STATIC mp_obj_t qpy_datacall_start(size_t n_args, const mp_obj_t *args) snprintf(DataCallStartStruct.apn, sizeof(DataCallStartStruct.apn), "%s", (char *)apninfo.buf); snprintf(DataCallStartStruct.user, sizeof(DataCallStartStruct.user), "%s", (char *)usrinfo.buf); snprintf(DataCallStartStruct.pwd, sizeof(DataCallStartStruct.pwd), "%s", (char *)pwdinfo.buf); + + MP_THREAD_GIL_EXIT(); ret = Helios_DataCall_Start(profile_id, 0, &DataCallStartStruct); + MP_THREAD_GIL_ENTER(); + return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_start_obj, 5, 6, qpy_datacall_start); @@ -133,13 +136,12 @@ STATIC mp_obj_t qpy_datacall_record_apn(size_t n_args, const mp_obj_t *args) mp_get_buffer_raise(args[3], &usrinfo, MP_BUFFER_READ); mp_get_buffer_raise(args[4], &pwdinfo, MP_BUFFER_READ); - if ((profile_id < (int)HELIOS_PROFILE_IDX_MIN) || (profile_id > (int)HELIOS_PROFILE_IDX_MAX)) + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; + + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) { -#if defined (PLAT_ASR) - mp_raise_ValueError("invalid value, profileIdx should be in [1,8]."); -#elif defined (PLAT_Unisoc) - mp_raise_ValueError("invalid value, profileIdx should be in [1,7]."); -#endif + mp_raise_msg_varg(&mp_type_ValueError, "invalid value, profileIdx should be in [%d,%d].", min_profile_id, max_profile_id); } if ((ip_type < 0) || (ip_type > 2)) { @@ -233,14 +235,12 @@ STATIC mp_obj_t qpy_datacall_get_info(size_t n_args, const mp_obj_t *args) char ip6_pri_dns[64] = {0}; char ip6_sec_dns[64] = {0}; Helios_DataCallInfoStruct info = {0}; + int min_profile_id = (int)HELIOS_PROFILE_IDX_MIN; + int max_profile_id = (int)HELIOS_PROFILE_IDX_MAX; - if ((profile_id < (int)HELIOS_PROFILE_IDX_MIN) || (profile_id > (int)HELIOS_PROFILE_IDX_MAX)) + if ((profile_id < min_profile_id) || (profile_id > max_profile_id)) { -#if defined (PLAT_ASR) - mp_raise_ValueError("invalid value, profileIdx should be in [1,8]."); -#elif defined (PLAT_Unisoc) - mp_raise_ValueError("invalid value, profileIdx should be in [1,7]."); -#endif + mp_raise_msg_varg(&mp_type_ValueError, "invalid value, profileIdx should be in [%d,%d].", min_profile_id, max_profile_id); } if ((ip_type < 0) || (ip_type > 2)) { @@ -369,7 +369,7 @@ STATIC mp_obj_t qpy_datacall_get_pdp_range(void) STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_get_pdp_range_obj, qpy_datacall_get_pdp_range); //#if defined(PLAT_ASR) || defined(PLAT_Unisoc) -STATIC mp_obj_t qpy_datacall_get_apn(mp_obj_t simid) +/*STATIC mp_obj_t qpy_datacall_get_apn(mp_obj_t simid) { #if defined(PLAT_ASR) || defined(PLAT_Unisoc) int sim_id = mp_obj_get_int(simid); @@ -386,18 +386,82 @@ STATIC mp_obj_t qpy_datacall_get_apn(mp_obj_t simid) return mp_obj_new_int(-1); #endif } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_get_apn_obj, qpy_datacall_get_apn); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_get_apn_obj, qpy_datacall_get_apn);*/ //#endif +STATIC mp_obj_t qpy_datacall_get_apn(size_t n_args, const mp_obj_t *args) +{ +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + int sim_id = mp_obj_get_int(args[0]); + int ret = 0; + char apn[99+1] = {0}; + + if (n_args == 1) + { + ret = Helios_DataCall_GetApn(2, sim_id, apn); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); + } + else if (n_args == 2) + { + int pid = mp_obj_get_int(args[1]); + + ret = Helios_DataCall_GetApn(3, sim_id, apn, pid); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); + } + else + { + mp_raise_ValueError("invalid value, The number of parameters cannot be greater than 2."); + } +#else + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); +#endif +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_apn_obj, 1, 2, qpy_datacall_get_apn); +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + +STATIC mp_obj_t qpy_datacall_set_dns_server(size_t n_args, const mp_obj_t *args) +{ + int profile_idx = mp_obj_get_int(args[0]); + int sim_id = mp_obj_get_int(args[1]); + + mp_buffer_info_t new_pri_dns = {0}; + mp_buffer_info_t new_sec_dns = {0}; + mp_get_buffer_raise(args[2], &new_pri_dns, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &new_sec_dns, MP_BUFFER_READ); + + char new_pri[128]; + char new_sec[128]; + memset(&new_pri, 0, sizeof(new_pri)); + memset(&new_sec, 0, sizeof(new_sec)); + + memcpy(new_pri, new_pri_dns.buf, new_pri_dns.len); + memcpy(new_sec, new_sec_dns.buf, new_sec_dns.len); + + int ret = 0; + ret = Helios_DataCall_SetDnsServer(profile_idx, sim_id, new_pri, new_sec); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_set_dns_server_obj, 4, 4, qpy_datacall_set_dns_server); +#endif + STATIC mp_obj_t qpy_module_datacall_deinit(void) -{ +{ g_usr_callback = NULL; MOD_DATACALL_LOG("module datacall deinit.\r\n"); #if defined(PLAT_ASR) || defined(PLAT_Unisoc) Helios_DataCall_Deinit(); #endif - return mp_obj_new_int(0); -} + return mp_obj_new_int(0); +} STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_datacall_deinit_obj, qpy_module_datacall_deinit); STATIC const mp_rom_map_elem_t mp_module_datacall_globals_table[] = { @@ -410,9 +474,10 @@ STATIC const mp_rom_map_elem_t mp_module_datacall_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_recordApn), MP_ROM_PTR(&qpy_datacall_record_apn_obj) }, { MP_ROM_QSTR(MP_QSTR_setAsynMode), MP_ROM_PTR(&qpy_datacall_set_asynmode_obj) }, { MP_ROM_QSTR(MP_QSTR_getPdpRange), MP_ROM_PTR(&qpy_get_pdp_range_obj) }, - //#if defined(PLAT_ASR) || defined(PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_datacall_get_apn_obj) }, - //#endif + #if defined(PLAT_ASR) || defined(PLAT_Unisoc) + { MP_ROM_QSTR(MP_QSTR_setDnsserver), MP_ROM_PTR(&qpy_datacall_set_dns_server_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_datacall_globals, mp_module_datacall_globals_table); diff --git a/ports/quectel/core/source/modexample.c b/ports/quectel/core/source/modexample.c index 8451e86..a4abd46 100644 --- a/ports/quectel/core/source/modexample.c +++ b/ports/quectel/core/source/modexample.c @@ -126,12 +126,14 @@ STATIC mp_obj_t example_exec(const mp_obj_t arg0) { mp_raise_msg_varg(&mp_type_OSError, "File path error or not exist: [%s]", (char *)bufinfo.buf); } + #if MICROPY_KBD_EXCEPTION else if(ret == RET_KBD_INTERRUPT) { pyexec_system_exit = PYEXEC_FORCED_EXIT; MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); mp_raise_msg_varg(&mp_type_SystemExit, "CTRL_C Interrupt"); } + #endif // Pawn 2021-01-18 for JIRA STASR3601-2428 end return mp_const_none; } diff --git a/ports/quectel/core/source/modlpm.c b/ports/quectel/core/source/modlpm.c index 4159b06..c14035c 100644 --- a/ports/quectel/core/source/modlpm.c +++ b/ports/quectel/core/source/modlpm.c @@ -140,7 +140,7 @@ STATIC mp_obj_t Helios_lpm_wakelock_create_mp(size_t n_args, const mp_obj_t *arg int name_size; char *lock_name = (char *)mp_obj_str_get_str(args[0]); - name_size = mp_obj_get_int(args[1]); + name_size = strlen(lock_name); #if 0 //Aim At EC100Y by kingka ret = quec_lpm_task_init(); @@ -150,6 +150,11 @@ STATIC mp_obj_t Helios_lpm_wakelock_create_mp(size_t n_args, const mp_obj_t *arg } #endif + if((NULL == lock_name) || (0 == name_size)) + { + return mp_obj_new_int(-1); + } + wakelock_fd = Helios_LPM_WakeLockInit(lock_name, name_size); @@ -212,6 +217,35 @@ STATIC mp_obj_t Helios_lpm_get_wakelock_num_mp() STATIC MP_DEFINE_CONST_FUN_OBJ_0(Helios_lpm_get_wakelock_num_mp_obj, Helios_lpm_get_wakelock_num_mp); #endif +/*=============================================================================*/ +/* FUNCTION: Helios_lpm_ex_set_mp */ +/*=============================================================================*/ +/*!@brief : set power ex + * @param[in] : lpm seconds + * @param[out] : + * @return : + * 0 success + * else fail + */ +/*=============================================================================*/ +#if defined(PLAT_ASR) +STATIC mp_obj_t Helios_lpm_ex_set_mp(const mp_obj_t lpm_seconds) +{ + int ret = 0; + int g_lpm_seconds; + + g_lpm_seconds = mp_obj_get_int(lpm_seconds); + ret = Helios_LPM_EXSet(g_lpm_seconds); + if ( ret == 0 ) + { + return mp_obj_new_int(0); + } + + return mp_obj_new_int(-1); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_lpm_ex_set_mp_obj, Helios_lpm_ex_set_mp); +#endif /* STATIC mp_obj_t mp_get_free_size() @@ -237,6 +271,9 @@ STATIC const mp_rom_map_elem_t pm_module_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_autosleep), MP_ROM_PTR(&Helios_sleep_enable_mp_obj) }, // { MP_ROM_QSTR(MP_QSTR_getFreeSize), MP_ROM_PTR(&mp_get_free_size_obj) }, +#if defined(PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_sclkEx_set), MP_ROM_PTR(&Helios_lpm_ex_set_mp_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(pm_module_globals, pm_module_globals_table); diff --git a/ports/quectel/core/source/modlvgl.c b/ports/quectel/core/source/modlvgl.c index de0da34..f599c19 100644 --- a/ports/quectel/core/source/modlvgl.c +++ b/ports/quectel/core/source/modlvgl.c @@ -26150,11 +26150,14 @@ STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_bidi_get_visual_pos_obj, 6, mp_lv_bi * lvgl extension definition for: * void lv_init(void) */ - +STATIC uint16_t mp_lvgl_init_flag = 0; STATIC mp_obj_t mp_lv_init(size_t mp_n_args, const mp_obj_t *mp_args) { - + if(1 == mp_lvgl_init_flag) { + lv_deinit(); + } lv_init(); + mp_lvgl_init_flag = 1; return mp_const_none; } @@ -32745,6 +32748,34 @@ STATIC lv_fs_res_t lv_fs_drv_t_dir_close_cb_callback(lv_fs_drv_t * arg0, void * return (uint8_t)mp_obj_get_int(callback_result); } +STATIC void qpy_lvgl_deinit() +{ + + if(-1 != helios_lv_handler_task_ref ) { + Helios_Thread_Delete(helios_lv_handler_task_ref); + helios_lv_handler_task_ref = -1; + } + if(-1 != helios_lv_tick_task_ref ) { + Helios_Thread_Delete(helios_lv_tick_task_ref); + helios_lv_tick_task_ref = -1; + } + if(1 == mp_lvgl_init_flag) { + lv_deinit(); + mp_lvgl_init_flag = 0; + } + +} + + +STATIC mp_obj_t mp_lvgl_deinit(size_t mp_n_args, const mp_obj_t *mp_args) +{ + QPY_LVGL_LOG("mp lvgl deinit start \n"); + qpy_lvgl_deinit(); + QPY_LVGL_LOG("mp lvgl deinit end\n"); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(qpy_module_lvgl_deinit_obj, 0, mp_lvgl_deinit, qpy_lvgl_deinit); /* @@ -32753,6 +32784,7 @@ STATIC lv_fs_res_t lv_fs_drv_t_dir_close_cb_callback(lv_fs_drv_t * arg0, void * STATIC const mp_rom_map_elem_t lvgl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lvgl) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_lvgl_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_obj), MP_ROM_PTR(&mp_obj_type) }, { MP_ROM_QSTR(MP_QSTR_cont), MP_ROM_PTR(&mp_cont_type) }, { MP_ROM_QSTR(MP_QSTR_btn), MP_ROM_PTR(&mp_btn_type) }, diff --git a/ports/quectel/core/source/modmachine.c b/ports/quectel/core/source/modmachine.c index d6bfe53..1206df4 100644 --- a/ports/quectel/core/source/modmachine.c +++ b/ports/quectel/core/source/modmachine.c @@ -48,6 +48,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C_simulation), MP_ROM_PTR(&machine_simulation_i2c_type) }, { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #if !defined(PLAT_Qualcomm) { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, @@ -55,7 +56,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #endif -#if defined(PLAT_ASR) +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_KeyPad), MP_ROM_PTR(&machine_keypad_type) }, #endif diff --git a/ports/quectel/core/source/modmachine.h b/ports/quectel/core/source/modmachine.h index e5fc4fa..5e42d02 100644 --- a/ports/quectel/core/source/modmachine.h +++ b/ports/quectel/core/source/modmachine.h @@ -36,10 +36,11 @@ extern const mp_obj_type_t machine_extint_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_timer_type; extern const mp_obj_type_t machine_hard_i2c_type; +extern const mp_obj_type_t machine_simulation_i2c_type; extern const mp_obj_type_t machine_hard_spi_type; extern const mp_obj_type_t machine_wdt_type; extern const mp_obj_type_t machine_nandflash_type; -#if defined(PLAT_ASR) +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) extern const mp_obj_type_t machine_keypad_type; #endif diff --git a/ports/quectel/core/source/modmisc.c b/ports/quectel/core/source/modmisc.c index 13676da..8fc8bdb 100644 --- a/ports/quectel/core/source/modmisc.c +++ b/ports/quectel/core/source/modmisc.c @@ -68,7 +68,12 @@ STATIC const mp_rom_map_elem_t misc_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&misc_usb_type) }, #endif #endif -#if defined(PLAT_ASR) + +#if defined(PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_Temperature), MP_ROM_PTR(&machine_temperature_type) }, +#endif + +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_USBNET), MP_ROM_PTR(&misc_usbnet_module) }, #endif }; diff --git a/ports/quectel/core/source/modmisc.h b/ports/quectel/core/source/modmisc.h index 4b42750..0210545 100644 --- a/ports/quectel/core/source/modmisc.h +++ b/ports/quectel/core/source/modmisc.h @@ -34,11 +34,14 @@ extern const mp_obj_type_t misc_power_type; extern const mp_obj_type_t misc_pwm_type; extern const mp_obj_type_t misc_adc_type; extern const mp_obj_type_t misc_usb_type; -#if defined(PLAT_ASR) +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) extern const mp_obj_module_t misc_usbnet_module; #endif extern const mp_obj_type_t misc_powerkey_type; +#if defined(PLAT_RDA) +extern const mp_obj_module_t machine_temperature_type; +#endif #endif /* __MOD_MISC_H_ */ diff --git a/ports/quectel/core/source/modnet.c b/ports/quectel/core/source/modnet.c index 5c2d80f..d9749d4 100644 --- a/ports/quectel/core/source/modnet.c +++ b/ports/quectel/core/source/modnet.c @@ -418,7 +418,10 @@ STATIC mp_obj_t qpy_net_get_mnc(void) mp_obj_t mnc_list = mp_obj_new_list(0, NULL); Helios_NwCellInfoStruct info = {0}; + MP_THREAD_GIL_EXIT(); ret = Helios_Nw_GetCellInfo(0, &info); + MP_THREAD_GIL_ENTER(); + if (ret == 0) { if (info.gsm_info_num > 0) @@ -452,6 +455,56 @@ STATIC mp_obj_t qpy_net_get_mnc(void) } STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_mnc_obj, qpy_net_get_mnc); +STATIC mp_obj_t qpy_net_get_mnc_servingcell(void) +{ + int ret = 0; + int i = 0; + Helios_NwCellInfoStruct info = {0}; + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(0, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) @@ -504,6 +560,56 @@ STATIC mp_obj_t qpy_net_get_mcc(void) } STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_mcc_obj, qpy_net_get_mcc); +STATIC mp_obj_t qpy_net_get_mcc_servingcell(void) +{ + int ret = 0; + int i = 0; + Helios_NwCellInfoStruct info = {0}; + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(0, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) @@ -556,6 +665,56 @@ STATIC mp_obj_t qpy_net_get_lac(void) } STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_lac_obj, qpy_net_get_lac); +STATIC mp_obj_t qpy_net_get_lac_servingcell(void) +{ + int ret = 0; + int i = 0; + Helios_NwCellInfoStruct info = {0}; + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(0, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) @@ -607,6 +769,55 @@ STATIC mp_obj_t qpy_net_get_cid(void) } STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_cid_obj, qpy_net_get_cid); +STATIC mp_obj_t qpy_net_get_cid_servingcell(void) +{ + int ret = 0; + int i = 0; + Helios_NwCellInfoStruct info = {0}; + + MP_THREAD_GIL_EXIT(); + ret = Helios_Nw_GetCellInfo(0, &info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) @@ -781,7 +993,7 @@ STATIC mp_obj_t qpy_net_set_apn(mp_obj_t apn, mp_obj_t simid) } return mp_obj_new_int(-1); #else - return mp_obj_new_int(-1); + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_net_set_apn_obj, qpy_net_set_apn); @@ -805,7 +1017,7 @@ STATIC mp_obj_t qpy_net_get_apn(mp_obj_t simid) } return mp_obj_new_int(-1); #else - return mp_obj_new_int(-1); + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_get_apn_obj, qpy_net_get_apn); @@ -926,8 +1138,16 @@ STATIC const mp_rom_map_elem_t net_module_globals_table[] = { #if !defined (PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_net_add_event_handler_obj) }, #endif + +//#if defined(PLAT_ASR) || defined(PLAT_Unisoc) { MP_ROM_QSTR(MP_QSTR_setApn), MP_ROM_PTR(&qpy_net_set_apn_obj) }, { MP_ROM_QSTR(MP_QSTR_getApn), MP_ROM_PTR(&qpy_net_get_apn_obj) }, +//#endif + + { MP_ROM_QSTR(MP_QSTR_getServingCi), MP_ROM_PTR(&qpy_net_get_cid_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingLac), MP_ROM_PTR(&qpy_net_get_lac_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingMnc), MP_ROM_PTR(&qpy_net_get_mnc_servingcell_obj) }, + { MP_ROM_QSTR(MP_QSTR_getServingMcc), MP_ROM_PTR(&qpy_net_get_mcc_servingcell_obj) }, }; STATIC MP_DEFINE_CONST_DICT(net_module_globals, net_module_globals_table); diff --git a/ports/quectel/core/source/modquecIot.c b/ports/quectel/core/source/modquecIot.c deleted file mode 100644 index cc9f1f9..0000000 --- a/ports/quectel/core/source/modquecIot.c +++ /dev/null @@ -1,1134 +0,0 @@ -/************************************************************************* -** @author : -** @version : -** @date : -** @brief : 注意文件使用 UTF-8 编码 -***************************************************************************/ -#include "Ql_iotApi.h" -//#include "ql_iotDp.h" -#include "Qhal_driver.h" -//#include "ql_iotLocator.h" -#include "py/obj.h" -#include "py/objlist.h" -#include "py/objtuple.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mpz.h" -#include "py/objint.h" -#include "mpconfigport.h" - -#include "helios_os.h" -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdBusPassTransSend(mp_obj_t mp_mode, mp_obj_t mp_data) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - int mode = mp_obj_get_int(mp_mode); - mp_buffer_info_t data = {0}; - mp_get_buffer_raise(mp_data, &data, MP_BUFFER_READ); - if (data.len == 0) - { - return mp_obj_new_bool(FALSE); - } - if (FALSE == Ql_iotCmdBusPassTransSend(mode, (quint8_t *)data.buf, data.len)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotCmdBusPassTransSend_obj, qpy_Ql_iotCmdBusPassTransSend); - - - -//mpz -> 64bit integer for 32bit builds -static qint64_t mpz_to_64bit_int( const mp_obj_int_t* arg, bool is_signed ) -{ - static_assert( MPZ_DIG_SIZE == 16, "Expected MPZ_DIG_SIZE == 16" ); - - //see mpz_as_int_checked - const qint64_t maxCalcThreshold = is_signed ? 140737488355327 : 281474976710655; - - const mpz_t *i = &arg->mpz; - if( !is_signed && i->neg ) - { - mp_raise_TypeError(MP_ERROR_TEXT("Source integer must be unsigned")); - } - - short unsigned int *d = i->dig + i->len; - qint64_t val = 0; - - while( d-- > i->dig ) - { - if( val > maxCalcThreshold ) - { - mp_raise_ValueError(MP_ERROR_TEXT("Value too large for 64bit integer")); - } - val = ( val << MPZ_DIG_SIZE ) | *d; - } - - if( i->neg ) - { - val = -val; - } - return val; -} - -static qint64_t mp_obj_get_lint( mp_const_obj_t arg ) -{ - if( arg == mp_const_false ) - { - return 0u; - } - else if( arg == mp_const_true ) - { - return 1u; - } - else if( MP_OBJ_IS_SMALL_INT( arg ) ) - { - return MP_OBJ_SMALL_INT_VALUE( arg ); - } - else if( MP_OBJ_IS_TYPE( arg, &mp_type_int ) ) - { - return mpz_to_64bit_int( (mp_obj_int_t*) arg, 1); - } - else - { - mp_raise_TypeError(MP_ERROR_TEXT("unsigned integer")); - } - return 0u; -} - -static qbool phy_dict_handle(mp_obj_t mp_data, void **ttlvHead); -static qbool phy_list_handle(mp_obj_t mp_data, void **ttlvHead) -{ - size_t len = 0; - mp_obj_t *items = NULL; - mp_obj_list_get(mp_data, &len, &items); - if (len == 0) - { - return FALSE; - } - for (quint32_t i = 0; i < len; i++) - { - mp_obj_t id = mp_obj_new_int(0); - mp_obj_t value = items[i]; - if (mp_obj_is_bool(value)) - { - Ql_iotTtlvIdAddBool(ttlvHead, mp_obj_get_int(id), value == mp_const_true ? TRUE : FALSE); - } - else if (mp_obj_is_int(value)) - { - Ql_iotTtlvIdAddInt(ttlvHead, mp_obj_get_int(id), mp_obj_get_lint(value)); - } - else if (mp_obj_is_float(value)) - { - Ql_iotTtlvIdAddFloat(ttlvHead, mp_obj_get_int(id), mp_obj_get_float(value)); - } - else if(mp_obj_is_str(value) || mp_obj_is_type(value, &mp_type_bytearray) || mp_obj_is_type(value, &mp_type_bytes)) - { - mp_buffer_info_t data = {0}; - mp_get_buffer_raise(value, &data, MP_BUFFER_READ); - Ql_iotTtlvIdAddByte(ttlvHead, mp_obj_get_int(id), data.buf, data.len); - } - else if(mp_obj_is_type(value, &mp_type_dict)) - { - void *ttlvStructHead = NULL; - phy_dict_handle(value, &ttlvStructHead); - Ql_iotTtlvIdAddStruct(ttlvHead, mp_obj_get_int(id), ttlvStructHead); - } - else if(mp_obj_is_type(value, &mp_type_list) || mp_obj_is_type(value, &mp_type_tuple)) - { - void *ttlvStructHead = NULL; - phy_list_handle(value, &ttlvStructHead); - Ql_iotTtlvIdAddStruct(ttlvHead, mp_obj_get_int(id), ttlvStructHead); - } - else - { - printf("unknown type\r\n"); - return FALSE; - } - } - return TRUE; -} - -static qbool phy_dict_handle(mp_obj_t mp_data, void **ttlvHead) -{ - quint32_t index = 0; - mp_map_t *map = NULL; - mp_obj_t id = 0; - mp_obj_t value = 0; - if(!mp_obj_is_type(mp_data, &mp_type_dict)) - { - printf("need dict"); - return FALSE; - } - - map = mp_obj_dict_get_map(mp_data); - if (map == NULL) - { - printf("can't get map"); - return FALSE; - } - - for ( ; index < map->alloc; index++) - { - id = map->table[index].key; - value = map->table[index].value; - - if (id == MP_OBJ_NULL) - { - printf("id\r\n"); - if (index + (quint32_t)1 < map->alloc) - { - continue; - } - else if(index > 0) - { - return TRUE; - } - else - { - return FALSE; - } - } - if (mp_obj_is_bool(value)) - { - Ql_iotTtlvIdAddBool(ttlvHead, mp_obj_get_int(id), value == mp_const_true ? TRUE : FALSE); - } - else if (mp_obj_is_int(value)) - { - Ql_iotTtlvIdAddInt(ttlvHead, mp_obj_get_int(id), mp_obj_get_lint(value)); - } - else if (mp_obj_is_float(value)) - { - Ql_iotTtlvIdAddFloat(ttlvHead, mp_obj_get_int(id), mp_obj_get_float(value)); - } - else if(mp_obj_is_str(value) || mp_obj_is_type(value, &mp_type_bytearray) || mp_obj_is_type(value, &mp_type_bytes)) - { - mp_buffer_info_t data = {0}; - mp_get_buffer_raise(value, &data, MP_BUFFER_READ); - Ql_iotTtlvIdAddByte(ttlvHead, mp_obj_get_int(id), data.buf, data.len); - } - else if(mp_obj_is_type(value, &mp_type_dict)) - { - void *ttlvStructHead = NULL; - phy_dict_handle(value, &ttlvStructHead); - Ql_iotTtlvIdAddStruct(ttlvHead, mp_obj_get_int(id), ttlvStructHead); - } - else if(mp_obj_is_type(value, &mp_type_list) || mp_obj_is_type(value, &mp_type_tuple)) - { - void *ttlvStructHead = NULL; - phy_list_handle(value, &ttlvStructHead); - Ql_iotTtlvIdAddStruct(ttlvHead, mp_obj_get_int(id), ttlvStructHead); - } - else - { - printf("unknown type"); - return FALSE; - } - } - return TRUE; -} - - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdBusPhymodelReport(mp_obj_t mp_mode, mp_obj_t mp_data) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - - int mode = mp_obj_get_int(mp_mode); - mp_obj_t ret = mp_const_true; - void *ttlvHead = NULL; - if (phy_dict_handle(mp_data, &ttlvHead)) - { - if (NULL == ttlvHead || FALSE == Ql_iotCmdBusPhymodelReport(mode, ttlvHead)) - { - ret = mp_const_false; - } - } - else - { - ret = mp_const_false; - } - Ql_iotTtlvFree(&ttlvHead); - return ret; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotCmdBusPhymodelReport_obj, qpy_Ql_iotCmdBusPhymodelReport); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdBusPhymodelAck(mp_obj_t mp_mode, mp_obj_t mp_pkgid, mp_obj_t mp_data) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - int mode = mp_obj_get_int(mp_mode); - int pkgid = mp_obj_get_int(mp_pkgid); - mp_obj_t ret = mp_const_true; - void *ttlvHead = NULL; - if (phy_dict_handle(mp_data, &ttlvHead)) - { - if (NULL == ttlvHead || FALSE == Ql_iotCmdBusPhymodelAck(mode, (quint16_t)pkgid, ttlvHead)) - { - ret = mp_const_false; - } - } - else - { - ret = mp_const_false; - } - Ql_iotTtlvFree(&ttlvHead); - return ret; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_Ql_iotCmdBusPhymodelAck_obj, qpy_Ql_iotCmdBusPhymodelAck); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdOtaAction(mp_obj_t mp_action) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - int action = mp_obj_get_int(mp_action); - if (FALSE == Ql_iotCmdOtaAction(action)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotCmdOtaAction_obj, qpy_Ql_iotCmdOtaAction); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdOtaMcuFWDataRead(mp_obj_t mp_addr, mp_obj_t mp_len) -{ - quint32_t addr = mp_obj_get_int(mp_addr); - quint32_t len = mp_obj_get_int(mp_len); - // 2021-06-18 限制SOTA读取长度。因为读取长度过长,会导致模组dump。而且读取超过固件大小的长度也会先行申请内存,容易dump。 - if (Ql_iotGetWorkState() == 0 || len == 0 || len > Helios_GetAvailableMemorySize() / 3) - { - return mp_const_none; - } - void * data = NULL; - quint32_t ret = 0; - - data = malloc(len); - if (data == NULL) - { - mp_raise_OSError(MP_ENOMEM); - return mp_const_none; - } - if ((ret = Ql_iotCmdOtaMcuFWDataRead(addr, (quint8_t *)data, len)) > 0) - { - free(data); - return mp_obj_new_bytes((const unsigned char *)data, ret); - } - free(data); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotCmdOtaMcuFWDataRead_obj, qpy_Ql_iotCmdOtaMcuFWDataRead); -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdSysStatusReport(mp_obj_t mp_data) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - qbool ret = FALSE; - size_t count = 0; - mp_obj_t *items = NULL; - quint16_t *ids = NULL; - mp_obj_get_array(mp_data, &count, &items); - if (count && (ids = HAL_MALLOC(count * sizeof(sizeof(quint16_t)))) != NULL) - { - size_t i; - for (i = 0; i < count; i++) - { - ids[i] = mp_obj_get_int(items[i]); - } - ret = Ql_iotCmdSysStatusReport(ids, count); - HAL_FREE(ids); - } - return mp_obj_new_bool(ret ? TRUE : FALSE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotCmdSysStatusReport_obj, qpy_Ql_iotCmdSysStatusReport); -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotCmdSysDevInfoReport(mp_obj_t mp_data) -{ - if (Ql_iotGetWorkState() != QIOT_STATE_SUBSCRIBED) - { - return mp_obj_new_bool(FALSE); - } - qbool ret = FALSE; - size_t count = 0; - mp_obj_t *items = NULL; - quint16_t *ids = NULL; - mp_obj_get_array(mp_data, &count, &items); - if (count && (ids = HAL_MALLOC(count * sizeof(sizeof(quint16_t)))) != NULL) - { - size_t i; - for (i = 0; i < count; i++) - { - ids[i] = mp_obj_get_int(items[i]); - } - ret = Ql_iotCmdSysDevInfoReport(ids, count); - HAL_FREE(ids); - } - return mp_obj_new_bool(ret ? TRUE : FALSE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotCmdSysDevInfoReport_obj, qpy_Ql_iotCmdSysDevInfoReport); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -extern qbool Qhal_quecsdk_init(void); -STATIC mp_obj_t qpy_Ql_iotInit(void) -{ - if (Ql_iotGetWorkState() != 0) - { - return mp_const_false; - } - if (Qhal_quecsdk_init()) - { - return mp_const_true; - } - else - { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotInit_obj, qpy_Ql_iotInit); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetConnmode(mp_obj_t mode) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_obj_new_bool(FALSE); - } - if (FALSE == Ql_iotConfigSetConnmode(mp_obj_get_int(mode))) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotConfigSetConnmode_obj, qpy_Ql_iotConfigSetConnmode); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetConnmode(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - QIot_connMode_e mode = Ql_iotConfigGetConnmode(); - return mp_obj_new_int(mode); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetConnmode_obj, qpy_Ql_iotConfigGetConnmode); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetPdpContextId(mp_obj_t context_id) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_false; - } - if (FALSE == Ql_iotConfigSetPdpContextId((quint8_t)mp_obj_get_int(context_id))) - { - return mp_const_false; - } - return mp_const_true; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotConfigSetPdpContextId_obj, qpy_Ql_iotConfigSetPdpContextId); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetPdpContextId(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - quint8_t contextid = Ql_iotConfigGetPdpContextId(); - return mp_obj_new_int(contextid); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetPdpContextId_obj, qpy_Ql_iotConfigGetPdpContextId); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetServer(mp_obj_t type, mp_obj_t server) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_obj_new_bool(FALSE); - } - mp_buffer_info_t serverinfo = {0}; - mp_get_buffer_raise(server, &serverinfo, MP_BUFFER_READ); - if (FALSE == Ql_iotConfigSetServer(mp_obj_get_int(type), (const char *)serverinfo.buf)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotConfigSetServer_obj, qpy_Ql_iotConfigSetServer); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetServer(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - int type = 0; - char *server = NULL; - - Ql_iotConfigGetServer((QIot_protocolType_t *)&type, &server); - mp_obj_t url_info[2] = - { - mp_obj_new_int(type), - mp_obj_new_str(server, strlen(server)), - }; - return mp_obj_new_tuple(2, url_info); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetServer_obj, qpy_Ql_iotConfigGetServer); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetProductinfo(mp_obj_t product_key, mp_obj_t product_secret) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_obj_new_bool(FALSE); - } - mp_buffer_info_t keyinfo = {0}; - mp_buffer_info_t secretinfo = {0}; - mp_get_buffer_raise(product_key, &keyinfo, MP_BUFFER_READ); - mp_get_buffer_raise(product_secret, &secretinfo, MP_BUFFER_READ); - if (FALSE == Ql_iotConfigSetProductinfo((const char *)keyinfo.buf, (const char *)secretinfo.buf)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotConfigSetProductinfo_obj, qpy_Ql_iotConfigSetProductinfo); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetProductinfo(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - char *product_key = NULL; - char *product_secret = NULL; - char *product_ver = NULL; - - Ql_iotConfigGetProductinfo(&product_key, &product_secret, &product_ver); - mp_obj_t product_info[3] = - { - mp_obj_new_str(product_key, strlen(product_key)), - mp_obj_new_str(product_secret, strlen(product_secret)), - mp_obj_new_str(product_ver, strlen(product_ver))}; - return mp_obj_new_tuple(3, product_info); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetProductinfo_obj, qpy_Ql_iotConfigGetProductinfo); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetLifetime(mp_obj_t life_time) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_obj_new_bool(FALSE); - } - int lifetime = mp_obj_get_int(life_time); - if (FALSE == Ql_iotConfigSetLifetime(lifetime)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_Ql_iotConfigSetLifetime_obj, qpy_Ql_iotConfigSetLifetime); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetLifetime(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - quint32_t lifetime = Ql_iotConfigGetLifetime(); - return mp_obj_new_int_from_uint(lifetime); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetLifetime_obj, qpy_Ql_iotConfigGetLifetime); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigSetMcuVersion(mp_obj_t mp_compno, mp_obj_t mp_version) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_obj_new_bool(FALSE); - } - mp_buffer_info_t mcu_compno = {0}; - mp_buffer_info_t mcu_version = {0}; - mp_get_buffer_raise(mp_compno, &mcu_compno, MP_BUFFER_READ); - mp_get_buffer_raise(mp_version, &mcu_version, MP_BUFFER_READ); - if (FALSE == Ql_iotConfigSetMcuVersion((const char *)mcu_compno.buf, (const char *)mcu_version.buf)) - { - return mp_obj_new_bool(FALSE); - } - return mp_obj_new_bool(TRUE); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_Ql_iotConfigSetMcuVersion_obj, qpy_Ql_iotConfigSetMcuVersion); - -/************************************************************************** -** @brief : -** @param : -** @retval: -***************************************************************************/ -STATIC mp_obj_t qpy_Ql_iotConfigGetMcuVersion(void) -{ - if (Ql_iotGetWorkState() == 0) - { - return mp_const_none; - } - char *temp = NULL; - char *oldVer = NULL; - mp_obj_t objList = mp_obj_new_list(0, NULL); - Ql_iotConfigGetMcuVersion(NULL, &oldVer); - temp = HAL_MALLOC(HAL_STRLEN(oldVer) + 1); - if (temp) - { - char *words[100]; - HAL_SPRINTF(temp, "%s", oldVer); - quint32_t count = Quos_stringSplit(temp, words, sizeof(words) / sizeof(words[0]), ";", FALSE); - while (count--) - { - char *wordsnode[2]; - qint32_t nodeLen = Quos_stringSplit(words[count], wordsnode, sizeof(wordsnode) / sizeof(wordsnode[0]), ":", FALSE); - if (2 == nodeLen) - { - mp_obj_t node[] = - { - mp_obj_new_str(wordsnode[0], HAL_STRLEN(wordsnode[0])), - mp_obj_new_str(wordsnode[1], HAL_STRLEN(wordsnode[1])) - }; - mp_obj_list_append(objList, mp_obj_new_tuple(sizeof(node) / sizeof(node[0]), node)); - } - } - HAL_FREE(temp); - } - return objList; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotConfigGetMcuVersion_obj, qpy_Ql_iotConfigGetMcuVersion); - -static qbool ttlv_dict_handle(const void *ttlv_head, quint32_t count, mp_obj_t node_dict); -static qbool ttlv_array_handle(const void *ttlv_head, quint32_t count, mp_obj_t node_list) -{ - for (quint32_t i = 0; i < count; i++) - { - uint16_t id = 0; - int type = 0; - void *node = Ql_iotTtlvNodeGet(ttlv_head, i, &id, (QIot_dpDataType_e *)&type); - if(node) - { - switch (type) - { - case QIOT_DPDATA_TYPE_BOOL: - { - qbool bool_value; - Ql_iotTtlvNodeGetBool(node, &bool_value); - mp_obj_list_append(node_list, mp_obj_new_bool(bool_value)); - break; - } - case QIOT_DPDATA_TYPE_INT: - { - qint64_t num_value; - Ql_iotTtlvNodeGetInt(node, &num_value); - mp_obj_list_append(node_list, mp_obj_new_int_from_ll((long long)num_value)); - break; - } - case QIOT_DPDATA_TYPE_FLOAT: - { - double num_value; - Ql_iotTtlvNodeGetFloat(node, &num_value); - //(LL_DBG, LL_DBG,"FLOAT %f\r\n",num_value); - mp_obj_list_append(node_list, mp_obj_new_float((mp_float_t)num_value)); - break; - } - case QIOT_DPDATA_TYPE_BYTE: - { - quint8_t *value; - quint32_t len = Ql_iotTtlvNodeGetByte(node, &value); - mp_obj_list_append(node_list, mp_obj_new_bytes(value, len)); - break; - } - case QIOT_DPDATA_TYPE_STRUCT: - { - quint32_t struct_count = Ql_iotTtlvCountGet(node); - uint16_t temp_id = 0; - int temp_type = 0; - Ql_iotTtlvNodeGet(Ql_iotTtlvNodeGetStruct(node), 0, &temp_id, (QIot_dpDataType_e *)&temp_type); - if (temp_id == 0) - { - mp_obj_t struct_list = mp_obj_new_list(0, NULL); - ttlv_array_handle(Ql_iotTtlvNodeGetStruct(node), struct_count, struct_list); - mp_obj_list_append(node_list, struct_list); - } - else - { - mp_obj_t struct_dict = mp_obj_new_dict(struct_count); - ttlv_dict_handle(Ql_iotTtlvNodeGetStruct(node), struct_count, struct_dict); - mp_obj_list_append(node_list, struct_dict); - } - break; - } - default: - return FALSE; - break; - } - } - } - return TRUE; -} -static qbool ttlv_dict_handle(const void *ttlv_head, quint32_t count, mp_obj_t node_dict) -{ - for(quint32_t i=0; i 255) + { + mp_raise_ValueError("invalid value, seconds should be in [0-255]."); + } + + int ret = Helios_VoiceCall_Auto_Answer(0, seconds); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voice_auto_answer_obj, qpy_voicecall_auto_answer); + +//start call +STATIC mp_obj_t qpy_voicecall_start(mp_obj_t mp_obj_phone_num) +{ + char *phonenum = (char *)mp_obj_str_get_str(mp_obj_phone_num); + + int ret = Helios_VoiceCall_start(0, phonenum); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voice_call_start_obj, qpy_voicecall_start); + +//answer call +STATIC mp_obj_t qpy_voicecall_answer(void) +{ + int ret = Helios_VoiceCall_Answer(0); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_answer_obj, qpy_voicecall_answer); + +//end call +STATIC mp_obj_t qpy_voicecall_end(void) +{ + int ret = Helios_VoiceCall_End(0); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_end_obj, qpy_voicecall_end); + +STATIC mp_obj_t qpy_voicecall_start_dtmf(mp_obj_t mp_obj_dtmf, mp_obj_t mp_obj_duration) +{ + int ret = 0; + char *dtmf = (char *)mp_obj_str_get_str(mp_obj_dtmf); + int duration = mp_obj_get_int(mp_obj_duration); + + if (duration > 1000 || duration < 100) + { + mp_raise_ValueError("invalid value.duration shuould be in [100,1000]"); + } + + ret = Helios_VoiceCall_Start_Dtmf(0, dtmf, duration); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_voice_call_start_dtmf_obj, qpy_voicecall_start_dtmf); + +//fw set +STATIC mp_obj_t qpy_voicecall_fw_set(mp_obj_t mp_obj_reason, mp_obj_t mp_obj_fwmode, mp_obj_t mp_obj_phone_num) +{ + int reason = mp_obj_get_int(mp_obj_reason); + int fwmode = mp_obj_get_int(mp_obj_fwmode); + char *phonenum = (char *)mp_obj_str_get_str(mp_obj_phone_num); + + int ret = Helios_VoiceCall_Set_Fw(0, reason, fwmode, phonenum); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_fw_set_obj, qpy_voicecall_fw_set); + + +STATIC mp_obj_t qpy_voicecall_set_channel(mp_obj_t device) +{ + int channel = mp_obj_get_int(device); + + if ((channel < 0) || (channel > 2)) + { + mp_raise_ValueError("invalid device index, the value of device should be in[0,2]"); + } + + if (!audio_channel_check(channel)) + { + mp_raise_msg_varg(&mp_type_ValueError, "The current platform does not support device %d.", channel); + } + + int ret = Helios_Audio_SetAudioChannle(channel); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voicecall_set_channel_obj, qpy_voicecall_set_channel); + + +STATIC mp_obj_t qpy_voicecall_set_volume(mp_obj_t volume) +{ + int vol = mp_obj_get_int(volume); + if (vol < 0 || vol > 11) + { + mp_raise_ValueError("invalid value, the value of volume should be array between [0,11]"); + return mp_obj_new_int(-1); + } + + Helios_AudPlayerType type = 2; + int ret = Helios_Audio_SetVolume(type, vol); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voicecall_set_volume_obj, qpy_voicecall_set_volume); + + +STATIC mp_obj_t qpy_voicecall_get_volume(void) +{ + Helios_AudPlayerType type = 2; + int vol = Helios_Audio_GetVolume(type); + return mp_obj_new_int(vol); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voicecall_get_volume_obj, qpy_voicecall_get_volume); + + +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) +STATIC mp_obj_t qpy_voice_call_set_auto_record(size_t n_args, const mp_obj_t *args) +{ + int enable = mp_obj_get_int(args[0]); + int record_type = mp_obj_get_int(args[1]); + int record_mode = mp_obj_get_int(args[2]); + char *filename = (char *)mp_obj_str_get_str(args[3]); + + if ((enable != 0) && (enable != 1)) + mp_raise_ValueError("invalid value. should be [0 or 1]"); + if (record_type < 0 || record_type > 1) + mp_raise_ValueError("invalid value. should be [0 or 1]"); + if (record_mode < 0 || record_mode > 2) + mp_raise_ValueError("invalid value. should be [0 ~ 2]"); + if (filename == NULL) + mp_raise_ValueError("invalid value. must not be NULL"); + + Helios_Voicecall_Record_Process_t param = {0}; + param.record_type = record_type; + param.record_mode = record_mode; + strncpy(param.filename, filename, strlen(filename)); + HELIOS_VC_ERROR_CODE ret = Helios_Voicecall_Set_Auto_Record(enable, ¶m); + if (ret == HELIOS_VC_SUCCESS) + return mp_obj_new_int(0); + else if (ret == HELIOS_VC_FAILURE) + return mp_obj_new_int(-1); + else if (ret == HELIOS_VC_NOT_SUPPORT) + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); + else + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_voice_call_set_auto_record_obj, 4, 4, qpy_voice_call_set_auto_record); + +STATIC mp_obj_t qpy_voice_call_start_record(mp_obj_t mp_obj_recordtype, mp_obj_t mp_obj_recordmode, mp_obj_t mp_obj_filename) +{ + int record_type = mp_obj_get_int(mp_obj_recordtype); + int record_mode = mp_obj_get_int(mp_obj_recordmode); + char *filename = (char *)mp_obj_str_get_str(mp_obj_filename); + + if (record_type < 0 || record_type > 1) + mp_raise_ValueError("invalid value. should be [0 or 1]"); + if (record_mode < 0 || record_mode > 2) + mp_raise_ValueError("invalid value. should be [0 ~ 2]"); + if (filename == NULL) + mp_raise_ValueError("invalid value. must not be NULL"); + + Helios_Voicecall_Record_Process_t param = {0}; + param.record_type = record_type; + param.record_mode = record_mode; + strncpy(param.filename, filename, strlen(filename)); + + HELIOS_VC_ERROR_CODE ret = Helios_VoiceCall_Start_Record(¶m); + if (ret == HELIOS_VC_SUCCESS) + return mp_obj_new_int(0); + else if (ret == HELIOS_VC_FAILURE) + return mp_obj_new_int(-1); + else if (ret == HELIOS_VC_NOT_SUPPORT) + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); + else + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_start_record_obj, qpy_voice_call_start_record); + +STATIC mp_obj_t qpy_voice_call_stop_record() +{ + HELIOS_VC_ERROR_CODE ret = Helios_VoiceCall_Stop_Record(); + if (ret == HELIOS_VC_SUCCESS) + return mp_obj_new_int(0); + else if (ret == HELIOS_VC_FAILURE) + return mp_obj_new_int(-1); + else if (ret == HELIOS_VC_NOT_SUPPORT) + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); + else + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_stop_record_obj, qpy_voice_call_stop_record); +#endif + +static c_callback_t *g_record_callback = NULL; + +#if defined(PLAT_ASR)// || defined(PLAT_Unisoc) +helios_ring_buf_t *VC_stream_ring_buf = NULL; +#define RECORD_BUFFER_MAX (uint)10*1024 + +static int helios_stream_record_cb(char *p_data, int len, HELIOS_VC_AUD_REC_STATE res) +{ + /*if(res == HELIOS_VC_AUD_REC_START || res == HELIOS_VC_AUD_REC_FINISHED || res == HELIOS_VC_AUD_REC_DATA) { + + if(g_record_callback == NULL) { + return -1; + } + + mp_obj_t audio_cb[3] = { + mp_obj_new_str(p_data,strlen(p_data)), + mp_obj_new_int(len), + mp_obj_new_int(res), + }; + + mp_sched_schedule_ex(g_record_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(3, audio_cb))); + } + + return 0;*/ + unsigned int send_len = 0; + static int pcm_data_size = 0; - EDIT HISTORY FOR FILE -This section contains comments describing changes made to the module. -Notice that changes are listed in reverse chronological order. - -WHEN WHO WHAT,WHERE,WHY ----------- --------- --------------------------------------------------- -2021/07/20 Mia.zhong Create. -**************************************************************************/ - -#include "obj.h" -#include "runtime.h" -#include "mphalport.h" -#include "helios_debug.h" -#include "helios_voicecall.h" - - -#define QPY_MODVOICECALL_LOG(msg, ...) custom_log("VOICECALL", msg, ##__VA_ARGS__) - -//auto answer -STATIC mp_obj_t qpy_voicecall_auto_answer(mp_obj_t mp_obj_seconds) -{ - int seconds = mp_obj_get_int(mp_obj_seconds); - - if (seconds < 0 || seconds > 255) - { - mp_raise_ValueError("invalid value, seconds should be in [0-255]."); - } - - int ret = Helios_VoiceCall_Auto_Answer(0, seconds); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voice_auto_answer_obj, qpy_voicecall_auto_answer); - -//start call -STATIC mp_obj_t qpy_voicecall_start(mp_obj_t mp_obj_phone_num) -{ - char *phonenum = (char *)mp_obj_str_get_str(mp_obj_phone_num); - - int ret = Helios_VoiceCall_start(0, phonenum); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voice_call_start_obj, qpy_voicecall_start); - -//answer call -STATIC mp_obj_t qpy_voicecall_answer(void) -{ - int ret = Helios_VoiceCall_Answer(0); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_answer_obj, qpy_voicecall_answer); - -//end call -STATIC mp_obj_t qpy_voicecall_end(void) -{ - int ret = Helios_VoiceCall_End(0); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_end_obj, qpy_voicecall_end); - -STATIC mp_obj_t qpy_voicecall_start_dtmf(mp_obj_t mp_obj_dtmf, mp_obj_t mp_obj_duration) -{ - int ret = 0; - char *dtmf = (char *)mp_obj_str_get_str(mp_obj_dtmf); - int duration = mp_obj_get_int(mp_obj_duration); - - if (duration > 1000 || duration < 100) - { - mp_raise_ValueError("invalid value.duration shuould be in [100,1000]"); - } - - ret = Helios_VoiceCall_Start_Dtmf(0, dtmf, duration); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_voice_call_start_dtmf_obj, qpy_voicecall_start_dtmf); - -//fw set -STATIC mp_obj_t qpy_voicecall_fw_set(mp_obj_t mp_obj_reason, mp_obj_t mp_obj_fwmode, mp_obj_t mp_obj_phone_num) -{ - int reason = mp_obj_get_int(mp_obj_reason); - int fwmode = mp_obj_get_int(mp_obj_fwmode); - char *phonenum = (char *)mp_obj_str_get_str(mp_obj_phone_num); - int ret = Helios_VoiceCall_Set_Fw(0, reason, fwmode, phonenum); - - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_fw_set_obj, qpy_voicecall_fw_set); - -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) -STATIC mp_obj_t qpy_voice_call_set_auto_record(size_t n_args, const mp_obj_t *args) -{ - int enable = mp_obj_get_int(args[0]); - int record_type = mp_obj_get_int(args[1]); - int record_mode = mp_obj_get_int(args[2]); - char *filename = (char *)mp_obj_str_get_str(args[3]); - - if ((enable != 0) && (enable != 1)) - mp_raise_ValueError("invalid value. should be [0 or 1]"); - if (record_type < 0 || record_type > 1) - mp_raise_ValueError("invalid value. should be [0 or 1]"); - if (record_mode < 0 || record_mode > 2) - mp_raise_ValueError("invalid value. should be [0 ~ 2]"); - if (filename == NULL) - mp_raise_ValueError("invalid value. must not be NULL"); - - Helios_Voicecall_Record_Process_t param = {0}; - param.record_type = record_type; - param.record_mode = record_mode; - strncpy(param.filename, filename, strlen(filename)); - HELIOS_VC_ERROR_CODE ret = Helios_Voicecall_Set_Auto_Record(enable, ¶m); - if (ret == HELIOS_VC_SUCCESS) - return mp_obj_new_int(0); - else if (ret == HELIOS_VC_FAILURE) - return mp_obj_new_int(-1); - else if (ret == HELIOS_VC_NOT_SUPPORT) - return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); - else - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_voice_call_set_auto_record_obj, 4, 4, qpy_voice_call_set_auto_record); - -STATIC mp_obj_t qpy_voice_call_start_record(mp_obj_t mp_obj_recordtype, mp_obj_t mp_obj_recordmode, mp_obj_t mp_obj_filename) -{ - int record_type = mp_obj_get_int(mp_obj_recordtype); - int record_mode = mp_obj_get_int(mp_obj_recordmode); - char *filename = (char *)mp_obj_str_get_str(mp_obj_filename); - - if (record_type < 0 || record_type > 1) - mp_raise_ValueError("invalid value. should be [0 or 1]"); - if (record_mode < 0 || record_mode > 2) - mp_raise_ValueError("invalid value. should be [0 ~ 2]"); - if (filename == NULL) - mp_raise_ValueError("invalid value. must not be NULL"); - - Helios_Voicecall_Record_Process_t param = {0}; - param.record_type = record_type; - param.record_mode = record_mode; - strncpy(param.filename, filename, strlen(filename)); - - HELIOS_VC_ERROR_CODE ret = Helios_VoiceCall_Start_Record(¶m); - if (ret == HELIOS_VC_SUCCESS) - return mp_obj_new_int(0); - else if (ret == HELIOS_VC_FAILURE) - return mp_obj_new_int(-1); - else if (ret == HELIOS_VC_NOT_SUPPORT) - return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); - else - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_start_record_obj, qpy_voice_call_start_record); - -STATIC mp_obj_t qpy_voice_call_stop_record() -{ - HELIOS_VC_ERROR_CODE ret = Helios_VoiceCall_Stop_Record(); - if (ret == HELIOS_VC_SUCCESS) - return mp_obj_new_int(0); - else if (ret == HELIOS_VC_FAILURE) - return mp_obj_new_int(-1); - else if (ret == HELIOS_VC_NOT_SUPPORT) - return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); - else - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_voice_call_stop_record_obj, qpy_voice_call_stop_record); -#endif - -static c_callback_t *g_voice_call_callback = NULL; - -static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *ctx) -{ - printf("voicecall event_id=%ld\n",event_id); - - switch(event_id) + if(res == HELIOS_VC_AUD_REC_START) + { + //audio_record_printf("recorder start run"); + pcm_data_size = 0; + } + else if(res == HELIOS_VC_AUD_REC_FINISHED) + { + //audio_record_printf("recorder stop run"); + + } + else if(res == HELIOS_VC_AUD_REC_DATA) { - case HELIOS_VC_RING_IND: - { - Helios_call_incoming *vc_info = (Helios_call_incoming *)ctx; - if (ctx) - { - char phone_num[20] = {0}; - memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); - - mp_obj_t tuple[3] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_str(phone_num,strlen(phone_num)) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); - } - } - } - break; - - case HELIOS_VC_CONNECT_IND: - { - Helios_call_connect *vc_info = (Helios_call_connect *)ctx; - if (ctx) - { - char phone_num[20] = {0}; - memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); - - mp_obj_t tuple[3] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_str(phone_num,strlen(phone_num)) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); - } - } - } - break; - - case HELIOS_VC_NOCARRIER_IND: //no carrier reason - { - Helios_call_disconnect *vc_info = (Helios_call_disconnect *)ctx; - if (ctx) - { - mp_obj_t tuple[3] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_int(vc_info->cause) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); - } - } - } - break; - - case HELIOS_VC_CCWA_IND: - { - Helios_call_waiting *vc_info = (Helios_call_waiting *)ctx; - if (ctx) - { - char phone_num[40] = {0}; - memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); - mp_obj_t tuple[5] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_str(vc_info->phone_num, strlen(vc_info->phone_num)), - mp_obj_new_int(vc_info->num_type), - mp_obj_new_int(vc_info->CliValidity) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(5, tuple)); - } - } - } - break; - - case HELIOS_VC_DIALING_IND: - { - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_int(event_id)); - } - } - break; + if(len <= 0 || VC_stream_ring_buf == NULL) + return -1; - case HELIOS_VC_MO_FAILED_IND: - { - Helios_call_mo_failed *vc_info = (Helios_call_mo_failed *)ctx; - if (ctx) - { - mp_obj_t tuple[4] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_int(vc_info->Cause), - mp_obj_new_int(vc_info->InBandTones) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(4, tuple)); - } - } - } - break; + send_len = helios_rb_write(VC_stream_ring_buf, (unsigned char*)p_data, len); - case HELIOS_VC_HOLDING_IND: - { - Helios_call_holding *vc_info = (Helios_call_holding *)ctx; - if (ctx) - { - char phone_num[20] = {0}; - memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); - - mp_obj_t tuple[3] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->CallId), - mp_obj_new_str(phone_num,strlen(phone_num)) - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); - } - } - } - break; + pcm_data_size += send_len; + } - case HELIOS_VC_RING_VOLTE_IND: - case HELIOS_VC_CONNECT_VOLTE_IND: - case HELIOS_VC_NOCARRIER_VOLTE_IND: - case HELIOS_VC_CCWA_VOLTE_IND: - case HELIOS_VC_DIALING_VOLTE_IND: - case HELIOS_VC_ALERTING_VOLTE_IND: - case HELIOS_VC_HOLDING_VOLTE_IND: - { - Helios_call_volte *vc_info = (Helios_call_volte *)ctx; - if (ctx) - { - char phone_num[40] = {0}; - memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); - mp_obj_t tuple[9] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(vc_info->id), - mp_obj_new_int(vc_info->dir), - mp_obj_new_int(vc_info->status), - mp_obj_new_int(vc_info->type), - mp_obj_new_int(vc_info->mpty), - mp_obj_new_str(vc_info->phone_num, strlen(vc_info->phone_num)), - mp_obj_new_int(vc_info->num_type), - mp_obj_new_int(vc_info->release_direction), - }; - if (g_voice_call_callback) - { - mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(9, tuple)); - } - } - } - break; - - default: - break; + if(res == HELIOS_VC_AUD_REC_START || res == HELIOS_VC_AUD_REC_FINISHED || res == HELIOS_VC_AUD_REC_DATA) { + + if(g_record_callback == NULL) { + return -1; + } + + if(res == HELIOS_VC_AUD_REC_FINISHED) send_len = pcm_data_size; + #if MICROPY_ENABLE_CALLBACK_DEAL + st_CallBack_AudioRecord *record = malloc(sizeof(st_CallBack_AudioRecord)); + if(NULL != record) { + record->record_type = RECORE_TYPE_STREAM; + record->p_data = "stream"; + record->len = send_len; + record->res = res; + record->callback = *g_record_callback; + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_VOICECALL_RECORD, record); + } + #else + char* p_data_buf = "stream"; + mp_obj_t audio_cb[3] = { + mp_obj_new_str(p_data_buf,strlen(p_data_buf)), + mp_obj_new_int(send_len), + mp_obj_new_int(res), + }; + + mp_sched_schedule_ex(g_record_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(3, audio_cb))); + #endif } -} -STATIC mp_obj_t qpy_voicecall_add_event_handler(mp_obj_t handler) + return 0; +} + +STATIC mp_obj_t qpy_voice_call_start_record_stream(mp_obj_t mp_obj_recordtype, mp_obj_t mp_obj_recordmode, mp_obj_t mp_obj_cb) +{ + int record_type = mp_obj_get_int(mp_obj_recordtype); + int record_mode = mp_obj_get_int(mp_obj_recordmode); + + if (record_type < 0 || record_type > 1) + mp_raise_ValueError("invalid value. should be [0 or 1]"); + if (record_mode < 0 || record_mode > 2) + mp_raise_ValueError("invalid value. should be [0 ~ 2]"); + + Helios_Voicecall_Record_Process_t param = {0}; + param.record_type = record_type; + param.record_mode = record_mode; + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_record_callback = &cb; + mp_sched_schedule_callback_register(g_record_callback, mp_obj_cb); + + if(VC_stream_ring_buf == NULL) { + VC_stream_ring_buf = helios_rb_create(RECORD_BUFFER_MAX); + } + + HELIOS_VC_ERROR_CODE ret = Helios_VoiceCall_Start_Record_Stream(¶m, (helios_vc_cb_on_record)helios_stream_record_cb); + if (ret == HELIOS_VC_SUCCESS) + return mp_obj_new_int(0); + else if (ret == HELIOS_VC_FAILURE) + return mp_obj_new_int(-1); + else if (ret == HELIOS_VC_NOT_SUPPORT) + return mp_obj_new_str("NOT SUPPORT",strlen("NOT SUPPORT")); + else + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_start_record_stream_obj, qpy_voice_call_start_record_stream); + +STATIC mp_obj_t qpy_voice_call_record_stream_read(mp_obj_t read_buf, mp_obj_t len) { - Helios_VoiceCallInitStruct info = {0}; - static c_callback_t cb = {0}; - memset(&cb, 0, sizeof(c_callback_t)); - info.user_cb = ql_voice_call_EventHandler; - //g_voice_call_callback = handler; - - g_voice_call_callback = &cb; - mp_sched_schedule_callback_register(g_voice_call_callback, handler); - Helios_VoiceCall_Register(&info); - - return mp_obj_new_int(0); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voicecall_add_event_handler_obj, qpy_voicecall_add_event_handler); + int read_actual_len = 0; + //audio_record_obj_t *self = MP_OBJ_TO_PTR(self_in); -STATIC mp_obj_t qpy_module_voicecall_deinit(void) -{ - g_voice_call_callback = NULL; - Helios_VoiceCallInitStruct info = {0}; - info.user_cb = NULL; - Helios_VoiceCall_Register(&info); - return mp_obj_new_int(0); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(read_buf, &bufinfo, MP_BUFFER_WRITE); + + int read_len = mp_obj_get_int(len); + if(read_len > 0 && VC_stream_ring_buf) { + read_actual_len = helios_rb_read(VC_stream_ring_buf, bufinfo.buf, read_len); + return mp_obj_new_int(read_actual_len); + } + return mp_obj_new_int(-1); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_voicecall_deinit_obj, qpy_module_voicecall_deinit); - - -STATIC const mp_rom_map_elem_t mp_module_voicecall_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_voiceCall) }, - { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_voicecall_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_setAutoAnswer), MP_ROM_PTR(&qpy_voice_auto_answer_obj) }, - { MP_ROM_QSTR(MP_QSTR_callStart), MP_ROM_PTR(&qpy_voice_call_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_callAnswer), MP_ROM_PTR(&qpy_voice_call_answer_obj) }, - { MP_ROM_QSTR(MP_QSTR_callEnd), MP_ROM_PTR(&qpy_voice_call_end_obj) }, - { MP_ROM_QSTR(MP_QSTR_startDtmf), MP_ROM_PTR(&qpy_voice_call_start_dtmf_obj) }, - { MP_ROM_QSTR(MP_QSTR_setFw), MP_ROM_PTR(&qpy_voice_call_fw_set_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_voicecall_add_event_handler_obj) }, -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) - { MP_ROM_QSTR(MP_QSTR_setAutoRecord), MP_ROM_PTR(&qpy_voice_call_set_auto_record_obj) }, - { MP_ROM_QSTR(MP_QSTR_startRecord), MP_ROM_PTR(&qpy_voice_call_start_record_obj) }, - { MP_ROM_QSTR(MP_QSTR_stopRecord), MP_ROM_PTR(&qpy_voice_call_stop_record_obj) }, -#endif -}; -STATIC MP_DEFINE_CONST_DICT(mp_module_voicecall_globals, mp_module_voicecall_globals_table); - - -const mp_obj_module_t mp_module_voicecall = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_voicecall_globals, -}; - - - - +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_voice_call_record_stream_read_obj, qpy_voice_call_record_stream_read); +#endif + +static c_callback_t *g_voice_call_callback = NULL; + +static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *ctx) +{ + printf("voicecall event_id=%ld\n",event_id); + + switch(event_id) + { + case HELIOS_VC_RING_IND: + { + Helios_call_incoming *vc_info = (Helios_call_incoming *)ctx; + if (ctx) + { + char phone_num[20] = {0}; + memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); + + mp_obj_t tuple[3] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_str(phone_num,strlen(phone_num)) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + } + } + } + break; + + case HELIOS_VC_CONNECT_IND: + { + Helios_call_connect *vc_info = (Helios_call_connect *)ctx; + if (ctx) + { + char phone_num[20] = {0}; + memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); + + mp_obj_t tuple[3] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_str(phone_num,strlen(phone_num)) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + } + } + } + break; + + case HELIOS_VC_NOCARRIER_IND: //no carrier reason + { + Helios_call_disconnect *vc_info = (Helios_call_disconnect *)ctx; + if (ctx) + { + mp_obj_t tuple[3] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_int(vc_info->cause) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + } + } + } + break; + + case HELIOS_VC_CCWA_IND: + { + Helios_call_waiting *vc_info = (Helios_call_waiting *)ctx; + if (ctx) + { + char phone_num[40] = {0}; + memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); + mp_obj_t tuple[5] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_str(vc_info->phone_num, strlen(vc_info->phone_num)), + mp_obj_new_int(vc_info->num_type), + mp_obj_new_int(vc_info->CliValidity) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(5, tuple)); + } + } + } + break; + + case HELIOS_VC_DIALING_IND: + { + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_int(event_id)); + } + } + break; + + case HELIOS_VC_MO_FAILED_IND: + { + Helios_call_mo_failed *vc_info = (Helios_call_mo_failed *)ctx; + if (ctx) + { + mp_obj_t tuple[4] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_int(vc_info->Cause), + mp_obj_new_int(vc_info->InBandTones) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(4, tuple)); + } + } + } + break; + + case HELIOS_VC_HOLDING_IND: + { + Helios_call_holding *vc_info = (Helios_call_holding *)ctx; + if (ctx) + { + char phone_num[20] = {0}; + memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); + + mp_obj_t tuple[3] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->CallId), + mp_obj_new_str(phone_num,strlen(phone_num)) + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + } + } + } + break; + + case HELIOS_VC_RING_VOLTE_IND: + case HELIOS_VC_CONNECT_VOLTE_IND: + case HELIOS_VC_NOCARRIER_VOLTE_IND: + case HELIOS_VC_CCWA_VOLTE_IND: + case HELIOS_VC_DIALING_VOLTE_IND: + case HELIOS_VC_ALERTING_VOLTE_IND: + case HELIOS_VC_HOLDING_VOLTE_IND: + { + Helios_call_volte *vc_info = (Helios_call_volte *)ctx; + if (ctx) + { + char phone_num[40] = {0}; + memcpy(phone_num, vc_info->phone_num, strlen(vc_info->phone_num)); + mp_obj_t tuple[9] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(vc_info->id), + mp_obj_new_int(vc_info->dir), + mp_obj_new_int(vc_info->status), + mp_obj_new_int(vc_info->type), + mp_obj_new_int(vc_info->mpty), + mp_obj_new_str(vc_info->phone_num, strlen(vc_info->phone_num)), + mp_obj_new_int(vc_info->num_type), + mp_obj_new_int(vc_info->release_direction), + }; + if (g_voice_call_callback) + { + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(9, tuple)); + } + } + } + break; + + default: + break; + } +} + +STATIC mp_obj_t qpy_voicecall_add_event_handler(mp_obj_t handler) +{ + Helios_VoiceCallInitStruct info = {0}; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + info.user_cb = ql_voice_call_EventHandler; + //g_voice_call_callback = handler; + + g_voice_call_callback = &cb; + mp_sched_schedule_callback_register(g_voice_call_callback, handler); + Helios_VoiceCall_Register(&info); + + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_voicecall_add_event_handler_obj, qpy_voicecall_add_event_handler); + +STATIC mp_obj_t qpy_module_voicecall_deinit(void) +{ +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + Helios_VoiceCall_Stop_Record(); +#endif + Helios_VoiceCall_End(0); + + g_voice_call_callback = NULL; + g_record_callback = NULL; + + Helios_VoiceCallInitStruct info = {0}; + info.user_cb = NULL; + Helios_VoiceCall_Register(&info); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_voicecall_deinit_obj, qpy_module_voicecall_deinit); + + +STATIC const mp_rom_map_elem_t mp_module_voicecall_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_voiceCall) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_voicecall_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_setAutoAnswer), MP_ROM_PTR(&qpy_voice_auto_answer_obj) }, + { MP_ROM_QSTR(MP_QSTR_callStart), MP_ROM_PTR(&qpy_voice_call_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_callAnswer), MP_ROM_PTR(&qpy_voice_call_answer_obj) }, + { MP_ROM_QSTR(MP_QSTR_callEnd), MP_ROM_PTR(&qpy_voice_call_end_obj) }, + { MP_ROM_QSTR(MP_QSTR_startDtmf), MP_ROM_PTR(&qpy_voice_call_start_dtmf_obj) }, + { MP_ROM_QSTR(MP_QSTR_setFw), MP_ROM_PTR(&qpy_voice_call_fw_set_obj) }, + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_voicecall_add_event_handler_obj) }, + { MP_ROM_QSTR(MP_QSTR_setChannel), MP_ROM_PTR(&qpy_voicecall_set_channel_obj) }, + { MP_ROM_QSTR(MP_QSTR_setVolume), MP_ROM_PTR(&qpy_voicecall_set_volume_obj) }, + { MP_ROM_QSTR(MP_QSTR_getVolume), MP_ROM_PTR(&qpy_voicecall_get_volume_obj) }, +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + { MP_ROM_QSTR(MP_QSTR_setAutoRecord), MP_ROM_PTR(&qpy_voice_call_set_auto_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_startRecord), MP_ROM_PTR(&qpy_voice_call_start_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_stopRecord), MP_ROM_PTR(&qpy_voice_call_stop_record_obj) }, +#endif +#if defined(PLAT_ASR)// || defined(PLAT_Unisoc) + { MP_ROM_QSTR(MP_QSTR_startRecordStream), MP_ROM_PTR(&qpy_voice_call_start_record_stream_obj) }, + { MP_ROM_QSTR(MP_QSTR_readRecordStream), MP_ROM_PTR(&qpy_voice_call_record_stream_read_obj) }, +#endif + +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_voicecall_globals, mp_module_voicecall_globals_table); + + +const mp_obj_module_t mp_module_voicecall = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_voicecall_globals, +}; + + + + + diff --git a/ports/quectel/core/source/modwifilocator.c b/ports/quectel/core/source/modwifilocator.c new file mode 100644 index 0000000..c3081d0 --- /dev/null +++ b/ports/quectel/core/source/modwifilocator.c @@ -0,0 +1,902 @@ +/* + * Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "helios_datacall.h" +#include "helios_celllocator.h" +#include "helios_debug.h" +#include "quos_md5.h" + +#include "modwifilocator.h" + +#define QPY_MODLBS_LOG(msg, ...) custom_log(wifilocator, msg, ##__VA_ARGS__) +#define WIFI_LOWER_CASE( c ) ( ((c) >= 'A' && (c) <= 'Z') ? ((c) + 0x20) : (c) ) + +STATIC Helios_LBSInfoStruct position_rec = {0}; + +STATIC bool checkCPUendian() +{ + union{ + uint32_t i; + uint8_t s[4]; + }u_test; + u_test.i = 0x12345678; + return (0x12 == u_test.s[0]); +} + +STATIC uint16_t HtoN_uint16(uint16_t h) +{ + return checkCPUendian() ? h : BigLittleSwap16(h); +} + +STATIC int16_t HtoN_int16(int16_t h) +{ + return (int16_t)checkCPUendian() ? h : BigLittleSwap16(h); +} + +STATIC uint8_t* ber_length_serialize(int32_t tlen, uint8_t *bufptr, int32_t* len) +{ + uint8_t *start_data = bufptr; + int32_t len_size = *len; + + //TLV_ASSERT(len != 0 && bufptr != 0); + + /* no indefinite lengths sent */ + if (tlen < 0x80) + { + if (len_size < 1) + { + return NULL; + } + *bufptr++ = (uint8_t)tlen; + } + else if (tlen <= 0xFF) + { + if (len_size < 2) + { + return NULL; + } + *bufptr++ = (uint8_t)(0x01 | BER_LONG_LEN); + *bufptr++ = (uint8_t)tlen; + } + else if (tlen <= 0xFFFF) + { /* 0xFF < tlen <= 0xFFFF */ + if (len_size < 3) + { + return NULL; + } + *bufptr++ = (uint8_t)(0x02 | BER_LONG_LEN); + *bufptr++ = (uint8_t)((tlen >> 8) & 0xFF); + *bufptr++ = (uint8_t)(tlen & 0xFF); + } + else if (tlen <= 0xFFFFFF) + { /* 0xFF < tlen <= 0xFFFF */ + if (len_size < 4) + { + return NULL; + } + *bufptr++ = (uint8_t)(0x03 | BER_LONG_LEN); + *bufptr++ = (uint8_t)((tlen >> 16) & 0xFF); + *bufptr++ = (uint8_t)((tlen >> 8) & 0xFF); + *bufptr++ = (uint8_t)(tlen & 0xFF); + } + else + { + if (len_size < 5) + { + return NULL; + } + *bufptr++ = (uint8_t)(0x04 | BER_LONG_LEN); + *bufptr++ = (uint8_t)((tlen >> 24) & 0xFF); + *bufptr++ = (uint8_t)((tlen >> 16) & 0xFF); + *bufptr++ = (uint8_t)((tlen >> 8) & 0xFF); + *bufptr++ = (uint8_t)(tlen & 0xFF); + } + + *len = (int32_t)(bufptr-start_data); + return bufptr; +} + +STATIC uint8_t* ber_tag_serialize(ber_class_tag tclass, ber_construct_tag tconstructed, uint32_t tval, uint8_t *bufp, int32_t* len) +{ + uint8_t *buf = (uint8_t *)bufp; + uint8_t *end = NULL; + int32_t tag_len = *len; + int32_t required_size = 1; + int32_t i = 0; + + if(len == 0 || bufp == 0) + { + return NULL; + } + + if(tval <= 30) + { + /* Encoded in 1 octet */ + if(tag_len) + buf[0] = (tclass << 6) | (tconstructed << 5) | tval; + *len = 1; + return bufp; + } + else if(tag_len) + { + *buf++ = (tclass << 6) | (tconstructed << 5) |0x1F; + tag_len--; + } + + /* + * Compute the size of the subsequent bytes. + */ + int32_t size = (int32_t)8 * sizeof(tval); + for(required_size = 1, i = 7; i < size; i += 7) { + if(tval >> i) + required_size++; + else + break; + } + + if(tag_len < required_size) + return NULL; + + /* + * Fill in the buffer, space permitting. + */ + end = buf + required_size - 1; + for(i -= 7; buf < end; i -= 7, buf++) + *buf = 0x80 | ((tval >> i) & 0x7F); + *buf = (tval & 0x7F); /* Last octet without high bit */ + + *len = required_size + 1; + return buf; +} + +STATIC int32_t tlv_serialize_tlv_buffer(const ber_tlv_tag* tlvtag, int32_t tlvlen,const uint8_t* tlvvalue, + int32_t valuesize, uint8_t** retbuf) +{ + uint8_t tagbuf[32] = {0}; + int32_t taglen = sizeof(tagbuf); + uint8_t lenbuf[32] = {0}; + int32_t lensize = sizeof(lenbuf); + uint8_t* alloc_buf = NULL; + + if(!ber_tag_serialize(tlvtag->class_tag, tlvtag->construct_tag, tlvtag->tag_value, tagbuf, &taglen)) + { + QPY_MODLBS_LOG("ber_tag_serialize Fail \r\n"); + return -1; + } + + if(!ber_length_serialize(tlvlen,lenbuf,&lensize)) + { + QPY_MODLBS_LOG("ber_length_serialize Fail \r\n"); + return -1; + } + + *retbuf = (uint8_t*)malloc(taglen+lensize+valuesize); + if(!*retbuf) + { + QPY_MODLBS_LOG("apptcpip_mem_malloc Fail \r\n"); + return -1; + } + alloc_buf = *retbuf; + memcpy(alloc_buf,tagbuf,taglen); + alloc_buf += taglen; + memcpy(alloc_buf,lenbuf,lensize); + alloc_buf += lensize; + memcpy(alloc_buf,tlvvalue,valuesize); + return(taglen+lensize+valuesize); +} + +STATIC uint32_t QTlv_Serialize_BaseInfo_Buf(tlv_baseinfo_struct* pBaseInfo, uint8_t *retBuffer) +{ + uint32_t data_len = 0; + + if(pBaseInfo == NULL || retBuffer == NULL) + { + return 0; + } + + memcpy(retBuffer, &(pBaseInfo->serve_type),sizeof(pBaseInfo->serve_type)); + data_len += sizeof(pBaseInfo->serve_type); + memcpy(retBuffer+data_len, &(pBaseInfo->encript_type),sizeof(pBaseInfo->encript_type)); + data_len += sizeof(pBaseInfo->encript_type); + memcpy(retBuffer+data_len, &(pBaseInfo->key_index),sizeof(pBaseInfo->key_index)); + data_len += sizeof(pBaseInfo->key_index); + memcpy(retBuffer+data_len, &(pBaseInfo->pos_data_type),sizeof(pBaseInfo->pos_data_type)); + data_len += sizeof(pBaseInfo->pos_data_type); + memcpy(retBuffer+data_len, &(pBaseInfo->loc_method),sizeof(pBaseInfo->loc_method)); + data_len += sizeof(pBaseInfo->loc_method); + + return data_len; +} + +STATIC uint32_t QTlv_Serialize_AuthInfo_Buf(bool bWithPwd, uint8_t *retBuffer, QTlvAuthInfo *authInfo) +{ + int16_t net_order = 0; + uint32_t data_len = 0; + uint32_t tmpLen = 0; + + tmpLen = strlen((const char *)authInfo->name); + memcpy(retBuffer, authInfo->name, tmpLen); + data_len = tmpLen; + + if(1 == bWithPwd) + { + tmpLen = strlen((const char *)authInfo->pwd); + memcpy(retBuffer+data_len, authInfo->pwd, tmpLen); + data_len += tmpLen; + } + + /* IMEI*/ + tmpLen = AUTH_IMEI_LEN; + memcpy(retBuffer+data_len, authInfo->imei, tmpLen); + data_len += tmpLen; + + if(strlen((const char *)authInfo->token) > 0) + { + memcpy(retBuffer+data_len, authInfo->token, AUTH_TOTKEN_LEN); + data_len += AUTH_TOTKEN_LEN; + } + + net_order = (int16_t)HtoN_uint16((uint16_t)(authInfo->rand)); + memcpy(retBuffer+data_len,&net_order,sizeof(net_order)); + data_len += sizeof(net_order); + + return data_len; +} + +STATIC void QTlv_data_encryption_xor(uint8_t keyIndex, const uint8_t* src, uint8_t* dest, uint32_t len) +{ + uint32_t keyRewind = 0; + uint32_t i = 0; + + for (i=0; i < len; i++) + { + if(keyRewind >= XOR_KEY_LEN) + keyRewind = 0; + dest[i] = src[i] ^ xor_key[keyIndex][keyRewind++]; + } +} + +STATIC uint8_t* tlv_realloc_memory(uint8_t* buf1, uint32_t buf1Len, uint8_t* buf2, uint32_t buf2Len) +{ + uint8_t* newBuf = NULL; + + newBuf = (uint8_t*)malloc(buf1Len+buf2Len); + if (!newBuf) + { + return NULL; + } + // 合并内存 + memcpy(newBuf, buf1, buf1Len); + memcpy(newBuf+buf1Len, buf2, buf2Len); + // 释放内存 + free((void *)buf1); + free((void *)buf2); + buf2 = NULL; + buf1 = newBuf; + + return newBuf; +} + +STATIC uint32_t QTlv_Serialize_WifiInfo_Buf(tlv_wifiinfo_struct *wifiInfo, uint8_t *retBuffer) +{ + uint32_t data_len = 0; + uint32_t tmpLen = 0; + uint16_t net_order_16 = 0; + + tmpLen = 17; + memcpy(retBuffer,wifiInfo->mac,tmpLen); + data_len += tmpLen; + tmpLen = strlen((const char*)wifiInfo->ssid); + memcpy(retBuffer+data_len,wifiInfo->ssid,tmpLen); + data_len += tmpLen; + + net_order_16 = HtoN_int16(wifiInfo->rssi); + memcpy(retBuffer+data_len,&net_order_16,sizeof(net_order_16)); + data_len += sizeof(net_order_16); + return data_len; +} + +STATIC void wifi_hex_to_str(unsigned char *pbDest, unsigned char *pbSrc, int nLen) +{ + char ddl,ddh; + int i; + + for (i=0; i 57) ddh = ddh + 7; + if (ddl > 57) ddl = ddl + 7; + pbDest[i*2] = WIFI_LOWER_CASE(ddh); + pbDest[i*2+1] = WIFI_LOWER_CASE(ddl); + } + pbDest[nLen*2] = '\0'; +} + +STATIC mp_obj_t wifi_locreqencode(size_t n_args, const mp_obj_t *args) +{ + uint8_t i = 0; + uint8_t* buf_1 = NULL; + uint8_t* buf_2 = NULL; + int buf_len_1 = 0; + int buf_len_2 = 0; + int len = 0; + int ret = 0; + + ber_tlv_tag tag; + tag.class_tag = BER_TAG_CLASS_UNIVERSAL; + tag.construct_tag = BER_TAG_PRIMITIVE; + tlv_baseinfo_struct baseinfo_req; + uint8_t basicBuf[MAX_BASIC_INFO_SIZE]; + + /* base info encode*/ + baseinfo_req.serve_type = Q_SERV_TYPE_LOC; + baseinfo_req.encript_type = Q_ENCRIPT_XOR; + baseinfo_req.key_index = Q_LOC_KEY_INDEX;//rand() % MAX_RAW_KEY_NUM; + baseinfo_req.pos_data_type = Q_LOC_DATA_METHOD; + baseinfo_req.loc_method = Q_LOC_MOD_WIFI; + + len = QTlv_Serialize_BaseInfo_Buf(&(baseinfo_req), basicBuf); + tag.tag_value = BER_LOC_BASIC_TAG; + buf_len_1 = tlv_serialize_tlv_buffer(&tag, len, basicBuf,len, &buf_1); + if(buf_len_1 <= 0) + { + QPY_MODLBS_LOG("serialize buffer Fail \r\n"); + return mp_obj_new_int(-1); + } + + /* auth info encode*/ + QTlvAuthInfo authInfo; + memset(&authInfo, 0, sizeof(QTlvAuthInfo)); + memcpy(authInfo.name, "quectel", strlen("quectel")); + memcpy(authInfo.pwd, "123456", strlen("123456")); + + ret = Helios_Dev_GetIMEI((void *)authInfo.imei, AUTH_IMEI_LEN+1); + QPY_MODLBS_LOG("wifi_locreq: get imei [%s]\r\n", authInfo.imei); + + mp_buffer_info_t tokeninfo = {0}; + mp_get_buffer_raise(args[0], &tokeninfo, MP_BUFFER_READ); + + uint8_t digest1[16] = {0}; + md5_state_t md5_ctx1; + memset(&md5_ctx1, 0, sizeof(md5_state_t)); + Quos_md5Init(&md5_ctx1); + Quos_md5Append(&md5_ctx1, (uint8_t *)tokeninfo.buf, strlen((char *)tokeninfo.buf)); + Quos_md5Finish(&md5_ctx1, digest1); + + uint8_t secretinfo[64] = {0}; + wifi_hex_to_str(secretinfo, digest1, 16); + QPY_MODLBS_LOG("MD5 secretinfo tokeninfo.buf[%s] digest1 [%s]\r\n", tokeninfo.buf, secretinfo); + + memcpy(authInfo.token, secretinfo, AUTH_TOTKEN_LEN); + + authInfo.rand = 356; + uint8_t authBuf[MAX_AUTH_INFO_SIZE]; + len = QTlv_Serialize_AuthInfo_Buf(0, authBuf, &authInfo); + QTlv_data_encryption_xor(baseinfo_req.key_index, authBuf, authBuf, len); + tag.tag_value = BER_LOC_AUTH_TAG; + buf_len_2 = tlv_serialize_tlv_buffer(&tag, len, authBuf, len, &buf_2); + if(buf_len_2 <=0) + { + SAFE_FREE(buf_1); + QPY_MODLBS_LOG("wifi_locreq: AuthInfo error\r\n"); + return mp_obj_new_int(-1); + } + else + { + /*合并内存*/ + buf_1 = tlv_realloc_memory(buf_1,buf_len_1,buf_2,buf_len_2); + if (!buf_1){ + SAFE_FREE(buf_1); + SAFE_FREE(buf_2); + return mp_obj_new_int(-1); + } + buf_len_1 += buf_len_2; + } + + /* wifi info encode*/ + ret = Helios_WifiScan_Support(); + if (ret != 1) + mp_raise_ValueError("WiFi-Scan is not support."); + + uint8_t status = 0; + Helios_WifiScan_GetStatus(&status); + if (status != 1) + { + ret = Helios_WifiScan_Open(); + if (ret != 0) + mp_raise_ValueError("WiFi-Scan open Fail."); + } + + Helios_WifiScanAPInfoStruct info = {0}; + tlv_wifiinfo_struct tlv_wifiinfo = {0}; + + MP_THREAD_GIL_EXIT(); + ret = Helios_WifiScan_SyncStart(&info); + MP_THREAD_GIL_ENTER(); + + if (ret == 0) + { + if (info.ap_nums == 0) + mp_raise_ValueError("WiFi-Scan wifi Scan timeout."); + + for (i = 0; i < info.ap_nums; i++) + { + if (i >= 5) + break; + uint8_t wifiBuf[MAX_WIFI_INFO_SIZE]; + char wifimac_str[MAX_MAC_ADDR_STR_LEN] = {0}; + sprintf(wifimac_str, "%02X:%02X:%02X:%02X:%02X:%02X", \ + info.ap[i].bssid[0],info.ap[i].bssid[1],\ + info.ap[i].bssid[2],info.ap[i].bssid[3],\ + info.ap[i].bssid[4],info.ap[i].bssid[5]); + + memcpy(&tlv_wifiinfo.mac, wifimac_str, strlen((const char*)wifimac_str)); + tlv_wifiinfo.rssi = info.ap[i].rssi; + memcpy(&tlv_wifiinfo.ssid, "test", strlen((const char*)"test")); + len = QTlv_Serialize_WifiInfo_Buf(&(tlv_wifiinfo), wifiBuf); + + QTlv_data_encryption_xor(baseinfo_req.key_index, wifiBuf, wifiBuf, len); + tag.tag_value = BER_LOC_WIFI1_TAG+i; + buf_len_2 = tlv_serialize_tlv_buffer(&tag, len, wifiBuf, len, &buf_2); + if(buf_len_2 <=0) + { + SAFE_FREE(buf_1); + mp_raise_ValueError("WiFi-Scan tlv_buffer Fail."); + } + else + { + buf_1 = tlv_realloc_memory(buf_1,buf_len_1,buf_2,buf_len_2); + if (!buf_1) + { + SAFE_FREE(buf_1); + SAFE_FREE(buf_2); + mp_raise_ValueError("WiFi-Scan memory Fail."); + } + buf_len_1 += buf_len_2; + } + } + } + else + { + mp_raise_ValueError("WiFi-Scan wifi Scan Fail."); + } + + /*MD5 info encode*/ + uint8_t md5Str[256] = {0}; + uint8_t serialBuf[64]; + uint8_t pDigest[16] = {0}; + int retLen = 0; + int offset = 0; + + memset(md5Str, 0, sizeof(md5Str)); + memset(pDigest, 0, sizeof(pDigest)); + + retLen = QTlv_Serialize_BaseInfo_Buf(&(baseinfo_req), serialBuf); + memcpy(md5Str+offset, serialBuf, retLen); + offset += retLen; + + retLen = QTlv_Serialize_AuthInfo_Buf(1, serialBuf, &authInfo); + memcpy(md5Str+offset, serialBuf, retLen); + offset += retLen; + + tlv_wifiinfo_struct tlv_md5_wifiinfo = {0}; + char md5_wifimac_str[MAX_MAC_ADDR_STR_LEN] = {0}; + sprintf(md5_wifimac_str, "%02X:%02X:%02X:%02X:%02X:%02X", \ + info.ap[0].bssid[0],info.ap[0].bssid[1],\ + info.ap[0].bssid[2],info.ap[0].bssid[3],\ + info.ap[0].bssid[4],info.ap[0].bssid[5]); + memcpy(&tlv_md5_wifiinfo.mac, md5_wifimac_str, strlen((const char*)md5_wifimac_str)); + memcpy(&tlv_md5_wifiinfo.ssid, "test", strlen((const char*)"test")); + tlv_md5_wifiinfo.rssi = info.ap[0].rssi; + retLen = QTlv_Serialize_WifiInfo_Buf(&(tlv_md5_wifiinfo), serialBuf); + memcpy(md5Str+offset, serialBuf, retLen); + offset += retLen; + + uint8_t digest[16] = {0}; + md5_state_t md5_ctx; + memset(&md5_ctx, 0, sizeof(md5_state_t)); + Quos_md5Init(&md5_ctx); + Quos_md5Append(&md5_ctx, md5Str, offset); + Quos_md5Finish(&md5_ctx, digest); + + uint8_t md5Buf[AUTH_MD5_LEN]; + QTlv_data_encryption_xor(baseinfo_req.key_index, digest, md5Buf, AUTH_MD5_LEN); + tag.tag_value = BER_LOC_MD5_TAG; + buf_len_2 = tlv_serialize_tlv_buffer(&tag, AUTH_MD5_LEN, md5Buf, AUTH_MD5_LEN, &buf_2); + if(buf_len_2 <=0) + { + SAFE_FREE(buf_1); + mp_raise_ValueError("WiFi-Scan MD5 Fail."); + } + else + { + /*合并内存*/ + buf_1 = tlv_realloc_memory(buf_1,buf_len_1,buf_2,buf_len_2); + if (!buf_1) + { + SAFE_FREE(buf_1); + SAFE_FREE(buf_2); + mp_raise_ValueError("WiFi-Scan MD5 memory Fail."); + } + buf_len_1 += buf_len_2; + } + + /*version info encode*/ + uint8_t srvListVer[MAX_SERVER_LIST_VERSION_SIZE]; + uint8_t version[15] = "2021"; + + QTlv_data_encryption_xor(baseinfo_req.key_index, version, srvListVer, len); + tag.tag_value = BER_LOC_SRV_LIST_VER_TAG; + buf_len_2 = tlv_serialize_tlv_buffer(&tag, len, srvListVer, len, &buf_2); + if(buf_len_2 <=0) + { + SAFE_FREE(buf_1); + mp_raise_ValueError("WiFi-Scan version tlv_buffer Fail."); + } + else + { + /*合并内存*/ + buf_1 = tlv_realloc_memory(buf_1,buf_len_1,buf_2,buf_len_2); + if (!buf_1){ + SAFE_FREE(buf_1); + SAFE_FREE(buf_2); + mp_raise_ValueError("WiFi-Scan version memory Fail."); + } + buf_len_1 += buf_len_2; + } + + ///*序列化整个Auth信息*/ + retLen = 0; + uint8_t* retBuffer = NULL; + tag.tag_value = BER_LOC_TAG; + tag.construct_tag = BER_TAG_CONSTRUCTED; + retLen = tlv_serialize_tlv_buffer(&tag, buf_len_1, buf_1, buf_len_1, &retBuffer); + + SAFE_FREE(buf_1); + if(retLen <= 0) + { + mp_raise_ValueError("WiFi-Scan TLV data Fail."); + } + + mp_obj_t codeinfo_objs[2] = { + mp_obj_new_int(retLen), + mp_obj_new_str((char *)retBuffer, retLen), + }; + + return mp_obj_new_tuple(2, codeinfo_objs); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_lbs_get_wifi_locreqencode_obj, 1, 6, wifi_locreqencode); + + +STATIC QTLVNode* QTLVNode_AddBrother(QTLVNode* curNode, QTLVNode* newNode) +{ + curNode->next = newNode; + return curNode->next; +} + +STATIC QTLVNode* QTLVNode_AddChild(QTLVNode* curNode, QTLVNode* newNode) +{ + curNode->child= newNode; + return curNode->child; +} + +STATIC int32_t ber_fetch_tag(const uint8_t *ptr, int32_t size, ber_tlv_tag* rettag) +{ + int32_t skipped = 0; + uint32_t val = *(const uint8_t *)ptr; + + if(size == 0) + return (0); + + rettag->class_tag = (ber_class_tag)(val >> 6); // 获取类别 + rettag->construct_tag = (ber_construct_tag)((val >>5 ) & 0x01); // 获得结构类型 + + if((val &= BER_EXTENSION_ID) != BER_EXTENSION_ID) + { + rettag->tag_value = (val & BER_EXTENSION_ID); + return (1); + } + + val = 0; + for(ptr = ((const uint8_t *)ptr) + 1, skipped = 2; skipped <= size; ptr = ((const uint8_t *)ptr) + 1, skipped++) + { + uint32_t oct = *(const uint8_t *)ptr; + if(oct & BER_MORE_TAG) + { + val = (val << 7) | (oct & 0x7F); + if(val >> ((8 * sizeof(val)) - 9)) + { + return (-1); + } + } + else + { + val = (val << 7) | oct; + rettag->tag_value = val; + return (skipped); + } + } + return 0; +} + +STATIC int32_t ber_fetch_length(const uint8_t *bufptr, int32_t size, uint32_t *len_r) +{ + const uint8_t *buf = (const uint8_t *)bufptr; + int32_t oct = 0; + + if(size == 0) + return 0; + + oct = *(const uint8_t *)buf; + if((oct & BER_LONG_LEN) == 0) + { + *len_r = oct; + return 1; + } + else + { + int32_t len = 0; + int32_t skipped = 0; + + if(oct == 0xff) + { + return -1; + } + + oct &= 0x7F; + for(len = 0, buf++, skipped = 1; oct && (++skipped <= size); buf++, oct--) + { + len = (len << 8) | *buf; + if(len < 0 || (len > MAX_SIGLE_TLV_LEN)) + { + return -1; + } + } + + if(oct == 0) + { + *len_r = len; + return skipped; + } + return 0; /* Want more */ + } +} + +STATIC uint16_t NtoH_uint16(uint16_t n) +{ + return checkCPUendian() ? n : BigLittleSwap16(n); +} + +STATIC uint32_t NtoH_uint32(uint32_t n) +{ + /* 若本机为大端,与网络字节序同,直接返回;若本机为小端,网络数据转换成小端再返回*/ + return checkCPUendian() ? n : BigLittleSwap32(n); +} + +STATIC float NtoH_float(float n) +{ + uint32_t host_uint32 = NtoH_uint32(*((uint32_t*)&n)); + return *((float*)&host_uint32); +} + +STATIC int32_t tlv_parse_to_tree(const uint8_t* buffer, uint32_t bufSize, QTLVNode** root) +{ + QTLVNode* insertNode = *root; + QTLVNode* ktlvNode = NULL; + uint32_t currentIndex = 0; + uint8_t currentReadTag = 'T'; + int32_t bFirst = 1; + int32_t isConstruected = 0; + ber_tlv_tag tag; + int32_t tagused = 0; + int32_t lenused = 0; + int32_t objectUsed = 0; + QTLVNode* ktlvChildNode = NULL; + tlv_baseinfo_struct baseinfo_rec; + uint8_t decodeLen = 0; + + memset(&tag, 0, sizeof(ber_tlv_tag)); + memset(&baseinfo_rec, 0, sizeof(tlv_baseinfo_struct)); + while(currentIndex < bufSize) + { + isConstruected = 0; + ktlvNode = NULL; + if (!bFirst) + ktlvNode = QTLVNode_Create(); + else + ktlvNode = insertNode; + + do + { + if (currentReadTag == 'T') + { + tagused = ber_fetch_tag(buffer+currentIndex,bufSize-currentIndex,&(tag)); + if (0 >= tagused) + { + mp_raise_ValueError("WiFi-Scan TLV ber_fetch_tag Fail."); + } + else + { + ktlvNode->tag.tag_value = tag.tag_value; + ktlvNode->tag.class_tag = tag.class_tag; + isConstruected = ktlvNode->tag.construct_tag = tag.construct_tag; + currentIndex += tagused; + currentReadTag = 'L'; + } + } + + if (currentReadTag == 'L') + { + lenused = ber_fetch_length(buffer+currentIndex, bufSize-currentIndex, &(ktlvNode->length)); + if (0 >= lenused) + { + mp_raise_ValueError("WiFi-Scan TLV ber_fetch_length Fail."); + } + else + { + currentIndex += lenused; + currentReadTag = 'V'; + } + } + + if (currentReadTag == 'V') + { + if (!isConstruected) + { + ktlvNode->value= (uint8_t*)malloc(ktlvNode->length); + if (!ktlvNode->value) + { + mp_raise_ValueError("WiFi-Scan TLV malloc Fail."); + } + + memcpy(ktlvNode->value, buffer+currentIndex, ktlvNode->length); + QPY_MODLBS_LOG("get ktlvNode->tag.tag_value [%d]\r\n", ktlvNode->tag.tag_value); + if (ktlvNode->tag.tag_value == BER_POS_STAT_TAG) + { + QTlvRetPosStat start = *(QTlvRetPosStat*)ktlvNode->value; + QPY_MODLBS_LOG("********BER_POS_STAT_TAG ktlvNode->value :******** [%d]\r\n", start); + if (start == 0) + { + mp_raise_ValueError("WiFi-Scan TLV server status Fail."); + } + else if (start >= POS_POS_NUM_10) + { + char ret_buf[60]; + sprintf(ret_buf, "WiFi-Scan token %d Fail.",start); + mp_raise_ValueError(ret_buf); + } + } + else if (ktlvNode->tag.tag_value == BER_POS_BASIC_TAG) + { + baseinfo_rec.serve_type = *ktlvNode->value; + baseinfo_rec.encript_type = *(ktlvNode->value+1); + baseinfo_rec.key_index = *(ktlvNode->value+2); + baseinfo_rec.pos_data_type = *(ktlvNode->value+3); + baseinfo_rec.loc_method = *(ktlvNode->value+4); + //QPY_MODLBS_LOG("[xjin]:********BER_POS_BASIC_TAG [%d][%d][%d][%d] [%d]\r\n", baseinfo_rec.serve_type, + // baseinfo_rec.encript_type,baseinfo_rec.key_index,baseinfo_rec.pos_data_type,baseinfo_rec.loc_method); + } + else if (ktlvNode->tag.tag_value == BER_POS_RAND_TAG) + { + uint16_t rec_rand = 0; + QTlv_data_encryption_xor(baseinfo_rec.key_index, ktlvNode->value, ktlvNode->value, ktlvNode->length); + rec_rand = NtoH_uint16(*((uint16_t*)ktlvNode->value)); + QPY_MODLBS_LOG("********BER_POS_RAND_TAG rand :******** [%d]\r\n", rec_rand); + } + else if (ktlvNode->tag.tag_value == BER_POS_MD5_TAG) + { + //QTlv_data_encryption_xor(baseinfo_rec.key_index, ktlvNode->value, ktlvNode->value, ktlvNode->length); + } + else if (ktlvNode->tag.tag_value == BER_POS_POS1_TAG) + { + decodeLen = 0; + QTlv_data_encryption_xor(baseinfo_rec.key_index, ktlvNode->value, ktlvNode->value, ktlvNode->length); + position_rec.longitude = NtoH_float(*(float*)(ktlvNode->value + decodeLen)); + decodeLen += sizeof(float); + position_rec.latitude = NtoH_float(*(float*)(ktlvNode->value + decodeLen)); + decodeLen += sizeof(float); + position_rec.accuracy = NtoH_uint16(*(uint16_t*)(ktlvNode->value + decodeLen)); + decodeLen += sizeof(uint16_t); + //QPY_MODLBS_LOG("position.longitude [%f] latitude [%f]\r\n", position_rec.longitude, position_rec.latitude); + //QPY_MODLBS_LOG("position.accuracy [%d]\r\n", position_rec.accuracy); + return 0; + } + + if (!bFirst) + { + insertNode = insertNode->AddBrother(insertNode, ktlvNode); + } + currentIndex += ktlvNode->length; + currentReadTag = 'T'; + bFirst = 0; + } + else + { + if (!bFirst) + { + insertNode = insertNode->AddBrother(insertNode, ktlvNode); + } + ktlvChildNode = QTLVNode_Create(); + insertNode->AddChild(insertNode, ktlvChildNode); + objectUsed = tlv_parse_to_tree(buffer+currentIndex,ktlvNode->length,&insertNode->child); + currentIndex += objectUsed; + currentReadTag = 'T'; + bFirst = 0; + } + } + } while (0); + } + + return -1; +} + + +STATIC QTLVNode* QTLVNode_Create(void) +{ + QTLVNode *curNode = (QTLVNode*)malloc(sizeof(QTLVNode)); + if(curNode == NULL) + { + mp_raise_ValueError("WiFi-Scan malloc Fail."); + } + memset(curNode, 0, sizeof(QTLVNode)); + curNode->AddBrother = QTLVNode_AddBrother; + curNode->AddChild = QTLVNode_AddChild; + return curNode; +} + + +STATIC mp_obj_t encode_wifi_locreq_tlvinfo(size_t n_args, const mp_obj_t *args) +{ + QTLVNode* firstNode = NULL; + int32_t retValue = 0; + uint8_t buffer[512]; + + firstNode = QTLVNode_Create(); + mp_buffer_info_t datainfo = {0}; + mp_get_buffer_raise(args[0], &datainfo, MP_BUFFER_READ); + memcpy(buffer, datainfo.buf, datainfo.len); + + retValue = tlv_parse_to_tree(buffer, (uint32_t)strlen((char *)buffer), &firstNode); + if (retValue == 0) + { + mp_obj_t codeinfo_objs[3] = { + mp_obj_new_float(position_rec.longitude), + mp_obj_new_float(position_rec.latitude), + mp_obj_new_int(position_rec.accuracy), + }; + return mp_obj_new_tuple(3, codeinfo_objs); + } + else + { + return mp_obj_new_int(-1); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_lbs_encode_wifi_tlvinfo_obj, 1, 6, encode_wifi_locreq_tlvinfo); + +STATIC const mp_rom_map_elem_t mp_module_wifilocator_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR___wifiLocator) }, + { MP_ROM_QSTR(MP_QSTR_getWifilocreq), MP_ROM_PTR(&qpy_lbs_get_wifi_locreqencode_obj) }, + { MP_ROM_QSTR(MP_QSTR_encodeWifilocreq), MP_ROM_PTR(&qpy_lbs_encode_wifi_tlvinfo_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_wifilocator_globals, mp_module_wifilocator_globals_table); + +const mp_obj_module_t mp_module_wifilocator = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_wifilocator_globals, +}; + + diff --git a/ports/quectel/core/source/modwifilocator.h b/ports/quectel/core/source/modwifilocator.h new file mode 100644 index 0000000..e47bb25 --- /dev/null +++ b/ports/quectel/core/source/modwifilocator.h @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include "helios_dev.h" +#include "helios_debug.h" +#include "helios_wifiscan.h" + +#include "nlr.h" +#include "objlist.h" +#include "objstr.h" +#include "runtime.h" +#include "mperrno.h" + +#define SAFE_FREE(p) {if(p){free(p); (p)=NULL;}} + +/* 短整型大小端互换*/ +#define BigLittleSwap16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8)) + +/* 长整型大小端互换*/ +#define BigLittleSwap32(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \ + (((uint32_t)(A) & 0x00ff0000) >> 8) | \ + (((uint32_t)(A) & 0x0000ff00) << 8) | \ + (((uint32_t)(A) & 0x000000ff) << 24)) + +/* 服务类型*/ +#define Q_SERV_TYPE_LOC 0x01 +#define Q_SERV_TYPE_LPOS 0x02 +#define Q_SERV_TYPE_APS 0x03 +#define Q_SERV_TYPE_USER 0x04 + +/*基站定位请求TAG宏定义*/ +#define BER_LOC_TAG 0x01 /* 基站定位请求,嵌套类型*/ +#define BER_LOC_BASIC_TAG 0x01 /* 基本信息*/ +#define BER_LOC_AUTH_TAG 0x02 /* 鉴权信息*/ + +#define BER_LOC_WIFI1_TAG 0x14 /*WIFI信息1*/ +#define BER_LOC_WIFI2_TAG 0x15 /*WIFI信息2*/ +#define BER_LOC_WIFI3_TAG 0x16 /*WIFI信息3*/ +#define BER_LOC_WIFI4_TAG 0x17 /*WIFI信息4*/ +#define BER_LOC_WIFI5_TAG 0x18 /*WIFI信息5*/ +#define BER_LOC_WIFI6_TAG 0x19 /*WIFI信息6*/ + +#define BER_LOC_MD5_TAG 0x09 /* MD5*/ +#define BER_LOC_SRV_LIST_VER_TAG 0x0A /*固化服务器表version*/ + +/* 服务类型字符串*/ +#define Q_SERV_STR_LOC ("q_loc") +#define Q_SERV_STR_LPOS ("q_lpos") +#define Q_SERV_STR_APS ("q_agps") +#define Q_SERV_STR_USER ("q_user") + +/* 基站定位的服务类型*/ +#define Q_LOC_MOD_WIFI 0x06 //wifi定位 + +/* 加密类型*/ +#define Q_ENCRIPT_XOR 0x01 + +/* 密钥索引 (暂先固定为0x01)*/ +#define Q_LOC_KEY_INDEX 0x01 + +/* 返回信息是否包含地址*/ +#define Q_ADDR_NONE 0x01 +#define Q_ADDR_INCLUDE 0x02 + +#define MAX_RAW_KEY_NUM (8) /*加扰key的总个数*/ +#define XOR_KEY_LEN (8) /*异或加解密的KEY长度*/ + +static uint8_t xor_key[MAX_RAW_KEY_NUM][XOR_KEY_LEN] = +{ + {0x01,0x03,0xef,0xfe,0x12,0x34,0x66,0x88}, + {0x32,0x47,0xdf,0x3e,0x33,0x69,0x76,0x92}, + {0x23,0x28,0x12,0xba,0xa5,0x12,0x38,0x2a}, + {0x43,0x82,0x11,0xdb,0xb9,0xa2,0x83,0x1c}, + {0xda,0x28,0xda,0x29,0x7a,0x2c,0x71,0x7c}, + {0x1b,0xf3,0x32,0x21,0xee,0xc2,0xea,0x36}, + {0x2f,0x25,0x27,0x83,0xed,0xec,0xa2,0x2f}, + {0x3a,0xcd,0xef,0x37,0x2a,0x3b,0x45,0x9a} +}; + + +/* 数据包类型:数据包格式,01为不包含地址的回复,02为包含地址的回复*/ +#define Q_LOC_DATA_METHOD 0x01 + + +#define BER_CONSTRUCTOR (0x20) +#define BER_LONG_LEN (0x80) +#define BER_MORE_TAG (0x80) +#define BER_EXTENSION_ID (0x1F) + +//wifi +#define MAX_WIFI_INFO_SIZE 58 + +#define BER_LOC_WIFI1_TAG 0x14 /*WIFI信息1*/ +#define BER_LOC_WIFI2_TAG 0x15 /*WIFI信息2*/ +#define BER_LOC_WIFI3_TAG 0x16 /*WIFI信息3*/ +#define BER_LOC_WIFI4_TAG 0x17 /*WIFI信息4*/ +#define BER_LOC_WIFI5_TAG 0x18 /*WIFI信息5*/ +#define BER_LOC_WIFI6_TAG 0x19 /*WIFI信息6*/ + +#define MAX_MAC_ADDR_STR_LEN 18 +#define MAX_WIFI_AP_SSID_LEN 32 + +#define AUTH_MD5_LEN 8 /*MD5值长度*/ +#define MAX_SIGLE_TLV_LEN (2046) /*单个TLV长度最大为2046字节*/ + +#define MAX_SERVER_LIST_VERSION_SIZE (20) + +typedef enum QuectelBerClass_Tag{ + BER_TAG_CLASS_UNIVERSAL = 0, /* 0b00 */ + BER_TAG_CLASS_APPLICATION = 1, /* 0b01 */ + BER_TAG_CLASS_CONTEXT = 2, /* 0b10 */ + BER_TAG_CLASS_PRIVATE = 3 /* 0b11 */ +}ber_class_tag; + +typedef enum QuectelBerConstruct_Tag{ + BER_TAG_PRIMITIVE, + BER_TAG_CONSTRUCTED +}ber_construct_tag; + +typedef struct QuectelBerTlv_Tag +{ + int32_t tag_value; + ber_construct_tag construct_tag; + ber_class_tag class_tag; +}ber_tlv_tag; + +/*retun loc*/ +typedef struct +{ + uint8_t serve_type; /*服务类型*/ + uint8_t encript_type; /*加密类型*/ + uint8_t key_index; /*密钥索引*/ + uint8_t pos_data_type; /*数据包类型*/ + uint8_t loc_method; /*定位类型*/ +}tlv_baseinfo_struct; + +#define MAX_BASIC_INFO_SIZE 5 + +/*请求的原始数据打包解包*/ +#define AUTH_NAME_LEN 16 +#define AUTH_PWD_LEN 16 +#define AUTH_IMEI_LEN 15 +#define AUTH_TOTKEN_LEN 16 +#define AUTH_FIXINFO_LEN 17 /* 固定长度:IMEI(15)+RAND(2)=17*/ +#define MAX_AUTH_INFO_SIZE (AUTH_NAME_LEN+AUTH_PWD_LEN+AUTH_FIXINFO_LEN) + +typedef struct QTlvAuthInfo_Tag +{ + uint8_t name[AUTH_NAME_LEN+1]; /*用户名*/ + uint8_t pwd[AUTH_PWD_LEN+1]; /*密码*/ + uint8_t imei[AUTH_IMEI_LEN+1]; /*IMEI*/ + uint8_t token[AUTH_TOTKEN_LEN*2+1]; /*密钥*/ + int16_t rand; /*随机数*/ +}QTlvAuthInfo; + +typedef struct +{ + uint8_t mac[MAX_MAC_ADDR_STR_LEN]; // eg. "44:6a:2e:12:08:01" + uint8_t ssid[MAX_WIFI_AP_SSID_LEN]; // eg. "Quectel-hf" + int16_t rssi; // eg. "-30 +}tlv_wifiinfo_struct; + + +/*返回位置信息*/ +#define BER_POS_TAG 0x02/* 复合结构*/ +#define BER_POS_STAT_TAG 0x01 +#define BER_POS_BASIC_TAG 0x02 +#define BER_POS_RAND_TAG 0x03 +#define BER_POS_POS1_TAG 0x04 +#define BER_POS_POS2_TAG 0x05 +#define BER_POS_POS3_TAG 0x06 +#define BER_POS_POS4_TAG 0x07 +#define BER_POS_POS5_TAG 0x08 +#define BER_POS_POS6_TAG 0x09 +#define BER_POS_MD5_TAG 0x0A /* MD5*/ + +#define BER_POS_REDIRECT1_TAG 0x0B /*重定向表数据1*/ +#define BER_POS_REDIRECT2_TAG 0x0C /*重定向表数据2*/ +#define BER_POS_REDIRECT3_TAG 0x0D /*重定向表数据3*/ +#define BER_POS_SRVLIST_VER_TAG 0x0E /*固化服务器表版本信息*/ +#define BER_POS_SRVLIST1_TAG 0x0F /*固化服务器表数据1*/ +#define BER_POS_SRVLIST2_TAG 0x10 +#define BER_POS_SRVLIST3_TAG 0x11 +#define BER_POS_SRVLIST4_TAG 0x12 +#define BER_POS_SRVLIST5_TAG 0x13 +#define BER_POS_SRVLIST6_TAG 0x14 +#define BER_POS_SRVLIST7_TAG 0x15 +#define BER_POS_SRVLIST8_TAG 0x16 +#define BER_POS_SRVLIST9_TAG 0x17 +#define BER_POS_SRVLIST10_TAG 0x18 /*固化服务器表数据10*/ +#define BER_POS_ADDRESS_TAG 0x19 /*街道信息*/ +#define BER_POS_TRIANGLE_FRE_TAG 0x1A/*获取服务器返回的三角定位访问频率*/ +#define BER_POS_ACCURACY_LEVEL_TAG 0x1B /*服务器返回是否是精准定位*/ + +/*status: +0 = 成功定位 +1 = 用户信息验证失败 +2 = 请求格式不正确 +3= 基站信息未发现*/ +/* 返回的状态类型*/ +typedef enum{ + POS_POS_NUM_0 =0, + POS_POS_NUM_1, + POS_POS_NUM_2, + POS_POS_NUM_3, + POS_POS_NUM_4, + POS_POS_NUM_5, + POS_POS_NUM_6, + POS_POS_NUM_10 = 10, //表示该token不存在或绑定的设备超过最大值 + POS_POS_NUM_11 = 11, //11表示设备的每天定位超过最大访问次数 + POS_POS_NUM_12 = 12, //token定位超过最大访问次数 + POS_POS_NUM_13 = 13, //token过期 + POS_POS_NUM_14 = 14, //该IMEI号不可访问服务器 + POS_POS_NUM_15 = 15, //token的每天定位超过最大访问次数 + POS_POS_NUM_16 = 16, //token的周期内定位超过最大访问次数 + POS_POS_NUM_17 = 17, //IMEI号不合法 + POS_POS_NUM_18 = 18, //token绑定设备超过最大值 +}QTlvRetPosStat; + +//encode TLV info +typedef struct QTLVNode_Tag { + //q_link_type link_ptr; + ber_tlv_tag tag; /*标记值*/ + uint32_t length; /* 数据长度*/ + uint8_t* value; /* 数据*/ + struct QTLVNode_Tag* next; /*兄弟*/ + struct QTLVNode_Tag* child; /*孩子*/ + + struct QTLVNode_Tag*(*AddBrother)(struct QTLVNode_Tag* curNode, struct QTLVNode_Tag* newNode); + struct QTLVNode_Tag*(*AddChild)(struct QTLVNode_Tag* curNode, struct QTLVNode_Tag* newNode); +}QTLVNode; + +static QTLVNode* QTLVNode_Create(void); + diff --git a/ports/quectel/core/source/mpconfigport.h b/ports/quectel/core/source/mpconfigport.h index 73ce854..88b7cb2 100644 --- a/ports/quectel/core/source/mpconfigport.h +++ b/ports/quectel/core/source/mpconfigport.h @@ -206,6 +206,9 @@ #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) #define MICROPY_ENABLE_FINALISER (1) // Pawn 2020/11/03 +#define MICROPY_ENABLE_DEVICE_REPORT (1) +#define MICROPY_ENABLE_CALLBACK_DEAL (1) + #define UINT_FMT "%lu" #define INT_FMT "%ld" @@ -283,6 +286,14 @@ extern const struct _mp_obj_module_t mp_module_ethernet; #define MICROPY_PORT_BUILTIN_MODULES_ETHERNET #endif +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) +extern const struct _mp_obj_module_t mp_module_wifilocator; +#define MICROPY_PORT_BUILTIN_MODULES_WIFILOCATOR { MP_OBJ_NEW_QSTR(MP_QSTR___wifiLocator), (mp_obj_t)&mp_module_wifilocator }, +#else +#define MICROPY_PORT_BUILTIN_MODULES_WIFILOCATOR +#endif + + #if defined(PLAT_ASR) || defined(PLAT_Unisoc)|| defined(PLAT_RDA) || defined(PLAT_Qualcomm) extern const struct _mp_obj_type_t mp_fota_type; #define MICROPY_PORT_BUILTIN_MODULES_FOTA { MP_OBJ_NEW_QSTR(MP_QSTR_fota), (mp_obj_t)&mp_fota_type}, @@ -421,6 +432,7 @@ extern const struct _mp_obj_module_t mp_module_qrcode; { MP_OBJ_NEW_QSTR(MP_QSTR_wifiScan), (mp_obj_t)&mp_module_wifiscan},\ { MP_OBJ_NEW_QSTR(MP_QSTR_audio), (mp_obj_t)&mp_module_audio},\ MICROPY_PORT_BUILTIN_MODULES_ETHERNET \ + MICROPY_PORT_BUILTIN_MODULES_WIFILOCATOR \ MICROPY_PORT_BUILTIN_MODULES_FOTA \ MICROPY_PORT_BUILTIN_MODULES_LVGL \ MICROPY_PORT_BUILTIN_MODULES_QRCODE \ diff --git a/ports/quectel/core/source/mphalport.c b/ports/quectel/core/source/mphalport.c index 538e97e..2fa2bca 100644 --- a/ports/quectel/core/source/mphalport.c +++ b/ports/quectel/core/source/mphalport.c @@ -36,15 +36,20 @@ #include "helios.h" #include "helios_os.h" #include "helios_rtc.h" - +#include "stackctrl.h" +#include "runtime.h" STATIC uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; //static Helios_Sem_t mp_hal_stdin_sem = 0; +#define QUECPYTHON_MAIN_THREAD_SLEEP_DEAL_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) #if !defined(PLAT_RDA) -#define QUECPYTHON_CALLBACK_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) -static Helios_MsgQ_t quecpython_callback_deal_queue = 0; +static Helios_MsgQ_t quecpython_main_thread_sleep_deal_queue = 0; +static int main_thread_sleep_flag = 0; +#define MAIN_THREAD_SLEEP_ENTER() (main_thread_sleep_flag = 1) +#define MAIN_THREAD_SLEEP_EXIT() (main_thread_sleep_flag = 0) +#define IS_MAIN_THREAD_IN_SLEEP() (1 == main_thread_sleep_flag) #endif //forrest.liu@20210809 add for quecpython task repl using waiting msg @@ -251,31 +256,33 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { } #if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) -void quecpython_callback_deal_queue_create(void) +void quecpython_main_thread_sleep_deal_queue_create(void) { - quecpython_callback_deal_queue = Helios_MsgQ_Create(QUECPYTHON_CALLBACK_MSG_MAX_NUM, sizeof(mp_uint_t)); + quecpython_main_thread_sleep_deal_queue = Helios_MsgQ_Create(QUECPYTHON_MAIN_THREAD_SLEEP_DEAL_MSG_MAX_NUM, sizeof(mp_uint_t)); } //Added by Freddy @20210520 发送消息至sleep的queue void quecpython_send_msg_to_sleep_func(void) { mp_uint_t msg = 0; - if(0 != quecpython_callback_deal_queue) + if(0 != quecpython_main_thread_sleep_deal_queue && IS_MAIN_THREAD_IN_SLEEP()) { - Helios_MsgQ_Put(quecpython_callback_deal_queue, (const void*)(&msg), sizeof(mp_uint_t), 0); + Helios_MsgQ_Put(quecpython_main_thread_sleep_deal_queue, (const void*)(&msg), sizeof(mp_uint_t), 0); } } -//Added by Freddy @20210520 sleep接口循环调用此接口达到sleep的目的, -//当有callback要执行时,给此queue发消息,即可立即退? +//Added by Freddy @20210520 sleep接口循环调用此接口达到sleep的目的, +//当有callback要执行时, 给此queue发消息, 即可立即退出 mp_uint_t quecpython_sleep_deal_fun(mp_uint_t ms) { - if(quecpython_callback_deal_queue) + if(quecpython_main_thread_sleep_deal_queue) { mp_uint_t dt; mp_uint_t t0 = mp_hal_ticks_us(); mp_uint_t msg; - int ret = Helios_MsgQ_Get(quecpython_callback_deal_queue, (mp_uint_t*)&msg, sizeof(msg), ms); + MAIN_THREAD_SLEEP_ENTER(); + int ret = Helios_MsgQ_Get(quecpython_main_thread_sleep_deal_queue, (mp_uint_t*)&msg, sizeof(msg), ms); + MAIN_THREAD_SLEEP_EXIT(); if(ret < 0) { return ms; diff --git a/ports/quectel/core/source/mpthreadport.c b/ports/quectel/core/source/mpthreadport.c index 8a184e1..4b6dacd 100644 --- a/ports/quectel/core/source/mpthreadport.c +++ b/ports/quectel/core/source/mpthreadport.c @@ -178,6 +178,20 @@ int mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { return thread_id; } +void mp_new_thread_add(uint32_t th_id, uint32_t stack_size) { + // Allocate linked-list node (must be outside thread_mutex lock) + thread_t *th = m_new_obj(thread_t); + // add thread to linked list of all threads + th->id = th_id; + th->ready = 0; + th->arg = NULL; + th->stack = Helios_Thread_GetStaskPtr((Helios_Thread_t)th->id); + + th->stack_len = stack_size / sizeof(uint32_t); + th->next = thread; + thread = th; +} + void mp_thread_finish(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { diff --git a/ports/quectel/core/source/mpthreadport.h b/ports/quectel/core/source/mpthreadport.h index 18c7dba..cbe4ebf 100644 --- a/ports/quectel/core/source/mpthreadport.h +++ b/ports/quectel/core/source/mpthreadport.h @@ -39,6 +39,7 @@ void mp_thread_mutex_init(mp_thread_mutex_t *mutex); int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait); void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex); void mp_thread_mutex_del(mp_thread_mutex_t *mutex); +void mp_new_thread_add(uint32_t th_id, uint32_t stack_size); #endif // MICROPY_INCLUDED_MPTHREADPORT_H diff --git a/ports/quectel/core/source/quecpython.c b/ports/quectel/core/source/quecpython.c index d52903d..cca29b6 100644 --- a/ports/quectel/core/source/quecpython.c +++ b/ports/quectel/core/source/quecpython.c @@ -34,6 +34,7 @@ #include "readline.h" #include "mpprint.h" #include "objmodule.h" +#include "callbackdeal.h" #if !defined(PLAT_RDA) #if CONFIG_MBEDTLS @@ -115,8 +116,11 @@ static char heap[1024 * 512]; extern pyexec_mode_kind_t pyexec_mode_kind; extern void machine_timer_deinit_all(void); +#if MICROPY_KBD_EXCEPTION MAINPY_RUNNING_FLAG_DEF MAINPY_INTERRUPT_BY_KBD_FLAG_DEF +SET_MAINPY_RUNNING_TIMER_DEF +#endif void quecpython_task(void *arg) { @@ -127,8 +131,8 @@ void quecpython_task(void *arg) #if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) //Added by Freddy @20210520 在线程sleep时,通过wait queue的方式超时代替实际的sleep, //当有callback执行时,给此queue发消息即可快速执行callback - void quecpython_callback_deal_queue_create(void); - quecpython_callback_deal_queue_create(); + void quecpython_main_thread_sleep_deal_queue_create(void); + quecpython_main_thread_sleep_deal_queue_create(); #endif #if !defined(PLAT_RDA) @@ -169,7 +173,11 @@ soft_reset: // mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); readline_init0(); - + + #if MICROPY_ENABLE_CALLBACK_DEAL + qpy_callback_deal_init(); + #endif + // run boot-up scripts #if defined(PLAT_RDA) pyexec_frozen_module("_boot_RDA.py"); @@ -178,13 +186,25 @@ soft_reset: #else pyexec_frozen_module("_boot.py"); #endif - if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE()) { + #if MICROPY_KBD_EXCEPTION + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE()) + #else + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) + #endif + { + #if MICROPY_KBD_EXCEPTION + MAINPY_RUNNING_FLAG_SET(); int ret = pyexec_file_if_exists("/usr/main.py"); + MAINPY_RUNNING_FLAG_CLEAR(); if(RET_KBD_INTERRUPT == ret) { MAINPY_INTERRUPT_BY_KBD_FLAG_SET(); } + #else + pyexec_file_if_exists("/usr/main.py"); + #endif } + #if MICROPY_KBD_EXCEPTION else { MAINPY_INTERRUPT_BY_KBD_FLAG_CLEAR(); @@ -192,6 +212,7 @@ soft_reset: if(MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE()) { + #endif for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { @@ -203,14 +224,19 @@ soft_reset: } } } + #if MICROPY_KBD_EXCEPTION } - + #endif machine_timer_deinit_all(); #if MICROPY_PY_THREAD //uart_printf("mp_thread_deinit in quecpython task.\r\n"); mp_thread_deinit(); #endif + + #if MICROPY_ENABLE_CALLBACK_DEAL + qpy_callback_deal_deinit(); + #endif mp_module_deinit_all(); diff --git a/ports/quectel/core/umqtt.py b/ports/quectel/core/umqtt.py index e2807d7..59cec64 100644 --- a/ports/quectel/core/umqtt.py +++ b/ports/quectel/core/umqtt.py @@ -428,7 +428,7 @@ class MQTTClient(BaseMqtt): try: self.sock.close() net_sta = net.getState() - if net_sta != -1 and net_sta[1][0] == 1: + if net_sta != -1 and ((net_sta[1][0] == 1) or (net_sta[1][0] == 5)): call_state = dataCall.getInfo(1, 0) if (call_state != -1) and (call_state[2][0] == 1): time_info = self.logTime() diff --git a/ports/quectel/core/wifilocator.py b/ports/quectel/core/wifilocator.py new file mode 100644 index 0000000..42366b7 --- /dev/null +++ b/ports/quectel/core/wifilocator.py @@ -0,0 +1,67 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import usocket as socket +import log +import net +import dataCall +import __wifiLocator + +class wifilocator: + + def __init__(self, token=None): + self.wifitoken = token + + def getwifilocator(self): + net_sta = net.getState() + if net_sta != -1 and ((net_sta[1][0] == 1) or (net_sta[1][0] == 5)): + call_state = dataCall.getInfo(1, 0) + if (call_state != -1) and (call_state[2][0] == 1): + if len(self.wifitoken) != 16: + return -2 + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sockaddr = socket.getaddrinfo('www.queclocator.com', 80)[0][-1] + sock.connect(sockaddr) + cellinfo = __wifiLocator.getWifilocreq(self.wifitoken) + senddata = b"POST /location/QLOC HTTP/1.0\r\nHost: www.queclocator.com\r\nContent-Length: {}\r\nContent-Type: 05\r\nAccept-Charset: utf-8\r\n\r\n{}".format(cellinfo[0], cellinfo[1]) + sock.write(senddata) + l = sock.readline() + try: + l = l.split(None, 2) + status = int(l[1]) + except: + raise ValueError("Connect FAIL!") + reason = "" + if status == 200: + while True: + l = sock.readline() + j = l.decode().split(":") + if not l or l == b"\r\n": + break + data = sock.recv(1024) + return __wifiLocator.encodeWifilocreq(data) + else: + if len(l) > 2: + reason = l[2].rstrip() + raise ValueError("error info:===='{}'====".format(reason)) + except Exception as e: + print("Wifi locator Get the coordinate error:%s "%str(e)) + return -3 + else: + return -1 + else: + return -1 + + diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 4df14a2..d75715f 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -124,6 +124,11 @@ mp_obj_t mp_obj_bound_get_meth(void *bound) return ((mp_obj_bound_meth_t *)bound)->meth; } +bool mp_obj_is_boundmeth(mp_obj_t o) { + + return mp_obj_is_type(o, &mp_type_bound_meth); +} + mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) { mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t); o->base.type = &mp_type_bound_meth; diff --git a/py/profile.c b/py/profile.c index 632b6a8..00c5ae7 100644 --- a/py/profile.c +++ b/py/profile.c @@ -300,11 +300,15 @@ STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t mp_prof_is_executing = false; if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_ENTER() + #endif mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_EXIT() + #endif } return top; } diff --git a/py/runtime.c b/py/runtime.c index 6955e17..eb5f32c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -44,6 +44,8 @@ #include "py/builtin.h" #include "py/stackctrl.h" #include "py/gc.h" +#include "interrupt_char.h" + #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -81,6 +83,7 @@ void mp_init(void) { MP_STATE_VM(mp_kbd_exception).traceback_len = 0; MP_STATE_VM(mp_kbd_exception).traceback_data = NULL; MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; + SET_MAINPY_RUNNING_TIMER_INIT(); #endif #if MICROPY_ENABLE_COMPILER @@ -162,6 +165,9 @@ void mp_deinit(void) { mp_thread_mutex_del(&MP_STATE_VM(gil_mutex)); #endif + #if MICROPY_KBD_EXCEPTION + SET_MAINPY_RUNNING_TIMER_DEINIT(); + #endif // mp_obj_dict_free(&dict_main); // mp_map_deinit(&MP_STATE_VM(mp_loaded_modules_map)); } diff --git a/py/scheduler.c b/py/scheduler.c index 02e8b7e..a536a3c 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -30,12 +30,18 @@ #include "py/runtime.h" #include "mphalport.h" +#include "callbackdeal.h" #if MICROPY_KBD_EXCEPTION // This function may be called asynchronously at any time so only do the bare minimum. void MICROPY_WRAP_MP_KEYBOARD_INTERRUPT(mp_keyboard_interrupt)(void) { MP_STATE_VM(mp_kbd_exception).traceback_data = NULL; MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); +#if MICROPY_ENABLE_CALLBACK_DEAL +#if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) + quecpython_send_msg_to_sleep_func(); +#endif +#endif #if MICROPY_ENABLE_SCHEDULER if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; @@ -67,7 +73,9 @@ void mp_handle_pending(bool raise_exc) { if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); if (obj != MP_OBJ_NULL) { + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_ENTER() + #endif MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; if (!mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; @@ -76,7 +84,9 @@ void mp_handle_pending(bool raise_exc) { MICROPY_END_ATOMIC_SECTION(atomic_state); nlr_raise(obj); } + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_EXIT() + #endif } mp_handle_pending_tail(atomic_state); } else { @@ -142,19 +152,24 @@ bool MICROPY_WRAP_MP_SCHED_SCHEDULE(mp_sched_schedule)(mp_obj_t function, mp_obj ret = false; } MICROPY_END_ATOMIC_SECTION(atomic_state); -#if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) - if(true == ret) { - quecpython_send_msg_to_sleep_func(); - mp_hal_stdin_send_msg_to_rx_chr();//forrest.liu@20210809 add for quecpython task repl using waiting msg - } -#else + if(true == ret) { + #if MICROPY_ENABLE_CALLBACK_DEAL + extern Helios_Thread_t qpy_callback_deal_task_ref; + if(Helios_Thread_GetID() != qpy_callback_deal_task_ref) { + qpy_send_msg_to_callback_deal_thread(CALLBACK_TYPE_ID_NONE, NULL); + } + #else + #if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) + quecpython_send_msg_to_sleep_func(); + #endif + #endif mp_hal_stdin_send_msg_to_rx_chr();//forrest.liu@20210809 add for quecpython task repl using waiting msg } -#endif return ret; } +extern bool mp_obj_is_boundmeth(mp_obj_t o); extern mp_obj_t mp_obj_bound_get_self(void *bound); extern mp_obj_t mp_obj_bound_get_meth(void *bound); //Add a callback to the unscheduled table. If it is a Method, @@ -172,8 +187,12 @@ bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg) } else if(true == callback->is_method)//bound_method { - mp_obj_t cb = mp_load_attr(callback->method_self, callback->method_name); - return mp_sched_schedule(cb, arg); + if(mp_obj_is_boundmeth(callback->cb)) { + return mp_sched_schedule(callback->cb, arg); + } else { + mp_obj_t cb = mp_load_attr(callback->method_self, callback->method_name); + return mp_sched_schedule(cb, arg); + } } else { diff --git a/py/vm.c b/py/vm.c index 1df0699..c842c05 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1374,14 +1374,18 @@ pending_exception_check: MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); if (obj != MP_OBJ_NULL) { + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_ENTER() + #endif MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; if (!mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; } MICROPY_END_ATOMIC_SECTION(atomic_state); RAISE(obj); + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_EXIT() + #endif } mp_handle_pending_tail(atomic_state); } else { @@ -1391,12 +1395,16 @@ pending_exception_check: #else // This is an inlined variant of mp_handle_pending if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_ENTER() + #endif MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; RAISE(obj); + #if MICROPY_KBD_EXCEPTION CHECK_MAINPY_KBD_INTERRUPT_EXIT() + #endif } #endif -- Gitee