From 01927c78951a839e46f54170d70b8297a9d7a8c0 Mon Sep 17 00:00:00 2001 From: "freddy.li" Date: Fri, 12 Nov 2021 19:05:42 +0800 Subject: [PATCH] update micropython --- config/config.in | 208 +- extmod/modaes.c | 654 ++++++ extmod/modaes.h | 28 + extmod/modhash.c | 308 +++ extmod/modhash.h | 44 + extmod/moduhashlib.c | 144 ++ extmod/moduselect.c | 13 +- extmod/vfs.c | 71 +- extmod/vfs_efs.c | 664 ++++++ .../source/utf8togbk.h => extmod/vfs_efs.h | 27 +- extmod/vfs_efs_file.c | 250 +++ extmod/vfs_lfs.c | 6 +- extmod/vfs_lfsx.c | 28 +- lib/littlefs/lfs1_util.h | 3 + lib/utils/interrupt_char.h | 30 + lib/utils/pyexec.c | 12 +- microPython.mk | 129 +- ports/quectel/core/Makefile | 176 +- ports/quectel/core/_boot_Qualcomm.py | 117 ++ ports/quectel/core/aLiYun.py | 13 +- ports/quectel/core/app_fota.py | 4 +- ports/quectel/core/backup_restore.py | 43 +- ports/quectel/core/bak_util.py | 62 + ports/quectel/core/checkNet.py | 93 +- ports/quectel/core/checksum.py | 46 +- ports/quectel/core/dataCall.py | 5 +- ports/quectel/core/gnss.py | 8 +- ports/quectel/core/hls.py | 434 ++++ ports/quectel/core/modbus_utils.py | 63 - ports/quectel/core/ql_fs.py | 41 +- ports/quectel/core/request.py | 59 +- ports/quectel/core/source/audio_audio.c | 126 +- ports/quectel/core/source/audio_record.c | 100 +- ports/quectel/core/source/audio_tts.c | 165 +- ports/quectel/core/source/camera_capture.c | 600 +++--- ports/quectel/core/source/camera_preview.c | 18 +- ports/quectel/core/source/camera_scandecode.c | 44 +- ports/quectel/core/source/machine_extint.c | 209 +- ports/quectel/core/source/machine_hw_spi.c | 26 +- ports/quectel/core/source/machine_iic.c | 8 +- ports/quectel/core/source/machine_keypad.c | 172 ++ ports/quectel/core/source/machine_lcd.c | 165 +- ports/quectel/core/source/machine_nandflash.c | 10 +- ports/quectel/core/source/machine_pin.c | 228 +-- ports/quectel/core/source/machine_rtc.c | 40 +- ports/quectel/core/source/machine_timer.c | 55 +- ports/quectel/core/source/machine_uart.c | 91 +- ports/quectel/core/source/machine_wdt.c | 8 +- ports/quectel/core/source/misc_adc.c | 2 + ports/quectel/core/source/misc_power.c | 12 +- ports/quectel/core/source/misc_powerkey.c | 33 +- ports/quectel/core/source/misc_pwm.c | 44 +- ports/quectel/core/source/misc_usb.c | 34 +- ports/quectel/core/source/misc_usbnet.c | 67 + ports/quectel/core/source/modaudio.c | 2 + ports/quectel/core/source/modaudio.h | 2 + ports/quectel/core/source/modble.c | 96 +- ports/quectel/core/source/modcamera.c | 2 +- ports/quectel/core/source/modcelllocator.c | 6 +- ports/quectel/core/source/moddatacall.c | 46 +- ports/quectel/core/source/moddev.c | 24 + ports/quectel/core/source/modethernet.c | 21 + .../quectel/core/source/modethernet_dm9051.c | 235 +++ ports/quectel/core/source/modexample.c | 9 + ports/quectel/core/source/modfota.c | 31 +- ports/quectel/core/source/modlpm.c | 20 +- ports/quectel/core/source/modlvgl.c | 27 +- ports/quectel/core/source/modmachine.c | 15 +- ports/quectel/core/source/modmachine.h | 3 + ports/quectel/core/source/modmisc.c | 12 +- ports/quectel/core/source/modmisc.h | 3 + ports/quectel/core/source/modnb.c | 66 + ports/quectel/core/source/modnb.h | 46 + ports/quectel/core/source/modnet.c | 1797 +++++++++-------- ports/quectel/core/source/modostimer.c | 59 +- ports/quectel/core/source/modpoc.c | 757 +++++++ ports/quectel/core/source/modqrcode.c | 166 ++ ports/quectel/core/source/modquecIot.c | 26 +- ports/quectel/core/source/modsecuredata.c | 5 +- ports/quectel/core/source/modsim.c | 84 +- ports/quectel/core/source/modslipif.c | 196 ++ ports/quectel/core/source/modsms.c | 27 +- ports/quectel/core/source/modsocket.c | 337 +++- ports/quectel/core/source/moduos.c | 8 +- ports/quectel/core/source/modutime.c | 6 +- ports/quectel/core/source/modvoicecall.c | 187 +- ports/quectel/core/source/modwifiscan.c | 19 +- ports/quectel/core/source/mpconfigport.h | 120 +- ports/quectel/core/source/mphalport.c | 97 +- ports/quectel/core/source/mphalport.h | 8 +- ports/quectel/core/source/mpthreadport.c | 7 + ports/quectel/core/source/mpthreadport.h | 5 + ports/quectel/core/source/nb_aep.c | 171 ++ ports/quectel/core/source/nb_oc.c | 186 ++ ports/quectel/core/source/nb_onenet.c | 707 +++++++ ports/quectel/core/source/quecpython.c | 63 +- ports/quectel/core/source/sensor_sn95500.c | 20 +- ports/quectel/core/source/utf8togbk.c | 1375 ------------- ports/quectel/core/source/utils_crc32.c | 97 +- ports/quectel/core/umqtt.py | 166 +- py/modthread.c | 30 +- py/obj.h | 9 + py/objboundmeth.c | 16 + py/objmodule.c | 22 + py/objmodule.h | 2 + py/profile.c | 3 + py/runtime.h | 3 + py/scheduler.c | 60 +- py/vm.c | 5 + 109 files changed, 9826 insertions(+), 3726 deletions(-) create mode 100644 extmod/modaes.c create mode 100644 extmod/modaes.h create mode 100644 extmod/modhash.c create mode 100644 extmod/modhash.h create mode 100644 extmod/vfs_efs.c rename ports/quectel/core/source/utf8togbk.h => extmod/vfs_efs.h (49%) create mode 100644 extmod/vfs_efs_file.c create mode 100644 ports/quectel/core/_boot_Qualcomm.py create mode 100644 ports/quectel/core/bak_util.py create mode 100644 ports/quectel/core/hls.py delete mode 100644 ports/quectel/core/modbus_utils.py create mode 100644 ports/quectel/core/source/machine_keypad.c create mode 100644 ports/quectel/core/source/misc_usbnet.c create mode 100644 ports/quectel/core/source/modethernet.c create mode 100644 ports/quectel/core/source/modethernet_dm9051.c create mode 100644 ports/quectel/core/source/modnb.c create mode 100644 ports/quectel/core/source/modnb.h create mode 100644 ports/quectel/core/source/modpoc.c create mode 100644 ports/quectel/core/source/modqrcode.c create mode 100644 ports/quectel/core/source/modslipif.c create mode 100644 ports/quectel/core/source/nb_aep.c create mode 100644 ports/quectel/core/source/nb_oc.c create mode 100644 ports/quectel/core/source/nb_onenet.c delete mode 100644 ports/quectel/core/source/utf8togbk.c diff --git a/config/config.in b/config/config.in index 2be8c55..1d3ece9 100644 --- a/config/config.in +++ b/config/config.in @@ -1,92 +1,116 @@ - -config LVGL - bool "Enable lvgl" - default n -help - This is lvgl support. - -menu "lvgl option" - depends on LVGL - - source "../services/microPython/config/lvgl_option.in" - endmenu - -config QRCODE - bool "Enable qrcode" - default n -help - This is qrcode support. - -config POC - bool "Enable poc" - default n -help - This is poc support. - -config CAMERA - bool "Enable camera" - default n -help - This is camera support. - -config CAMERA_DECODE - bool "Enable camera decoding function" - depends on CAMERA - default n -help - This is the camera scan decoding function. - -config CAMERA_SAVEPHOTOS - bool "Enable Save photo function" - depends on CAMERA - default n -help - Realize the function of saving photos. - - -config QUECTHING - bool "Enable quecthing" - default n -help - This supports QR code barcode decoding. - -config SPINAND - bool "Enable spi nand flash" - default n -help - This is SPINANDFLASH support. - -choice SPINAND_FILESYSTEM - bool "Select nandflash file system" - default NANDFLASH_YAFFS2 - depends on SPINAND - help - Select nandflash file system. - -config NANDFLASH_YAFFS2 - bool "yaffs2 file system" -config NANDFLASH_FAT - bool "fat file system" -endchoice - -config RTMP - bool "Enable rtmp" - default n -help - This is rtmp support. - -config JPEG - bool "Enable jpeg" - default n -help - Support JPEG and RGB conversion. - -config SPI_SDCARD - bool "Enable SPI SD Card" - default n -help - Support SPI SD Card support. - - - - + +config LVGL + bool "Enable lvgl" + default n +help + This is lvgl support. + +menu "lvgl option" + depends on LVGL + + source "../services/microPython/config/lvgl_option.in" + endmenu + +config QRCODE + bool "Enable qrcode" + default n +help + This is qrcode support. + + +choice POC_PLATFORM + bool "Select POC platform" + default POC_BND + depends on POC + help + Select POC platform. + +config POC_BND + bool "bnd platform" +config POC_SL + bool "sl platform" +endchoice + +config CAMERA + bool "Enable camera" + default n +help + This is camera support. + +config CAMERA_DECODE + bool "Enable camera decoding function" + depends on CAMERA + default n +help + This is the camera scan decoding function. + +config CAMERA_SAVEPHOTOS + bool "Enable Save photo function" + depends on CAMERA + default n +help + Realize the function of saving photos. + + +config QUECTHING + bool "Enable quecthing" + default y +help + This is quecIot support. + +config SPINAND + bool "Enable spi nand flash" + default n +help + This is SPINANDFLASH support. + +choice SPINAND_FILESYSTEM + bool "Select nandflash file system" + default NANDFLASH_YAFFS2 + depends on SPINAND + help + Select nandflash file system. + +config NANDFLASH_YAFFS2 + bool "yaffs2 file system" +config NANDFLASH_FAT + bool "fat file system" +endchoice + +config RTMP + bool "Enable rtmp" + default n +help + This is rtmp support. + +config JPEG + bool "Enable jpeg" + default n +help + Support JPEG and RGB conversion. + +config SPI_SDCARD + bool "Enable SPI SD Card" + default n +help + Support SPI SD Card support. + +config BT + bool "Enable BT OR BLE" + default n +help + This is BT support. + +config VIOCE_CALL + bool "Enable VoiceCall" + default n +help + This is VoiceCall support. + +config TTS + bool "Enable TTS" + default n +help + This is TTS support. + + diff --git a/extmod/modaes.c b/extmod/modaes.c new file mode 100644 index 0000000..1958923 --- /dev/null +++ b/extmod/modaes.c @@ -0,0 +1,654 @@ +// +// Created by ol on 2020/8/31. +// + +#include "modaes.h" + + + + + + + +/* + * Forward S-box + */ +static const unsigned char FSb[256] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 + }; + +/* + * Forward tables + */ +#define FT \ + \ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned int FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned int FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned int FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned int FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = + { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D + }; + +/* + * Reverse tables + */ +#define RT \ + \ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned int RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned int RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned int RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned int RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const unsigned int RCON[10] = + { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 + }; + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + { \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ + } + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + { \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ + } + + +void aes_setkey_enc( mp_aes_context* ctx, const unsigned char* key, int keysize ) +{ + int i; + unsigned int* RK; + + switch ( keysize ) + { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default : + keysize = 128; + ctx->nr = 10; + break; + } + + ctx->rk = RK = ctx->buf; + + memcpy( RK, key, keysize >> 3 ); + + switch ( ctx->nr ) + { + case 10: + for ( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( ( unsigned int ) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + case 12: + for ( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( ( unsigned int ) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + case 14: + for ( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( ( unsigned int ) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( ( unsigned int ) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } +} + + +void aes_setkey_dec( mp_aes_context* ctx, const unsigned char* key, int keysize ) +{ + int i, j; + mp_aes_context cty; + unsigned int* RK; + unsigned int* SK; + + ctx->rk = RK = ctx->buf; + + aes_setkey_enc( &cty, key, keysize ); + ctx->nr = cty.nr; + SK = cty.rk + ( cty.nr << 2 ); + + memcpy( RK, SK, sizeof( unsigned int ) << 2 ); + RK += 4; + SK -= 4; + + for ( i = ctx->nr - 1; i > 0; i--, SK -= 8 ) + { + for ( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + memcpy( RK, SK, sizeof( unsigned int ) << 2 ); +} + + +void aes_crypt_ecb_update( mp_aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16] ) +{ + int i; + unsigned int* RK; + unsigned int X[4], Y[4]; + + RK = ctx->rk; + + for ( i = 0; i < 4; i ++ ) + { + X[i] = ( *( ( unsigned int* )input + i ) ) ^ ( *RK++ ); + } + + if ( mode == AES_DECRYPT ) + { + for ( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y[0], Y[1], Y[2], Y[3], X[0], X[1], X[2], X[3] ); + AES_RROUND( X[0], X[1], X[2], X[3], Y[0], Y[1], Y[2], Y[3] ); + } + + AES_RROUND( Y[0], Y[1], Y[2], Y[3], X[0], X[1], X[2], X[3] ); + + X[0] = *RK++ ^ \ + ( ( unsigned int ) RSb[ ( Y[0] ) & 0xFF ] ) ^ + ( ( unsigned int ) RSb[ ( Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) RSb[ ( Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) RSb[ ( Y[1] >> 24 ) & 0xFF ] << 24 ); + + X[1] = *RK++ ^ \ + ( ( unsigned int ) RSb[ ( Y[1] ) & 0xFF ] ) ^ + ( ( unsigned int ) RSb[ ( Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) RSb[ ( Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) RSb[ ( Y[2] >> 24 ) & 0xFF ] << 24 ); + + X[2] = *RK++ ^ \ + ( ( unsigned int ) RSb[ ( Y[2] ) & 0xFF ] ) ^ + ( ( unsigned int ) RSb[ ( Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) RSb[ ( Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) RSb[ ( Y[3] >> 24 ) & 0xFF ] << 24 ); + + X[3] = *RK++ ^ \ + ( ( unsigned int ) RSb[ ( Y[3] ) & 0xFF ] ) ^ + ( ( unsigned int ) RSb[ ( Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) RSb[ ( Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) RSb[ ( Y[0] >> 24 ) & 0xFF ] << 24 ); + } + else /* AES_ENCRYPT */ + { + for ( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y[0], Y[1], Y[2], Y[3], X[0], X[1], X[2], X[3] ); + AES_FROUND( X[0], X[1], X[2], X[3], Y[0], Y[1], Y[2], Y[3] ); + } + + AES_FROUND( Y[0], Y[1], Y[2], Y[3], X[0], X[1], X[2], X[3] ); + + X[0] = *RK++ ^ \ + ( ( unsigned int ) FSb[ ( Y[0] ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( Y[3] >> 24 ) & 0xFF ] << 24 ); + + X[1] = *RK++ ^ \ + ( ( unsigned int ) FSb[ ( Y[1] ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( Y[0] >> 24 ) & 0xFF ] << 24 ); + + X[2] = *RK++ ^ \ + ( ( unsigned int ) FSb[ ( Y[2] ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( Y[1] >> 24 ) & 0xFF ] << 24 ); + + X[3] = *RK++ ^ \ + ( ( unsigned int ) FSb[ ( Y[3] ) & 0xFF ] ) ^ + ( ( unsigned int ) FSb[ ( Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( ( unsigned int ) FSb[ ( Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( ( unsigned int ) FSb[ ( Y[2] >> 24 ) & 0xFF ] << 24 ); + } + + memcpy( output, X, 16 ); +} + +// free later +int aes_crypt_ecb( mp_aes_context* ctx, int mode, const unsigned char* input, unsigned char *output, int slen, int* dlen ) +{ + register int i; + register int n; +// unsigned char* output; + unsigned char buff[16]; + + if ( mode == AES_ENCRYPT ) + { + n = 16 - ( slen & 15 ); + *dlen = slen + n; + + //output = ( unsigned char* )malloc( *dlen ); + if ( !output ) + { + return -1; + } + + memset( buff, n, sizeof( buff ) ); + if ( slen & 15 ) + { + memcpy( buff, input + ( slen & ~15 ), slen & 15 ); + } + + n = ( slen >> 4 ); + for ( i = 0; i < n; i ++ ) + { + aes_crypt_ecb_update( ctx, AES_ENCRYPT, \ + input + ( i << 4 ), output + ( i << 4 ) ); + } + aes_crypt_ecb_update( ctx, AES_ENCRYPT, buff, output + ( i << 4 ) ); + } + else + { + //output = ( unsigned char* )malloc( slen ); + if ( !output ) + { + return -1; + } + + n = ( slen >> 4 ); + for ( i = 0; i < n; i ++ ) + { + aes_crypt_ecb_update( ctx, AES_DECRYPT, \ + input + ( i << 4 ), output + ( i << 4 ) ); + } + + *dlen = slen - ( int )output[slen - 1]; + } + + //return output; + return 0; +} + +#if 0 + static const unsigned char base64_enc_map[64] = + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' + }; + + static const unsigned char base64_dec_map[128] = + { + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 + }; +#endif + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + +const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int mp_base64_encode( const unsigned char * bindata, char * base64, int binlength ) +{ + int i, j; + unsigned char current; + + for ( i = 0, j = 0 ; i < binlength ; i += 3 ) + { + current = (bindata[i] >> 2) ; + current &= (unsigned char)0x3F; + base64[j++] = base64char[(int)current]; + + current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ; + if ( i + 1 >= binlength ) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + base64[j++] = '='; + break; + } + current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F ); + base64[j++] = base64char[(int)current]; + + current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ; + if ( i + 2 >= binlength ) + { + base64[j++] = base64char[(int)current]; + base64[j++] = '='; + break; + } + current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 ); + base64[j++] = base64char[(int)current]; + + current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ; + base64[j++] = base64char[(int)current]; + } + base64[j] = '\0'; + return j; +} diff --git a/extmod/modaes.h b/extmod/modaes.h new file mode 100644 index 0000000..379bd68 --- /dev/null +++ b/extmod/modaes.h @@ -0,0 +1,28 @@ +// +// Created by ol on 2020/8/31. +// + +#ifndef UNTITLED_AES_H +#define UNTITLED_AES_H +#include "string.h" + + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 +/* 128 bit key */ +#define AES_KEY_LEN 128 + +typedef struct +{ + int nr; /*!< number of rounds */ + unsigned int* rk; /*!< AES round keys */ + unsigned int buf[68]; /*!< unaligned data */ +}mp_aes_context; + +void aes_setkey_enc( mp_aes_context* ctx, const unsigned char* key, int keysize ); +void aes_setkey_dec( mp_aes_context* ctx, const unsigned char* key, int keysize ); +void aes_crypt_ecb_update( mp_aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16] ); +int aes_crypt_ecb( mp_aes_context* ctx, int mode, const unsigned char* input, unsigned char *output, int slen, int* dlen ); + +int mp_base64_encode( const unsigned char * bindata, char * base64, int binlength ); +#endif //UNTITLED_AES_H diff --git a/extmod/modhash.c b/extmod/modhash.c new file mode 100644 index 0000000..67d7e90 --- /dev/null +++ b/extmod/modhash.c @@ -0,0 +1,308 @@ +// +// Created by ol on 2020/9/1. +// + +#include "modhash.h" + + +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include + +/* for uint32_t */ +#include +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN //[2020-08-06][Gary]Added for SHA1 +#endif +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] +) +{ + uint32_t a, b, c, d, e; + + typedef union + { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init( + SHA1_CTX * context +) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len +) +{ + uint32_t i; + + uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) + { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context +) +{ + unsigned i; + + unsigned char finalcount[8]; + + unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t} +#else + for (i = 0; i < 8; i++) + { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) + { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void SHA1( + char *hash_out, + const char *str, + int len) +{ + SHA1_CTX ctx; + unsigned int ii; + + SHA1Init(&ctx); + for (ii = 0; ii < (unsigned int)len; ii += 1) + { + SHA1Update(&ctx, (const unsigned char*)str + ii, 1); + } + SHA1Final((unsigned char *)hash_out, &ctx); + hash_out[20] = '\0'; + //uart_printf("[SHA1] %%%%%% input=%s, output=%s\n", str, hash_out); +} + diff --git a/extmod/modhash.h b/extmod/modhash.h new file mode 100644 index 0000000..f79f237 --- /dev/null +++ b/extmod/modhash.h @@ -0,0 +1,44 @@ +// +// Created by ol on 2020/10/28. +// + + +/* + SHA-1 in C + By Steve Reid + 100% Public Domain + */ + +#include "stdint.h" + +typedef struct +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +}SHA1_CTX; + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] +); + +void SHA1Init( + SHA1_CTX * context +); + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len +); + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context +); + +void SHA1( + char *hash_out, + const char *str, + int len); diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index d853ef6..4b25bd2 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -57,6 +57,9 @@ #include "mbedtls/sha1.h" #endif +#include "modhash.h" +#include "modaes.h" + #endif typedef struct _mp_obj_hash_t { @@ -238,6 +241,144 @@ STATIC const mp_obj_type_t uhashlib_sha1_type = { .make_new = uhashlib_sha1_make_new, .locals_dict = (void *)&uhashlib_sha1_locals_dict, }; + +int str2dec(const uint8_t *src, int srclen, uint8_t *dst) +{ + int i = 0, j = 0; + int dstlen = 0; + uint8_t temp[250] = {0}; + uint8_t dec_buf[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + uint8_t ascii_buf[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + // unsigned char temp[150] = {0}; + // unsigned char dec_buf[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + // unsigned char ascii_buf[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + for (i=0; i> 4) & 0x0f; + l = src[i] & 0x0f; + dst[2*i] = ascii_buf[h]; + dst[2*i+1] = ascii_buf[l]; + } + dst[2*i] = '\0'; + return (2*i); +} + + +STATIC mp_obj_t mp_hash_sha1(mp_obj_t arg) +{ + char out_buff[20] = {0}; + char str_buff[25] = {0}; + char return_buff[45] = {0}; + + mp_buffer_info_t argbuff; + mp_get_buffer_raise(arg, &argbuff, MP_BUFFER_READ); + + str2dec((uint8_t *)argbuff.buf, argbuff.len, (uint8_t *)out_buff); + + SHA1(str_buff, out_buff, 20); + dec2str( (uint8_t *)str_buff, 20, (uint8_t *)return_buff); + + return mp_obj_new_str(return_buff, strlen(return_buff)); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_hash_sha1_obj, mp_hash_sha1); + +STATIC mp_obj_t mp_hash_aes_ecb(mp_obj_t aes_key, mp_obj_t aes_data) +{ + int dlen; + char out[100] = {0}; + char return_buff[200] = {0}; + + mp_aes_context ctx; + + mp_buffer_info_t key_buff; + mp_get_buffer_raise(aes_key, &key_buff, MP_BUFFER_READ); + + mp_buffer_info_t data_buff; + mp_get_buffer_raise(aes_data, &data_buff, MP_BUFFER_READ); + + aes_setkey_enc(&ctx, (unsigned char*)key_buff.buf, 128); + + aes_crypt_ecb(&ctx, AES_ENCRYPT, (unsigned char*)data_buff.buf, (unsigned char *)out, data_buff.len, &dlen); + + dec2str((uint8_t *)out, 96, (uint8_t *)return_buff); + + + return mp_obj_new_str(return_buff, strlen(return_buff)); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_hash_aes_ecb_obj, mp_hash_aes_ecb); + + +STATIC mp_obj_t mp_hash_b64(mp_obj_t b64_data) +{ + int buflen; + + char out_buff[100] = {0}; + char return_buff[130] = {0}; + + mp_buffer_info_t b64_buff; + mp_get_buffer_raise(b64_data, &b64_buff, MP_BUFFER_READ); + + //mp_printf(&mp_plat_print, "[b64]buf =[%s]\n", (char *)b64_buff.buf); + buflen = str2dec((uint8_t *)b64_buff.buf, b64_buff.len, (uint8_t *)out_buff); + //mp_printf(&mp_plat_print, "[b64]buflen=%d \n", buflen); + + mp_base64_encode((unsigned char *)out_buff, return_buff, buflen); + + //mp_printf(&mp_plat_print, "[b64]len=%d \n", len); + //mp_printf(&mp_plat_print, "[b64]str_len=%d \n", strlen(return_buff)); + //mp_printf(&mp_plat_print, "[b64]return_buff=%s \n", return_buff); + + return mp_obj_new_str(return_buff, strlen(return_buff)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_hash_b64_obj, mp_hash_b64); + + #endif #if MICROPY_PY_UHASHLIB_MD5 @@ -334,6 +475,9 @@ STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = { #endif #if MICROPY_PY_UHASHLIB_SHA1 { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) }, + { MP_ROM_QSTR(MP_QSTR_hash_sha1), MP_ROM_PTR(&mp_hash_sha1_obj) }, + { MP_ROM_QSTR(MP_QSTR_aes_ecb), MP_ROM_PTR(&mp_hash_aes_ecb_obj) }, + { MP_ROM_QSTR(MP_QSTR_hash_base64), MP_ROM_PTR(&mp_hash_b64_obj) }, #endif #if MICROPY_PY_UHASHLIB_MD5 { MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) }, diff --git a/extmod/moduselect.c b/extmod/moduselect.c index b5f8342..b42a2c5 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -122,7 +122,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { mp_obj_get_array(args[2], &rwx_len[2], &x_array); // get timeout - mp_uint_t timeout = -1; + mp_uint_t timeout = (mp_uint_t)(-1); if (n_args == 4) { if (args[3] != mp_const_none) { #if MICROPY_PY_BUILTINS_FLOAT @@ -149,7 +149,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { // poll the objects mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len); - if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { + if (n_ready > 0 || (timeout != (mp_uint_t)(-1) && mp_hal_ticks_ms() - start_tick >= timeout)) { // one or more objects are ready, or we had a timeout mp_obj_t list_array[3]; list_array[0] = mp_obj_new_list(rwx_len[0], NULL); @@ -226,11 +226,12 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); +extern void Helios_msleep(uint32_t ms); STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); // work out timeout (its given already in ms) - mp_uint_t timeout = -1; + mp_uint_t timeout = (mp_uint_t)(-1); int flags = 0; if (n_args >= 2) { if (args[1] != mp_const_none) { @@ -251,9 +252,13 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { for (;;) { // poll the objects n_ready = poll_map_poll(&self->poll_map, NULL); - if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) { + if (n_ready > 0 || (timeout != (mp_uint_t)(-1) && mp_hal_ticks_ms() - start_tick >= timeout)) { break; } + else + { + Helios_msleep(1); + } MICROPY_EVENT_POLL_HOOK } diff --git a/extmod/vfs.c b/extmod/vfs.c index 27479c0..642ae14 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -374,23 +374,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open); mp_obj_t mp_vfs_chdir(mp_obj_t path_in) { mp_obj_t path_out; - // Pawn -2021-03-18 : Fixed file path error returns error message - const char *path = mp_obj_str_get_str(path_in); - if ( path[0] == '/' ) - { - if ( strncmp(path, "/usr/", 5) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - else - { - if ( strncmp(path, "usr/", 4) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - // Pawn -2021-03-18 : Fixed file path error returns error message + mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT) { // If we change to the root dir and a VFS is mounted at the root then @@ -513,23 +497,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir); mp_obj_t mp_vfs_mkdir(mp_obj_t path_in) { mp_obj_t path_out; - // Pawn -2021-03-18 : Fixed file path error returns error message - const char *path = mp_obj_str_get_str(path_in); - if ( path[0] == '/' ) - { - if ( strncmp(path, "/usr/", 5) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - else - { - if ( strncmp(path, "usr/", 4) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - // Pawn -2021-03-18 : Fixed file path error returns error message + mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) { mp_raise_OSError(MP_EEXIST); @@ -550,21 +518,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj, mp_vfs_mkdir); mp_obj_t mp_vfs_remove(mp_obj_t path_in) { mp_obj_t path_out; const char *path = mp_obj_str_get_str(path_in); - // Pawn -2021-03-18 : Fixed file path error returns error message - if ( path[0] == '/' ) - { - if ( strncmp(path, "/usr/", 5) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - else - { - if ( strncmp(path, "usr/", 4) != 0) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } + mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); //Kenney.wang 20201228 vfs readonly @@ -581,24 +535,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_remove_obj, mp_vfs_remove); mp_obj_t mp_vfs_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { mp_obj_t args[2]; - // Pawn -2021-03-18 : Fixed file path error returns error message - const char *old_path = mp_obj_str_get_str(old_path_in); - const char *new_path = mp_obj_str_get_str(new_path_in); - if ( (old_path[0] == '/') && (new_path[0] == '/') ) - { - if ( (strncmp(old_path, "/usr/", 5) != 0) && (strncmp(new_path, "/usr/", 5) != 0)) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - else - { - if ( (strncmp(old_path, "usr/", 4) != 0) && (strncmp(new_path, "usr/", 4) != 0)) - { - mp_raise_msg_varg(&mp_type_OSError, "File path error, Use an absolute path('/usr/xxx')"); - } - } - // Pawn -2021-03-18 : Fixed file path error returns error message + mp_vfs_mount_t *old_vfs = lookup_path(old_path_in, &args[0]); mp_vfs_mount_t *new_vfs = lookup_path(new_path_in, &args[1]); if (old_vfs != new_vfs) { diff --git a/extmod/vfs_efs.c b/extmod/vfs_efs.c new file mode 100644 index 0000000..5f1491c --- /dev/null +++ b/extmod/vfs_efs.c @@ -0,0 +1,664 @@ +/* + * 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_Qualcomm) + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/mpthread.h" +#include "py/objstr.h" +#include "extmod/vfs.h" +#include "extmod/vfs_efs.h" + +#include +#include + +#include "helios_fs.h" + + +#define EFS_NAME_MAX (768) /* Maximum length of a file name. */ +#define EFS_IFDIR (0040000) /**< Directory */ +#define EFS_IFMT (0170000) /**< Mask of all values */ + + struct efs_stat_type_s { + uint16_t st_dev; /**< Unique device ID among the mounted file + systems. */ + uint32_t st_ino; /**< INode number associated with the file. */ + uint16_t st_Mode; /**< Mode associated with the file. */ + uint8_t st_nlink; /**< Number of active links that are + referencing this file. The space occupied + by the file is released after its + references are reduced to 0. */ + uint32_t st_size; /**< File size in bytes. */ + unsigned long st_blksize; /**< Block size; smallest allocation unit of + the file system. The unit in which + the block Count is represented. */ + unsigned long st_blocks; /**< Number of blocks allocated for this file + in st_blksize units. */ + uint32_t st_atime; /**< Last access time. This is not updated, so + it might have an incorrect value. */ + uint32_t st_mtime; /**< Last modification time. Currently, this + indicates the time when the file was + created. */ + uint32_t st_ctime; /**< Last status change time. Currently, this + indicates the time when the file was + created. */ + uint32_t st_rdev; /**< Major and minor device number for special + device files. */ + uint16_t st_uid; /**< Owner or user ID of the file. */ + uint16_t st_gid; /**< Group ID of the file. The stored file data + blocks are charged to the quota of this + group ID. */ +}; + +enum efs_filename_rule_e{ + EFS_FILENAME_RULE_8BIT_RELAXED = 1, /**< 8-bit relaxed rule. */ + EFS_FILENAME_RULE_FAT = 2, /**< FAT rule. */ + EFS_FILENAME_RULE_FDI = 3 /**< FDI rule. */ +}; + +enum efs_filename_encoding_e{ + EFS_FILENAME_ENCODING_8BIT = 1, /**< 8-bit encoding. */ + EFS_FILENAME_ENCODING_UTF8 = 2 /**< UTF8 encoding. */ +}; +struct efs_statvfs_type_s { + unsigned long f_bsize; + /**< Fundamental file system block size. Minimum allocations in + the file system happen at this size. */ + uint32_t f_blocks; + /**< Maximum possible number of blocks available in the entire + file system. */ + uint32_t f_bfree; + /**< Total number of free blocks. */ + uint32_t f_bavail; + /**< Number of free blocks currently available. */ + uint32_t f_files; + /**< Total number of file serial numbers. */ + uint32_t f_ffree; + /**< Total number of free file serial numbers. */ + uint32_t f_favail; + /**< Number of file serial numbers available. */ + unsigned long f_fsid; + /**< File system ID; this varies depending on the implementation + of the file system. */ + unsigned long f_flag; + /**< Bitmask of f_flag values. */ + unsigned long f_namemax; + /**< Maximum length of the name part of the string for a file, + directory, or symlink. */ + unsigned long f_maxwrite; + /**< Maximum number of bytes that can be written in a single + write call. */ + uint32_t f_balloc; + /**< Blocks allocated in the general pool. */ + uint32_t f_hardalloc; + /**< Hard allocation count. Resource intensive, so this is not + usually computed. */ + unsigned long f_pathmax; + /**< Maximum path length, excluding the trailing NULL. The unit here + is in terms of character symbols. The number of bytes needed + to represent a character will vary depending on the + file name encoding scheme. For example, in a UTF8 encoding scheme, + representing a single character could take anywhere between + 1 to 4 bytes. */ + unsigned long f_is_case_sensitive; + /**< Set to 1 if Path is case sensitive. */ + unsigned long f_is_case_preserving; + /**< Set to 1 if Path is case preserved. */ + unsigned long f_max_file_size; + /**< Maximum file size in the units determined by the member + f_max_file_size_unit. */ + unsigned long f_max_file_size_unit; + /**< Unit type for f_max_file_size. */ + unsigned long f_max_open_files; + /**< This member tells how many files can be kept opened for one + particular file system. However, there is a global limit on how + many files can be kept opened simultaneously across all + file systems, which is configured by EFS_MAX_DESCRIPTORS. */ + enum efs_filename_rule_e f_name_rule; + /**< File naming rule. */ + enum efs_filename_encoding_e f_name_encoding; + /**< Encoding scheme. */ +}; + +struct efs_iter_entry_s { + char file_Path[EFS_NAME_MAX+1]; + /**< Name of the directory component. */ + struct efs_stat_type_s SBuf; + /**< See qapi_FS_Stat_Type_s for information on this structure. */ + uint32_t EFS_D_Stats_Present; + /**< Bitmask for the EFS_Stat_Type_s structure that defines + which fields are filled when the Helios_fdirread() API is called. */ +}; + +enum { EFS_MAKE_ARG_pname }; + +const mp_arg_t efs_make_allowed_args[] = { + { MP_QSTR_pname, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +}; + +extern int Helios_frename(const char *old_path, const char *new_path); +extern int Helios_frmdir(const char *path); +extern int Helios_fmkdir(const char *path, uint16_t mode); +extern int Helios_fstat(const char *path, struct efs_stat_type_s *sb); +extern int Helios_fstatvfs(const char *path, struct efs_statvfs_type_s *sb); +extern void* Helios_fdiropen(const char *path); +extern int Helios_fdirread(void* iter_handle, struct efs_iter_entry_s *iter_entry); +extern int Helios_fdirclose(void* iter_handle); + +const char *mp_vfs_efs_make_path(mp_obj_vfs_efs_t *self, mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + if (path[0] != '/') { + size_t l = vstr_len(&self->cur_dir); + if (l > 0) { + vstr_add_str(&self->cur_dir, path); + path = vstr_null_terminated_str(&self->cur_dir); + self->cur_dir.len = l; + } + } + return path; +} + +STATIC mp_import_stat_t mp_vfs_efs_import_stat(void *self_in, const char *path) { + mp_obj_vfs_efs_t *self = self_in; + struct efs_stat_type_s sb = {0}; + + //compatible for "from usr import module" function + if(0 == strncmp(path, "usr", 3)) + { + path = &path[3]; + } + + mp_obj_str_t path_obj = { { &mp_type_str }, 0, 0, (const byte *)path }; + path = mp_vfs_efs_make_path(self, MP_OBJ_FROM_PTR(&path_obj)); + char f_path[64] = "/usr"; + sprintf(f_path, "%s%s", "/usr", path); + + int ret = Helios_fstat(f_path, &sb); + if (ret == 0) + { + if (((sb.st_Mode) & EFS_IFMT) == EFS_IFDIR) + { + return MP_IMPORT_STAT_DIR; + } + else + { + return MP_IMPORT_STAT_FILE; + } + } + + return MP_IMPORT_STAT_NO_EXIST; +} + +STATIC mp_obj_t vfs_efs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_val_t args_parse[MP_ARRAY_SIZE(efs_make_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(efs_make_allowed_args), efs_make_allowed_args, args_parse); + char *partition_name = (char *)mp_obj_str_get_str(args_parse[EFS_MAKE_ARG_pname].u_obj); + + mp_obj_vfs_efs_t *vfs = m_new_obj(mp_obj_vfs_efs_t); + vfs->base.type = type; + vstr_init(&vfs->cur_dir, 16); + vstr_add_byte(&vfs->cur_dir, '/'); + + if(strcmp(partition_name, "customer_fs") == 0) + { + vfs->readonly = false; + //create dir for micropython dir "/usr" + Helios_fmkdir("/usr", 0777); + } + else + { + vfs->readonly = true; + //create dir for micropython dir "/bak" + Helios_fmkdir("/bak", 0777); + } + + return MP_OBJ_FROM_PTR(vfs); +} + +STATIC mp_obj_t vfs_efs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { + /*mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); + if (mp_obj_is_true(readonly)) { + self->readonly = true; + } + if (mp_obj_is_true(mkfs)) { + mp_raise_OSError(MP_EPERM); + } + return mp_const_none;*/ + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_efs_mount_obj, vfs_efs_mount); + +STATIC mp_obj_t vfs_efs_umount(mp_obj_t self_in) { + (void)self_in; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_efs_umount_obj, vfs_efs_umount); + +STATIC mp_obj_t vfs_efs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *mode = mp_obj_str_get_str(mode_in); + const char *path = mp_obj_str_get_str(path_in); + + //compatible for "from usr import module" function + if(0 == strncmp(path, "usr", 3)) + { + path = &path[3]; + } + + mp_obj_str_t path_obj = { { &mp_type_str }, 0, 0, (const byte *)path }; + path = mp_vfs_efs_make_path(self, MP_OBJ_FROM_PTR(&path_obj)); + path_obj.data = (const byte *)path; + + return mp_vfs_efs_file_open(self_in, &mp_type_vfs_efs_textio, MP_OBJ_FROM_PTR(&path_obj), mode_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_efs_open_obj, vfs_efs_open); + +STATIC mp_obj_t vfs_efs_chdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + + // Check path exists + const char *path = mp_vfs_efs_make_path(self, path_in); + if (path[1] != '\0') { + // Not at root, check it exists + struct efs_stat_type_s sb = {0}; + char f_path[64] = ""; + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + int ret = Helios_fstat(f_path, &sb); + if ((ret != 0) || ((sb.st_Mode & EFS_IFMT) != EFS_IFDIR)) { + mp_raise_OSError(-MP_ENOENT); + } + } + + // Update cur_dir with new path + if (path == vstr_str(&self->cur_dir)) { + self->cur_dir.len = strlen(path); + } else { + vstr_reset(&self->cur_dir); + vstr_add_str(&self->cur_dir, path); + } + + // If not at root add trailing / to make it easy to build paths + // and then normalise the path + if (vstr_len(&self->cur_dir) != 1) { + vstr_add_byte(&self->cur_dir, '/'); + + #define CWD_LEN (vstr_len(&self->cur_dir)) + size_t to = 1; + size_t from = 1; + char *cwd = vstr_str(&self->cur_dir); + while (from < CWD_LEN) { + for (; cwd[from] == '/' && from < CWD_LEN; ++from) { + // Scan for the start + } + if (from > to) { + // Found excessive slash chars, squeeze them out + vstr_cut_out_bytes(&self->cur_dir, to, from - to); + from = to; + } + for (; cwd[from] != '/' && from < CWD_LEN; ++from) { + // Scan for the next / + } + if ((from - to) == 1 && cwd[to] == '.') { + // './', ignore + vstr_cut_out_bytes(&self->cur_dir, to, ++from - to); + from = to; + } else if ((from - to) == 2 && cwd[to] == '.' && cwd[to + 1] == '.') { + // '../', skip back + if (to > 1) { + // Only skip back if not at the tip + for (--to; to > 1 && cwd[to - 1] != '/'; --to) { + // Skip back + } + } + vstr_cut_out_bytes(&self->cur_dir, to, ++from - to); + from = to; + } else { + // Normal element, keep it and just move the offset + to = ++from; + } + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_chdir_obj, vfs_efs_chdir); + +STATIC mp_obj_t vfs_efs_getcwd(mp_obj_t self_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + if (vstr_len(&self->cur_dir) == 1) { + return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); + } else { + // don't include trailing / + return mp_obj_new_str(self->cur_dir.buf, self->cur_dir.len - 1); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_efs_getcwd_obj, vfs_efs_getcwd); + +typedef struct _vfs_efs_ilistdir_it_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + bool is_str; + void *dir; + bool readonly; +} vfs_efs_ilistdir_it_t; + +STATIC mp_obj_t vfs_efs_ilistdir_it_iternext(mp_obj_t self_in) { + vfs_efs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + char real_file_path[128] = ""; + struct efs_stat_type_s sb = {0}; + + if (self->dir == NULL) + { + return MP_OBJ_STOP_ITERATION; + } + struct efs_iter_entry_s iter_entry; + + for (;;) + { + int ret = Helios_fdirread(self->dir, &iter_entry); + + if (ret != 0 || strlen(iter_entry.file_Path) == 0) + { + // stop on error or end of dir + break; + } + + if (iter_entry.file_Path[0] == '.' && (iter_entry.file_Path[1] == 0 || iter_entry.file_Path[1] == '.')) + { + // skip . and .. + continue; + } + + // make 4-tuple with info about this entry + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); + if (self->is_str) + { + t->items[0] = mp_obj_new_str(iter_entry.file_Path, strlen(iter_entry.file_Path)); + } + else + { + 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); + } + 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); + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number + t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_size); + + return MP_OBJ_FROM_PTR(t); + } + + Helios_fdirclose(self->dir); + self->dir = NULL; + + return MP_OBJ_STOP_ITERATION; +} + +STATIC mp_obj_t vfs_efs_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + vfs_efs_ilistdir_it_t *iter = m_new_obj(vfs_efs_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = vfs_efs_ilistdir_it_iternext; + 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] = ""; + + if (path[0] == '\0') { + path = "."; + } + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + iter->readonly = true; + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + iter->readonly = false; + } + + iter->dir = Helios_fdiropen(f_path); + if (iter->dir == NULL) { + mp_raise_OSError(-1); + } + return MP_OBJ_FROM_PTR(iter); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_ilistdir_obj, vfs_efs_ilistdir); + +STATIC mp_obj_t vfs_efs_mkdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_efs_make_path(self, path_in); + char f_path[64] = ""; + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + int ret = Helios_fmkdir(f_path, 0777); + if (ret != 0) { + mp_raise_OSError(ret); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_mkdir_obj, vfs_efs_mkdir); + +STATIC mp_obj_t vfs_efs_remove(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_efs_make_path(self, path_in); + char f_path[64] = ""; + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + int ret = Helios_remove(f_path); + if (ret != 0) { + mp_raise_OSError(ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_remove_obj, vfs_efs_remove); + +STATIC mp_obj_t vfs_efs_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *old_path = mp_vfs_efs_make_path(self, old_path_in); + const char *new_path = mp_obj_str_get_str(new_path_in); + vstr_t path_new; + vstr_init(&path_new, vstr_len(&self->cur_dir)); + if (new_path[0] != '/') { + vstr_add_strn(&path_new, vstr_str(&self->cur_dir), vstr_len(&self->cur_dir)); + } + vstr_add_str(&path_new, new_path); + char o_path[64] = ""; + char n_path[64] = ""; + + if(self->readonly) + { + sprintf(o_path, "%s%s", "/bak", old_path); + sprintf(n_path, "%s%s", "/bak", vstr_null_terminated_str(&path_new)); + } + else + { + sprintf(o_path, "%s%s", "/usr", old_path); + sprintf(n_path, "%s%s", "/usr", vstr_null_terminated_str(&path_new)); + } + + + int ret = Helios_frename(o_path, n_path); + vstr_clear(&path_new); + if (ret != 0) { + mp_raise_OSError(ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_efs_rename_obj, vfs_efs_rename); + +STATIC mp_obj_t vfs_efs_rmdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_efs_make_path(self, path_in); + char f_path[64] = ""; + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + int ret = Helios_frmdir(f_path); + if (ret != 0) { + mp_raise_OSError(ret); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_rmdir_obj, vfs_efs_rmdir); + +STATIC mp_obj_t vfs_efs_stat(mp_obj_t self_in, mp_obj_t path_in) { + int ret; + struct efs_stat_type_s sb = {0}; + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_efs_make_path(self, path_in); + char f_path[64] = ""; + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + ret = Helios_fstat(f_path, &sb); + if (ret != 0) { + mp_raise_OSError(ret); + } + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(((sb.st_Mode) & EFS_IFMT) == EFS_IFDIR ? MP_S_IFDIR : MP_S_IFREG);// st_mode + t->items[1] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_ino);// st_ino + t->items[2] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_dev);// st_dev + t->items[3] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_nlink);// st_nlink + t->items[4] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_uid);// st_uid + t->items[5] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_gid);// st_gid + t->items[6] = mp_obj_new_int_from_uint(sb.st_size);// st_size + t->items[7] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_atime);// st_atime + t->items[8] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_mtime);// st_mtime + t->items[9] = MP_OBJ_NEW_SMALL_INT(0);//mp_obj_new_int_from_uint(sb.st_ctime);// st_ctime + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_stat_obj, vfs_efs_stat); + + +STATIC mp_obj_t vfs_efs_statvfs(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + int ret; + struct efs_statvfs_type_s sb = {0}; + const char *path = mp_obj_str_get_str(path_in); + char f_path[64] = ""; + + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", path); + } + else + { + sprintf(f_path, "%s%s", "/usr", path); + } + + ret = Helios_fstatvfs(f_path, &sb); + if (ret != 0) { + mp_raise_OSError(ret); + } + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize);// f_bsize + t->items[1] = t->items[0];// f_frsize + t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks);//MP_OBJ_NEW_SMALL_INT(256);// f_blocks + t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.f_bfree);// f_bfree + t->items[4] = t->items[3];// f_bavail + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files + t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags + t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.f_namemax); + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_efs_statvfs_obj, vfs_efs_statvfs); + +STATIC const mp_rom_map_elem_t vfs_efs_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_efs_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_efs_umount_obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&vfs_efs_open_obj) }, + + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&vfs_efs_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&vfs_efs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&vfs_efs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&vfs_efs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&vfs_efs_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_efs_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_efs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_efs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_efs_statvfs_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(vfs_efs_locals_dict, vfs_efs_locals_dict_table); + +STATIC const mp_vfs_proto_t vfs_efs_proto = { + .import_stat = mp_vfs_efs_import_stat, +}; + +const mp_obj_type_t mp_type_vfs_efs = { + { &mp_type_type }, + .name = MP_QSTR_VfsEfs, + .make_new = vfs_efs_make_new, + .protocol = &vfs_efs_proto, + .locals_dict = (mp_obj_dict_t *)&vfs_efs_locals_dict, +}; + +#endif // PLAT_Qualcomm diff --git a/ports/quectel/core/source/utf8togbk.h b/extmod/vfs_efs.h similarity index 49% rename from ports/quectel/core/source/utf8togbk.h rename to extmod/vfs_efs.h index ddce999..2fa1d0d 100644 --- a/ports/quectel/core/source/utf8togbk.h +++ b/extmod/vfs_efs.h @@ -14,10 +14,29 @@ * limitations under the License. */ -#ifndef __UTF8TOGBK_H__ -#define __UTF8TOGBK_H__ +#ifndef _VFS_EFS_H_ +#define _VFS_EFS_H_ -int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen); +#if defined(PLAT_Qualcomm) +#include "py/lexer.h" +#include "py/obj.h" +extern const mp_obj_type_t mp_type_vfs_efs; +extern const mp_obj_type_t mp_type_vfs_efs_fileio; +extern const mp_obj_type_t mp_type_vfs_efs_textio; -#endif +#define EFS_DIR_PATH_ROOT "/datatx/usr" + +typedef struct _mp_obj_vfs_efs_t { + mp_obj_base_t base; + vstr_t cur_dir; + vstr_t root; + size_t root_len; + bool readonly; +} mp_obj_vfs_efs_t; + +mp_obj_t mp_vfs_efs_file_open(mp_obj_t self_in, const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in); + +#endif // PLAT_Qualcomm + +#endif // _VFS_EFS_H_ diff --git a/extmod/vfs_efs_file.c b/extmod/vfs_efs_file.c new file mode 100644 index 0000000..8a2fdb6 --- /dev/null +++ b/extmod/vfs_efs_file.c @@ -0,0 +1,250 @@ +/* + * 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_Qualcomm) +#include + +#include "py/mphal.h" +#include "py/mpthread.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "extmod/vfs_efs.h" + +#include "helios_fs.h" + + +typedef struct _mp_obj_vfs_efs_file_t { + mp_obj_base_t base; + HeliosFILE * fd; +} mp_obj_vfs_efs_file_t; + +#ifdef MICROPY_CPYTHON_COMPAT +STATIC void check_fd_is_open(const mp_obj_vfs_efs_file_t *o) { + if (o->fd < 0) { + mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file")); + } +} +#else +#define check_fd_is_open(o) +#endif + +STATIC void vfs_efs_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; + mp_obj_vfs_efs_file_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); +} + +mp_obj_t mp_vfs_efs_file_open(mp_obj_t self_in, const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { + mp_obj_vfs_efs_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_vfs_efs_file_t *o = m_new_obj(mp_obj_vfs_efs_file_t); + const char *mode = mp_obj_str_get_str(mode_in); + const char *fname = mp_obj_str_get_str(file_in); + HeliosFILE * fd; + char f_path[64] = ""; + + if(NULL != self) + { + if(self->readonly) + { + sprintf(f_path, "%s%s", "/bak", fname); + } + else + { + sprintf(f_path, "%s%s", "/usr", fname); + } + } + else + { + sprintf(f_path, "%s%s", "/usr", fname); + } + + o->base.type = type; + fd = Helios_fopen(f_path, mode); + + if(NULL == fd) + { + mp_raise_OSError(-1); + return mp_const_none; + } + o->fd = fd; + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_obj_t vfs_efs_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, + }; + + mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); + return mp_vfs_efs_file_open(NULL, type, arg_vals[0].u_obj, arg_vals[1].u_obj); +} + +STATIC mp_obj_t vfs_efs_file_fileno(mp_obj_t self_in) { + mp_obj_vfs_efs_file_t *self = MP_OBJ_TO_PTR(self_in); + check_fd_is_open(self); + return MP_OBJ_NEW_SMALL_INT(self->fd); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_efs_file_fileno_obj, vfs_efs_file_fileno); + +STATIC mp_obj_t vfs_efs_file___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + return mp_stream_close(args[0]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_efs_file___exit___obj, 4, 4, vfs_efs_file___exit__); + +STATIC mp_uint_t vfs_efs_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + mp_obj_vfs_efs_file_t *o = MP_OBJ_TO_PTR(o_in); + check_fd_is_open(o); + int r; + + r = Helios_fread(buf, size, 1, o->fd); + if(r < 0) + { + *errcode = -r; + return MP_STREAM_ERROR; + } + + return (mp_uint_t)r; +} + +STATIC mp_uint_t vfs_efs_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { + mp_obj_vfs_efs_file_t *o = MP_OBJ_TO_PTR(o_in); + check_fd_is_open(o); + #if MICROPY_PY_OS_DUPTERM + if (o->fd <= STDERR_FILENO) { + mp_hal_stdout_tx_strn(buf, size); + return size; + } + #endif + int r; + + r = Helios_fwrite((void *)buf, size, 1, o->fd); + if(r < 0) + { + *errcode = -r; + return MP_STREAM_ERROR; + } + + return (mp_uint_t)r; +} + +STATIC mp_uint_t vfs_efs_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mp_obj_vfs_efs_file_t *o = MP_OBJ_TO_PTR(o_in); + check_fd_is_open(o); + switch (request) { + case MP_STREAM_FLUSH: { + /*int ret; + MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { + if (err == EINVAL + && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { + // fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that + // error out. Because data is not buffered by us, and stdin/out/err.flush() + // should just be a no-op. + return 0; + } + *errcode = err; + return MP_STREAM_ERROR; + }); + return 0;*/ + } + case MP_STREAM_SEEK: { + struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg; + int res = Helios_fseek(o->fd, s->offset, s->whence); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + + s->offset = res; + return 0; + } + case MP_STREAM_CLOSE: + Helios_fclose(o->fd); + #ifdef MICROPY_CPYTHON_COMPAT + o->fd = NULL; + #endif + return 0; + case MP_STREAM_GET_FILENO: + return 0; + default: + *errcode = 0; + return MP_STREAM_ERROR; + } +} + +STATIC const mp_rom_map_elem_t vfs_efs_rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_efs_file_fileno_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_efs_file___exit___obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(vfs_efs_rawfile_locals_dict, vfs_efs_rawfile_locals_dict_table); + +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t vfs_efs_fileio_stream_p = { + .read = vfs_efs_file_read, + .write = vfs_efs_file_write, + .ioctl = vfs_efs_file_ioctl, +}; + +const mp_obj_type_t mp_type_vfs_efs_fileio = { + { &mp_type_type }, + .name = MP_QSTR_FileIO, + .print = vfs_efs_file_print, + .make_new = vfs_efs_file_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &vfs_efs_fileio_stream_p, + .locals_dict = (mp_obj_dict_t *)&vfs_efs_rawfile_locals_dict, +}; +#endif + +STATIC const mp_stream_p_t vfs_efs_textio_stream_p = { + .read = vfs_efs_file_read, + .write = vfs_efs_file_write, + .ioctl = vfs_efs_file_ioctl, + .is_text = true, +}; + +const mp_obj_type_t mp_type_vfs_efs_textio = { + { &mp_type_type }, + .name = MP_QSTR_TextIOWrapper, + .print = vfs_efs_file_print, + .make_new = vfs_efs_file_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &vfs_efs_textio_stream_p, + .locals_dict = (mp_obj_dict_t *)&vfs_efs_rawfile_locals_dict, +}; + +/*const mp_obj_vfs_efs_file_t mp_sys_stdin_obj = {{&mp_type_vfs_efs_textio}, STDIN_FILENO}; +const mp_obj_vfs_efs_file_t mp_sys_stdout_obj = {{&mp_type_vfs_efs_textio}, STDOUT_FILENO}; +const mp_obj_vfs_efs_file_t mp_sys_stderr_obj = {{&mp_type_vfs_efs_textio}, STDERR_FILENO}; +*/ + +#endif // PLAT_Qualcomm diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c index ed0748e..8ea6a87 100644 --- a/extmod/vfs_lfs.c +++ b/extmod/vfs_lfs.c @@ -33,9 +33,9 @@ #if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) -#define QUECTE_PY_LFS1 +#define QUECTEL_PY_LFS1 -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 enum { LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead ,LFS_MAKE_ARG_pname }; const mp_arg_t lfs_make_allowed_args[] = { @@ -68,7 +68,7 @@ static const mp_arg_t lfs_make_allowed_args[] = { #define MP_TYPE_VFS_LFSx mp_type_vfs_lfs1 #define MP_TYPE_VFS_LFSx_(s) mp_type_vfs_lfs1##s -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 typedef struct lfs1_flash_info { unsigned int FlashType; diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 1421517..4c9ce1c 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -50,11 +50,11 @@ #define QUEC_QPY_LFS_LOG(msg, ...) #endif -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 #define LFS_BLOCK_SIZE (1024 * 4) #endif -#ifndef QUECTE_PY_LFS1 +#ifndef QUECTEL_PY_LFS1 STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) { mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); int ret_i = 0; @@ -66,7 +66,7 @@ STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, i #endif STATIC int MP_VFS_LFSx(dev_read)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) { -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 unsigned int LfsStartAddress = 0, FlashAddrss = 0; LfsStartAddress = ((LFSx_API(flash_info) *)(c->context))->LfsStartAddress; @@ -78,7 +78,7 @@ STATIC int MP_VFS_LFSx(dev_read)(const struct LFSx_API (config) * c, LFSx_API(bl } STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, const void *buffer, LFSx_API(size_t) size) { -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 unsigned int LfsStartAddress = 0, FlashAddrss = 0; LfsStartAddress = ((LFSx_API(flash_info) *)(c->context))->LfsStartAddress; @@ -90,7 +90,7 @@ STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API (config) * c, LFSx_API(bl } STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API (config) * c, LFSx_API(block_t) block) { -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 unsigned int LfsStartAddress = 0, FlashAddrss = 0; LfsStartAddress = ((LFSx_API(flash_info) *)(c->context))->LfsStartAddress; @@ -102,7 +102,7 @@ STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API (config) * c, LFSx_API(b } STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API (config) * c) { -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 return 0; #else return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_SYNC, 0, false); @@ -110,14 +110,14 @@ STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API (config) * c) { } STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { -#ifndef QUECTE_PY_LFS1 +#ifndef QUECTEL_PY_LFS1 self->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; mp_vfs_blockdev_init(&self->blockdev, bdev); #endif struct LFSx_API (config) * config = &self->config; memset(config, 0, sizeof(*config)); -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 config->context = &self->info; #else config->context = &self->blockdev; @@ -128,7 +128,7 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size config->sync = MP_VFS_LFSx(dev_sync); -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 self->info.FlashType = 0; HeliosFlashPartiCtx *FlashPartiCtx = Helios_Flash_GetPartiCtx((const char*)self->partition_name); @@ -157,7 +157,7 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size #if LFS_BUILD_VERSION == 1 -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 config->lookahead = 32 * ((config->block_count + 31) / 32); #else config->lookahead = lookahead; @@ -195,7 +195,7 @@ STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t * type, size_t n_args, MP_OBJ_VFS_LFSx *self = m_new0(MP_OBJ_VFS_LFSx, 1); self->base.type = type; -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 char *src_data = (char *)mp_obj_str_get_str(args[LFS_MAKE_ARG_pname].u_obj); self->partition_name = src_data; #endif @@ -207,7 +207,7 @@ STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t * type, size_t n_args, self->enable_mtime = args[LFS_MAKE_ARG_mtime].u_bool; #endif -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 MP_VFS_LFSx(init_config)(self, NULL, args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); #else @@ -251,7 +251,7 @@ STATIC mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_ma mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); MP_OBJ_VFS_LFSx self; -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 MP_VFS_LFSx(init_config)(&self, NULL, args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); #else @@ -541,7 +541,7 @@ STATIC mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(statvfs_obj), MP_VFS_LFSx(statvfs)); STATIC mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { -#ifdef QUECTE_PY_LFS1 +#ifdef QUECTEL_PY_LFS1 (void)self_in; (void)readonly; (void)mkfs; diff --git a/lib/littlefs/lfs1_util.h b/lib/littlefs/lfs1_util.h index c3e0f36..db8f44d 100644 --- a/lib/littlefs/lfs1_util.h +++ b/lib/littlefs/lfs1_util.h @@ -78,6 +78,9 @@ extern "C" #define LFS1_ERROR(fmt, ...) #endif +#if defined(PLAT_RDA) +#define LFS1_NO_INTRINSICS +#endif // Runtime assertions #ifndef LFS1_NO_ASSERT diff --git a/lib/utils/interrupt_char.h b/lib/utils/interrupt_char.h index 93d54b1..1b0c97f 100644 --- a/lib/utils/interrupt_char.h +++ b/lib/utils/interrupt_char.h @@ -27,6 +27,36 @@ #ifndef MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_H #define MICROPY_INCLUDED_LIB_UTILS_INTERRUPT_CHAR_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; + +#define RET_KBD_INTERRUPT (0x00FA00FA) + +#define IS_REPL_REFUSED() (1 == repl_protect_enable) + +#define MAINPY_RUNNING_FLAG mainpy_running_flag +#define MAINPY_INTERRUPT_BY_KBD_FLAG mainpy_interrupt_by_kbd_flag + +#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 MAINPY_RUNNING_FLAG_SET() MAINPY_RUNNING_FLAG = 1; +#define MAINPY_RUNNING_FLAG_CLEAR() 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; +#define MAINPY_INTERRUPT_BY_KBD_FLAG_CLEAR() MAINPY_INTERRUPT_BY_KBD_FLAG = 0; +#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 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()) { +#define CHECK_MAINPY_KBD_INTERRUPT_EXIT() } + extern int mp_interrupt_char; void mp_hal_set_interrupt_char(int c); diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index 97f6df5..450604a 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -147,6 +147,9 @@ 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; + } 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; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); ret = 0; @@ -157,7 +160,12 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly - printf("took " UINT_FMT " ms\n", ticks); + #if defined(PLAT_Qualcomm) + printf("took " UINT_FMT " ms\n", (unsigned long)ticks); + #else + printf("took " UINT_FMT " ms\n", ticks); + #endif + // qstr info { size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; @@ -571,7 +579,9 @@ 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 diff --git a/microPython.mk b/microPython.mk index c0f463b..b6f53b4 100644 --- a/microPython.mk +++ b/microPython.mk @@ -5,18 +5,22 @@ include config/$(KCONFIG_CONFIG) $(NAME)_SRCS = \ extmod/modubinascii.c \ - extmod/moducryptolib.c \ extmod/moductypes.c \ - extmod/moduhashlib.c \ extmod/modujson.c \ extmod/modurandom.c \ extmod/modure.c \ extmod/moduzlib.c \ + extmod/moduasyncio.c \ + extmod/moduselect.c \ extmod/utime_mphal.c \ extmod/vfs.c \ extmod/vfs_blockdev.c \ extmod/vfs_lfs.c \ extmod/vfs_reader.c \ + extmod/moducryptolib.c \ + extmod/moduhashlib.c \ + extmod/modaes.c \ + extmod/modhash.c \ lib/littlefs/lfs1.c \ lib/littlefs/lfs1_util.c \ lib/mp-readline/readline.c \ @@ -32,29 +36,32 @@ $(NAME)_SRCS = \ ports/quectel/core/source/mpthreadport.c \ ports/quectel/core/source/quecpython.c \ ports/quectel/core/source/linklist.c \ - ports/quectel/core/source/moddev.c \ - ports/quectel/core/source/moduos.c \ - ports/quectel/core/source/modexample.c \ ports/quectel/core/source/modsha1.c \ ports/quectel/core/source/modutils.c \ ports/quectel/core/source/utils_crc32.c \ - ports/quectel/core/source/modostimer.c \ + ports/quectel/core/build/_frozen_mpy.c \ + ports/quectel/core/source/moduos.c \ + ports/quectel/core/source/modexample.c \ + ports/quectel/core/source/modutime.c \ ports/quectel/core/source/modmachine.c \ + ports/quectel/core/source/machine_uart.c \ ports/quectel/core/source/machine_pin.c \ - ports/quectel/core/source/machine_timer.c \ - ports/quectel/core/source/machine_rtc.c \ + ports/quectel/core/source/machine_extint.c \ + ports/quectel/core/source/machine_hw_spi.c \ ports/quectel/core/source/modsocket.c \ - ports/quectel/core/source/modnet.c \ ports/quectel/core/source/moddatacall.c \ - ports/quectel/core/build/_frozen_mpy.c \ - ports/quectel/core/source/modutime.c \ ports/quectel/core/source/modmisc.c \ ports/quectel/core/source/misc_power.c \ - ports/quectel/core/source/misc_powerkey.c \ - ports/quectel/core/source/misc_pwm.c \ ports/quectel/core/source/misc_adc.c \ - ports/quectel/core/source/modsim.c \ - ports/quectel/core/source/misc_usb.c \ + ports/quectel/core/source/modsim.c \ + ports/quectel/core/source/modnet.c \ + ports/quectel/core/source/machine_iic.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 \ py/argcheck.c \ py/asmarm.c \ py/asmbase.c \ @@ -174,42 +181,73 @@ $(NAME)_SRCS = \ py/warning.c +ifneq ($(strip $(PLAT)),Qualcomm) +$(NAME)_SRCS += \ + ports/quectel/core/source/machine_rtc.c +endif + +ifeq ($(strip $(PLAT)),Qualcomm) +$(NAME)_SRCS += \ + extmod/vfs_efs.c \ + extmod/vfs_efs_file.c \ + extmod/modussl_mbedtls.c \ + extmod/mb_ussl_error.c +endif + +ifeq ($(strip $(PLAT)),RDA) +$(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 +endif + ifneq ($(strip $(PLAT)),RDA) +ifneq ($(strip $(PLAT)),Qualcomm) $(NAME)_SRCS += \ extmod/modussl_mbedtls.c \ extmod/mb_ussl_error.c \ - ports/quectel/core/source/utf8togbk.c \ ports/quectel/core/source/modsms.c \ ports/quectel/core/source/modvoicecall.c \ - ports/quectel/core/source/machine_extint.c \ - ports/quectel/core/source/machine_hw_spi.c \ - ports/quectel/core/source/machine_iic.c \ ports/quectel/core/source/machine_lcd.c \ - ports/quectel/core/source/machine_uart.c \ ports/quectel/core/source/machine_wdt.c \ - ports/quectel/core/source/modlpm.c \ ports/quectel/core/source/modcelllocator.c \ ports/quectel/core/source/modwifiscan.c \ ports/quectel/core/source/sensor_sn95500.c \ ports/quectel/core/source/modsensor.c \ ports/quectel/core/source/modaudio.c \ ports/quectel/core/source/audio_audio.c \ - ports/quectel/core/source/audio_tts.c \ 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/modfota.c \ ifeq ($(strip $(PLAT)),ASR) $(NAME)_SRCS += \ - ports/quectel/core/source/modsecuredata.c + ports/quectel/core/source/modsecuredata.c \ + 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 +endif endif ifeq ($(strip $(PLAT)),Unisoc) $(NAME)_SRCS += \ - ports/quectel/core/source/modgnss.c \ - ports/quectel/core/source/modble.c + ports/quectel/core/source/modgnss.c +endif + +ifeq ($(CONFIG_TTS), y) +$(NAME)_SRCS += \ + ports/quectel/core/source/audio_tts.c +endif + +ifeq ($(CONFIG_BT), y) +$(NAME)_SRCS += \ + ports/quectel/core/source/modble.c endif ifeq ($(CONFIG_LVGL), y) @@ -260,12 +298,25 @@ $(NAME)_DEFINE = \ MP_ENDIANNESS_LITTLE \ MICROPY_BUILD_DATE=${BUILD_TIMESTAMP} + + +ifneq ($(strip $(PLAT)),Qualcomm) $(NAME)_CFLAGS = \ -Wno-error=unused-parameter \ -Wno-error=format-truncation \ -Wno-error=unused-variable \ -Wno-error=unused-function \ -Wno-error=format= +else +$(NAME)_CFLAGS = -Wno-error=tautological-constant-out-of-range-compare \ + -Wno-error=missing-field-initializers \ + -Wno-error=unused-parameter \ + -Wno-error=unused-variable \ + -Wno-error=unused-function \ + -Wno-error=missing-braces \ + -Wno-error=sometimes-uninitialized +endif + ifeq ($(CONFIG_LVGL), y) $(NAME)_CFLAGS += \ @@ -288,6 +339,7 @@ ifeq ($(CONFIG_CAMERA_DECODE), y) $(NAME)_COMPONENTS += components/ZBar $(NAME)_SRCS += \ ports/quectel/core/source/camera_scandecode.c + endif @@ -317,13 +369,38 @@ ifeq ($(CONFIG_RTMP), y) $(NAME)_COMPONENTS += components/rtmpdump endif +ifeq ($(CONFIG_POC), y) +$(NAME)_CFLAGS += \ + -Wno-error=incompatible-pointer-types \ + -Wno-error=ignored-qualifiers \ + -Wno-error=int-conversion \ + -Wno-error=implicit-function-declaration \ + -Wno-error=discarded-qualifiers \ + -Wno-error=unused-const-variable= + +$(NAME)_COMPONENTS += components/poc +$(NAME)_SRCS += \ + ports/quectel/core/source/modpoc.c +endif + +ifeq ($(CONFIG_QRCODE), y) +$(NAME)_COMPONENTS += components/qrcode +$(NAME)_SRCS += \ + ports/quectel/core/source/modqrcode.c +endif + ifeq ($(CONFIG_QUECTHING), y) +ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR Unisoc)) $(NAME)_SRCS += ports/quectel/core/source/modquecIot.c $(NAME)_INCS += ../../components/quecsdk $(NAME)_COMPONENTS += components/quecsdk endif +endif + +$(NAME)_CFLAGS += -Wno-error=implicit-fallthrough + $(NAME)_PRIVATE_SCRIPT = private.mk $(NAME)_PRIVATE_SCRIPT_TARGETS = construct clean diff --git a/ports/quectel/core/Makefile b/ports/quectel/core/Makefile index 4c8fd17..c1370ef 100644 --- a/ports/quectel/core/Makefile +++ b/ports/quectel/core/Makefile @@ -216,8 +216,6 @@ PY_EXTMOD_O_BASENAME = \ extmod/moduzlib.o \ extmod/moduheapq.o \ extmod/modutimeq.o \ - extmod/moduhashlib.o \ - extmod/moducryptolib.o \ extmod/modubinascii.o \ extmod/virtpin.o \ extmod/machine_mem.o \ @@ -229,6 +227,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/modbluetooth.o \ extmod/modurandom.o \ extmod/moduselect.o \ + extmod/moduasyncio.o \ extmod/moduwebsocket.o \ extmod/modwebrepl.o \ extmod/modframebuf.o \ @@ -242,21 +241,33 @@ PY_EXTMOD_O_BASENAME = \ extmod/vfs_lfs.o \ extmod/utime_mphal.o \ extmod/uos_dupterm.o \ + extmod/moduhashlib.o \ + extmod/moducryptolib.o \ lib/embed/abort_.o \ lib/utils/printf.o \ - lib/utils/sys_stdio_mphal.o + lib/utils/sys_stdio_mphal.o + +ifeq ($(strip $(PLAT)),Qualcomm) +PY_EXTMOD_O_BASENAME += \ + extmod/vfs_efs.o \ + extmod/vfs_efs_file.o \ + extmod/modussl_mbedtls.o +endif ifneq ($(strip $(PLAT)),RDA) +ifneq ($(strip $(PLAT)),Qualcomm) PY_EXTMOD_O_BASENAME += \ extmod/modussl_axtls.o \ extmod/modussl_mbedtls.o endif +endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% SRC_QSTR += $(SRC_MOD) $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) $(PY_EXTMOD_O_BASENAME:.o=.c) +ifneq ($(strip $(PLAT)),Qualcomm) SRC_QSTR += source/quecpython.c \ source/moddev.c \ source/moduos.c \ @@ -269,47 +280,89 @@ SRC_QSTR += source/quecpython.c \ source/machine_pin.c \ source/machine_timer.c \ source/machine_rtc.c \ + source/machine_uart.c \ source/modutime.c \ source/modmisc.c \ source/misc_power.c \ source/misc_powerkey.c \ - source/misc_pwm.c \ source/misc_adc.c \ - source/misc_usb.c \ source/modsocket.c \ + source/modfota.c \ source/modnet.c \ source/moddatacall.c \ source/modsim.c \ - + source/modlpm.c \ + source/machine_extint.c \ + source/machine_hw_spi.c \ + source/machine_iic.c +else +SRC_QSTR += source/quecpython.c \ + source/moduos.c \ + source/modexample.c \ + source/modsha1.c \ + source/modutils.c \ + source/utils_crc32.c \ + source/modostimer.c \ + source/modutime.c \ + source/modmachine.c \ + source/machine_uart.c \ + source/machine_pin.c \ + source/machine_timer.c \ + source/modsocket.c \ + source/modfota.c \ + source/moddatacall.c \ + source/machine_extint.c \ + source/machine_hw_spi.c \ + source/modmisc.c \ + source/misc_power.c \ + source/misc_adc.c \ + source/modsim.c \ + source/modnet.c \ + source/machine_iic.c \ + source/moddev.c \ + source/misc_powerkey.c \ + source/modlpm.c + +endif + ifeq ($(strip $(PLAT)),ASR) -SRC_QSTR += source/modsecuredata.c +SRC_QSTR += source/modsecuredata.c \ + source/misc_usbnet.c \ + source/machine_keypad.c \ + source/modslipif.c \ + source/modethernet.c \ + source/modethernet_dm9051.c +endif + +ifeq ($(strip $(PLAT)),RDA) +SRC_QSTR += source/modnb.c \ + source/nb_oc.c \ + source/nb_aep.c \ + source/nb_onenet.c endif ifneq ($(strip $(PLAT)),RDA) -SRC_QSTR += source/utf8togbk.c \ - source/modsms.c \ - source/machine_extint.c \ - source/machine_hw_spi.c \ - source/machine_iic.c \ - source/machine_uart.c \ +ifneq ($(strip $(PLAT)),Qualcomm) +SRC_QSTR += source/modsms.c \ source/machine_wdt.c \ source/machine_lcd.c \ - source/modlpm.c \ source/modcelllocator.c \ source/modwifiscan.c \ source/modaudio.c \ source/audio_audio.c \ source/audio_record.c \ source/audio_queue.c \ - source/audio_tts.c \ source/sensor_sn95500.c \ source/modsensor.c \ + source/misc_usb.c \ + source/misc_pwm.c \ source/modvoicecall.c #quecthing ifeq ($(CONFIG_QUECTHING), y) -SRC_QSTR += \ - source/modquecIot.c +ifeq ($(strip $(PLAT)),$(filter $(PLAT),ASR Unisoc)) +SRC_QSTR += source/modquecIot.c +endif endif #spinand @@ -318,6 +371,12 @@ SRC_QSTR += \ source/machine_nandflash.c endif +#qrcode +ifeq ($(CONFIG_QRCODE), y) +SRC_QSTR += \ + source/modqrcode.c +endif + #camera ifeq (y,$(CONFIG_CAMERA)) SRC_QSTR += \ @@ -340,25 +399,29 @@ SRC_QSTR += \ endif endif - +endif ifeq ($(strip $(PLAT)),Unisoc) -SRC_QSTR += source/modgnss.c \ - source/modble.c +SRC_QSTR += source/modgnss.c endif -ifeq ($(strip $(PLAT)),ASR) -SRC_QSTR += source/modfota.c -else -ifeq ($(strip $(PLAT)),Unisoc) -SRC_QSTR += source/modfota.c +ifeq ($(CONFIG_BT), y) +SRC_QSTR += source/modble.c endif + +ifeq (y,$(CONFIG_POC)) +SRC_QSTR += \ + source/modpoc.c endif ifeq ($(CONFIG_RTMP), y) SRC_QSTR += source/modrtmp.c endif +ifeq ($(CONFIG_TTS), y) +SRC_QSTR += source/audio_tts.c +endif + $(BUILD)/%.pp: %.c @$(ECHO) "PreProcess $<" $(Q)$(CPP) $(C_FLAGS) -Wp,-C,-dD,-dI -o $@ $< @@ -394,6 +457,26 @@ $(HEADER_BUILD)/moduledefs.h: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER SRC_QSTR += $(HEADER_BUILD)/moduledefs.h +ifeq ($(strip $(PLAT)),Qualcomm) +INC += -I$(COMPILER_PATH)/armv7m-none-eabi/libc/include +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/inc/azure_c_shared_utility +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/c-utility/pal/generic +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/iothub_client/inc/internal +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/serializer/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/azure_api/umqtt/inc/azure_umqtt_c +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/qapi +INC += -I$(ROOT)/system/platform/$(strip $(PLAT))/boards/$(strip $(BOARD))/include/threadx_api +endif + INC += -I. INC += -I$(HEADER_BUILD) INC += -I$(TOP) @@ -450,6 +533,8 @@ else ifeq ($(strip $(PLAT)),ASR) INC += -I$(ROOT)/system/lwip/$(strip $(PLAT)) INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include +else +INC += -I$(ROOT)/system/lwip/$(strip $(PLAT))/include endif endif endif @@ -477,6 +562,9 @@ INC += -I$(ROOT)/components/lvgl/src/lv_misc INC += -I$(ROOT)/components/lvgl/src/lv_objx INC += -I$(ROOT)/components/lvgl/src/lv_themes endif +ifeq (y, $(CONFIG_QRCODE)) +INC += -I$(ROOT)/components/qrcode +endif ifeq (y, $(CONFIG_QUECTHING)) INC += -I$(ROOT)/components/quecsdk/cloud INC += -I$(ROOT)/components/quecsdk/driverLayer @@ -500,6 +588,14 @@ ifeq ($(CONFIG_JPEG), y) INC += -I$(ROOT)/components/jpeg/jpeg-9c INC += -I$(ROOT)/components/jpeg endif +ifeq ($(CONFIG_POC_BND), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/bnd/inc +endif +ifeq ($(CONFIG_POC_SL), y) +INC += -I$(ROOT)/components/poc +INC += -I$(ROOT)/components/poc/sl/inc +endif ifeq (y,$(CONFIG_CAMERA_DECODE)) INC += -I$(ROOT)/components/ZBar/zbar INC += -I$(ROOT)/components/ZBar/include @@ -571,6 +667,8 @@ $(BUILD)/_frozen_mpy.c: $(BUILD)/_boot_RDA.mpy \ $(BUILD)/system.mpy \ $(BUILD)/dataCall.mpy \ $(BUILD)/umqtt.mpy \ + $(BUILD)/sys_bus.mpy \ + $(BUILD)/queue.mpy \ $(BUILD)/log.mpy \ $(HEADER_BUILD)/qstrdefs.generated.h @$(ECHO) "MISC freezing bytecode" @@ -580,9 +678,31 @@ $(BUILD)/_frozen_mpy.c: $(BUILD)/_boot_RDA.mpy \ $(BUILD)/system.mpy \ $(BUILD)/dataCall.mpy \ $(BUILD)/umqtt.mpy \ + $(BUILD)/sys_bus.mpy \ + $(BUILD)/queue.mpy \ $(BUILD)/log.mpy \ > $@ +else +ifeq ($(strip $(PLAT)),Qualcomm) +$(BUILD)/_frozen_mpy.c: $(BUILD)/_boot_Qualcomm.mpy \ + $(BUILD)/system.mpy \ + $(BUILD)/dataCall.mpy \ + $(BUILD)/umqtt.mpy \ + $(BUILD)/log.mpy \ + $(BUILD)/request.mpy \ + $(HEADER_BUILD)/qstrdefs.generated.h + @$(ECHO) "MISC freezing bytecode" + $(Q)$(MPY_TOOL) -f -q \ + $(HEADER_BUILD)/qstrdefs.preprocessed.h \ + $(BUILD)/_boot_Qualcomm.mpy \ + $(BUILD)/system.mpy \ + $(BUILD)/dataCall.mpy \ + $(BUILD)/umqtt.mpy \ + $(BUILD)/log.mpy \ + $(BUILD)/request.mpy \ + > $@ + else $(BUILD)/_frozen_mpy.c: \ $(BUILD)/_boot.mpy \ @@ -611,6 +731,8 @@ $(BUILD)/_frozen_mpy.c: \ $(BUILD)/queue.mpy \ $(BUILD)/sys_bus.mpy \ $(BUILD)/event_message.mpy \ + $(BUILD)/hls.mpy \ + $(BUILD)/bak_util.mpy \ $(HEADER_BUILD)/qstrdefs.generated.h @$(ECHO) "MISC freezing bytecode" $(Q)$(MPY_TOOL) -f -q \ @@ -641,8 +763,10 @@ $(BUILD)/_frozen_mpy.c: \ $(BUILD)/queue.mpy \ $(BUILD)/sys_bus.mpy \ $(BUILD)/event_message.mpy \ + $(BUILD)/hls.mpy \ + $(BUILD)/bak_util.mpy \ > $@ - +endif endif $(BUILD): $(Q)echo creating directory: $@ diff --git a/ports/quectel/core/_boot_Qualcomm.py b/ports/quectel/core/_boot_Qualcomm.py new file mode 100644 index 0000000..2968fed --- /dev/null +++ b/ports/quectel/core/_boot_Qualcomm.py @@ -0,0 +1,117 @@ +# 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 uos +import gc +import ujson +import dataCall +#import backup_restore +#import app_fota +import misc + +''' +Forrest.Liu - 2021/09/11 +Perfect auto mount fs + +''' +global datacall_flag +datacall_flag = 1 + +def _call_by_default_apn(): + dataCall.setAutoConnect(1, 1) + dataCall.recordApn(1, 0, '', '', '', 0, 0) + #dataCall.setAsynMode(1) + ret = -1 + repeat_count = 2 + while (ret == -1) and (repeat_count >= 0): + repeat_count -= 1 + ret = dataCall.start(1, 0, '', '', '', 0) + #dataCall.setAsynMode(0) + + +def _call_by_user_apn(): + with open("/usr/user_apn.json", "r", encoding='utf-8') as fd: + json_data = ujson.load(fd) + + pdp = json_data.get('pdp') + ipv = json_data.get('iptype') + apn = json_data.get('apn') + usr = json_data.get('user') + pwd = json_data.get('password') + ath = json_data.get('authtype') + + dataCall.setAutoConnect(int(pdp), 1) + + dataCall.recordApn(int(pdp), int(ipv), apn, usr, pwd, int(ath), 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) + + +def _auto_data_call(): + _call_by_default_apn() + #try: + #_call_by_user_apn() + #except OSError as e: + #if e.args[0] == 2: + # print('######user_apn.json not found!') + #_call_by_default_apn() + + +def _check_data_call(): + for pdp in range(1, 5): + nw_sta = dataCall.getInfo(pdp, 2) + if (nw_sta != -1) and (nw_sta[2][0] == 0) and (nw_sta[3][0] == 0): + continue + elif (nw_sta != -1) and ((nw_sta[2][0] == 1) or (nw_sta[3][0] == 1)): + return 1 + return 0 + +def _repl_enable(): + global datacall_flag + if "system_config.json" in uos.listdir("usr/"): + with open("/usr/system_config.json", "r", encoding='utf-8') as fd: + json_data = ujson.load(fd) + repl_flag = json_data.get("replFlag", 0) + datacall_flag = json_data.get("datacallFlag",1) + misc.replEnable(repl_flag) + else: + with open("/usr/system_config.json", "w+", encoding='utf-8') as fd: + repl_data = ujson.dumps({"replFlag": 0}) + fd.write(repl_data) + + +try: + bdev = uos.VfsEfs("customer_fs") + udev = uos.VfsEfs("customer_backup_fs") + uos.mount(bdev, '/usr') + uos.mount(udev, '/bak') + print('mount.') + +except Exception: + print('error ocurs in boot step.') + +finally: + #global datacall_flag + #_repl_enable() + if datacall_flag == 1: + ret = _check_data_call() + if ret == 0: + _auto_data_call() + + diff --git a/ports/quectel/core/aLiYun.py b/ports/quectel/core/aLiYun.py index 7852fdc..97e1dce 100644 --- a/ports/quectel/core/aLiYun.py +++ b/ports/quectel/core/aLiYun.py @@ -30,7 +30,7 @@ CLIENT_ID_R = "{}|securemode=2,authType=register,random={},signmethod=hmacsha256 class aLiYun: - def __init__(self, productKey, productSecret=None, DeviceName=None, DeviceSecret=None): + def __init__(self, productKey, productSecret=None, DeviceName=None, DeviceSecret=None, MqttServer=None): self.productKey = productKey self.productSecret = productSecret self.DeviceName = DeviceName @@ -40,6 +40,7 @@ class aLiYun: self.recvCb = None self.mqtt_client = None self.password = None + self.addr = MqttServer self.port = 1883 self.clientID = None @@ -87,6 +88,8 @@ class aLiYun: except: return -1 utime.sleep(2) + self.mqttObj = None + self.mqtt_client = None mqtts_cl.wait_msg() utime.sleep(1) mqtts_cl.disconnect() @@ -94,11 +97,15 @@ class aLiYun: try: self.connect(mqt_id, secret, hmac_msg, keepAlive, clean_session, ssl, reconn=reconn, pingmaxnum=pingmaxnum) return 0 - except: + except Exception as e: + print("[ERROR] connect failed. Error : %s" % str(e)) return -1 def connect(self, mqt_id, secret, hmac_msg, keepAlive, clean_session, ssl, reconn, pingmaxnum): - mqt_server = MQTT_SERVER.format(self.productKey) + if self.addr is None: + mqt_server = MQTT_SERVER.format(self.productKey) + else: + mqt_server = self.addr self.password = hmac.new(bytes(secret, "utf8"), msg=bytes(hmac_msg, "utf8"), digestmod=sha256).hexdigest() self.mqtt_client = MQTTClient(mqt_id, mqt_server, self.port, self.username, self.password, keepAlive, ssl=ssl, reconn=reconn, pingmaxnum=pingmaxnum) diff --git a/ports/quectel/core/app_fota.py b/ports/quectel/core/app_fota.py index 8b43aa0..be8e0ee 100644 --- a/ports/quectel/core/app_fota.py +++ b/ports/quectel/core/app_fota.py @@ -20,9 +20,9 @@ import app_fota_updater class new(object): def download(self, url, file_name): - app_fota_download.download(url, file_name) + return app_fota_download.download(url, file_name) def bulk_download(self, info=[]): - app_fota_download.bulk_download(info) + return app_fota_download.bulk_download(info) def set_update_flag(self): app_fota_download.set_update_flag() def update(self): diff --git a/ports/quectel/core/backup_restore.py b/ports/quectel/core/backup_restore.py index e7c8d7a..b05417b 100644 --- a/ports/quectel/core/backup_restore.py +++ b/ports/quectel/core/backup_restore.py @@ -22,15 +22,18 @@ import file_crc32 import ql_fs backup_root_dir = '/bak' -backup_restore_flag_file = '/bak/backup_restore.json' +backup_restore_flag_file = '/bak/backup_restore.json' backup_restore_flag_file_max_size = 64 + class _checkError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) + def _check(): if not ql_fs.path_exists(backup_restore_flag_file): raise _checkError('%s not exist' % backup_restore_flag_file) @@ -43,11 +46,46 @@ def _check(): raise _checkError('%s is empty' % backup_restore_flag_file) return fr + def _get_backup_restore_flag(): json_str = _check() backup_restore_flag = ujson.loads(json_str) return backup_restore_flag['enable'] + +def bak_update(file, data): + _backup_root_dir = '/_bak' + if not isinstance(data, dict) or ql_fs.path_exists(file): + return -1 + try: + backup_restore_flag = _get_backup_restore_flag() + except Exception as e: + return -2 + if backup_restore_flag: + _fs = uos.VfsLfs1(32, 32, 32, "customer_backup_fs") + uos.mount(_fs, _backup_root_dir) + res = 0 + try: + back_file = _backup_root_dir + file + res = ql_fs.touch(back_file, data) + if not ql_fs.path_exists(file): + res = ql_fs.touch(file, dict()) + ql_fs.file_copy(file, back_file) + code = checksum.bak_update(file_name=back_file) + if code is not None: + checksum.usr_update(file_name=file) + else: + raise Exception("checksum failed") + except Exception as e: + print(e) + uos.remove(file) + res = -5 + uos.umount(_backup_root_dir) + return res + else: + return -3 + + def main(): try: update_file_list = [] @@ -57,7 +95,8 @@ def main(): csum = ujson.loads(json_str) for item in csum: crc32_value = file_crc32.calc(item['name']) - if crc32_value == None or (int(crc32_value, 16) != int(item['crc32'], 16)): # crc32 mismatched, should restore backup file + if crc32_value == None or ( + int(crc32_value, 16) != int(item['crc32'], 16)): # crc32 mismatched, should restore backup file print('- restoring', item['name']) backup_file_name = backup_root_dir + '/' + item['name'] if not ql_fs.path_exists(backup_file_name): diff --git a/ports/quectel/core/bak_util.py b/ports/quectel/core/bak_util.py new file mode 100644 index 0000000..de67c0f --- /dev/null +++ b/ports/quectel/core/bak_util.py @@ -0,0 +1,62 @@ +# 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. + +#!python3 +# -*- coding:utf-8 -*- + + +import uos, ujson, ql_fs + + +class JsonFile(object): + _usr = "usr" + bak = "bak" + _bak = '/_' + bak + _back_config_path = "/_usr_config.json" + _customer_backup_fs = "customer_backup_fs" + + @classmethod + def write(cls, data): + if not isinstance(data, dict): + return -1 + if not ql_fs.path_exists(cls.bak + cls._back_config_path): + _fs = uos.VfsLfs1(32, 32, 32, cls._customer_backup_fs) + uos.mount(_fs, cls._bak) + try: + with open(cls._bak + cls._back_config_path, "w") as f: + f.write(ujson.dumps(data)) + ql_fs.file_copy(cls._usr + cls._back_config_path, cls.bak + cls._back_config_path) + except Exception as e: + return -2 + else: + return 0 + finally: + uos.umount(cls._bak) + else: + return -3 + + @classmethod + def read(cls): + if not ql_fs.path_exists(cls._usr + cls._back_config_path): + if ql_fs.path_exists(cls.bak + cls._back_config_path): + ql_fs.file_copy(cls._usr + cls._back_config_path, cls.bak + cls._back_config_path) + else: + return None + with open(cls._usr + cls._back_config_path, "r") as f: + return ujson.load(f) + + @classmethod + def add(cls, file, data): + from backup_restore import bak_update + return bak_update(file, data) diff --git a/ports/quectel/core/checkNet.py b/ports/quectel/core/checkNet.py index 0d81372..e809b5f 100644 --- a/ports/quectel/core/checkNet.py +++ b/ports/quectel/core/checkNet.py @@ -17,29 +17,22 @@ jayceon 2020/12/31 ''' +import sim +import net +import utime +import modem +import dataCall +from misc import Power + class CheckNetwork(): def __init__(self, proj_name, proj_version): - import sim as csim - import net as cnet - import utime as time - import modem as mod - import dataCall as dc - from misc import Power as pw - - self._sim = csim - self._net = cnet - self._time = time - self._modem = mod - self._dataCall = dc - self._Power = pw - self.PROJECT_NAME = proj_name self.PROJECT_VERSION = proj_version - self.FIRMWARE_VERSION = self._modem.getDevFwVersion() - self.POWERON_REASON = self._Power.powerOnReason() + self.FIRMWARE_VERSION = modem.getDevFwVersion() + self.POWERON_REASON = Power.powerOnReason() def poweron_print_once(self): - sim_sta = self._sim.getStatus() + sim_sta = sim.getStatus() print('==================================================') print('PROJECT_NAME : {}'.format(self.PROJECT_NAME)) print('PROJECT_VERSION : {}'.format(self.PROJECT_VERSION)) @@ -48,9 +41,10 @@ class CheckNetwork(): print('SIM_CARD_STATUS : {}'.format(sim_sta)) print('==================================================') - def check_datacall_status(self): + @staticmethod + def check_datacall_status(): for pdp in range(1, 8): - datacall_sta = self._dataCall.getInfo(pdp, 2) + datacall_sta = dataCall.getInfo(pdp, 2) if (datacall_sta != -1) and ((datacall_sta[2][0] == 1) or (datacall_sta[3][0] == 1)): return 1 elif (datacall_sta != -1) and (datacall_sta[2][0] == 0) and (datacall_sta[3][0] == 0): @@ -75,13 +69,13 @@ class CheckNetwork(): stage_code = 1 while True: - sim_sta = self._sim.getStatus() + sim_sta = sim.getStatus() if sim_sta == 1: break elif sim_sta == 0: return stage_code, sim_sta elif (sim_sta == 18) or (sim_sta == 20) or (sim_sta == 21): - self._time.sleep_ms(100) + utime.sleep_ms(100) timeout_ms -= 100 if timeout_ms <= 0: return stage_code, sim_sta @@ -90,9 +84,9 @@ class CheckNetwork(): stage_code = 2 while True: - net_sta = self._net.getState() + net_sta = net.getState() if net_sta == -1: - self._time.sleep_ms(100) + utime.sleep_ms(100) timeout_ms -= 100 if timeout_ms <= 0: return stage_code, -1 @@ -100,7 +94,7 @@ class CheckNetwork(): if net_sta[1][0] == 1: break else: - self._time.sleep_ms(100) + utime.sleep_ms(100) timeout_ms -= 100 if timeout_ms <= 0: return stage_code, net_sta[1][0] @@ -111,7 +105,56 @@ class CheckNetwork(): if datacall_sta == 1: return stage_code, datacall_sta else: - self._time.sleep_ms(100) + utime.sleep_ms(100) timeout_ms -= 100 if timeout_ms <= 0: return stage_code, datacall_sta + + +def wait_network_connected(timeout_s=60): + if (timeout_s < 1) or (timeout_s > 3600): + raise OSError("timeout_s should be in [1, 3600]s!") + timeout_ms = timeout_s * 1000 + + stage_code = 1 + while True: + sim_sta = sim.getStatus() + if sim_sta == 1: + break + elif sim_sta == 0: + return stage_code, sim_sta + elif (sim_sta == 18) or (sim_sta == 20) or (sim_sta == 21): + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, sim_sta + else: + return stage_code, sim_sta + + stage_code = 2 + while True: + net_sta = net.getState() + if net_sta == -1: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, -1 + else: + if net_sta[1][0] == 1: + break + else: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, net_sta[1][0] + + stage_code = 3 + while True: + datacall_sta = CheckNetwork.check_datacall_status() + if datacall_sta == 1: + return stage_code, datacall_sta + else: + utime.sleep_ms(100) + timeout_ms -= 100 + if timeout_ms <= 0: + return stage_code, datacall_sta \ No newline at end of file diff --git a/ports/quectel/core/checksum.py b/ports/quectel/core/checksum.py index 1b4b6eb..95df203 100644 --- a/ports/quectel/core/checksum.py +++ b/ports/quectel/core/checksum.py @@ -24,12 +24,15 @@ checksum_file = '/usr/checksum.json' checksum_file_max_size = 16384 backup_checksum_file = '/bak/checksum.json' + class _checkError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) + def check(): if not ql_fs.path_exists(checksum_file): if not ql_fs.path_exists(backup_checksum_file): @@ -46,6 +49,7 @@ def check(): raise _checkError('%s is empty' % checksum_file) return fr + def retrieve(file_name): # Pawn 2021-01-14 for JIRA STASR3601-2428 begin if not file_name.startswith("/"): @@ -59,9 +63,10 @@ def retrieve(file_name): return item['crc32'] return None -def _flush_checksum(checksum=[]): + +def _flush_checksum(checksum=[], file_name=checksum_file): json_str = ujson.dumps(checksum) - fp = open(checksum_file, 'wt+') + fp = open(file_name, 'wt+') fp.seek(0) wl = fp.write(json_str) fp.close() @@ -69,16 +74,46 @@ def _flush_checksum(checksum=[]): return checksum return None + +def bak_update(file_name): + # add by Jaxsen xu + checksum = ql_fs.read_json(backup_checksum_file) + + if not file_name.startswith("/"): + file_name = "/" + file_name + + src_file = file_name[file_name.find("/", 1):] + exist_file = False + for item in checksum: + if item['name'].lower() == src_file.lower(): + exist_file = True + file_crc32_value = file_crc32.calc(file_name) + item['crc32'] = file_crc32_value + if not exist_file: + checksum.append(dict(name=src_file, crc32=file_crc32.calc(file_name))) + return _flush_checksum(checksum, file_name=file_name[:file_name.find("/", 1)] + "/checksum.json") + +def usr_update(file_name): + try: + data = ql_fs.read_json(checksum_file) + if data is not None: + data.append(dict(name=file_name, crc32=file_crc32.calc(file_name))) + return ql_fs.touch(checksum_file, data) + return None + except Exception as e: + return None + + def update(file_name): try: json_str = check() checksum = ujson.loads(json_str) - + # Pawn 2021-01-14 for JIRA STASR3601-2428 begin if not file_name.startswith("/"): file_name = "/" + file_name # Pawn 2021-01-14 for JIRA STASR3601-2428 end - + for item in checksum: if item['name'].lower() == file_name.lower(): file_crc32_value = file_crc32.calc(file_name) @@ -89,11 +124,13 @@ def update(file_name): except Exception: return None + def bulk_update(file_name_list=[]): try: json_str = check() checksum = ujson.loads(json_str) need_update = 0 + for file_name in file_name_list: # Pawn 2021-01-14 for JIRA STASR3601-2428 begin if not file_name.startswith("/"): @@ -111,4 +148,3 @@ def bulk_update(file_name_list=[]): return None except Exception: return None - diff --git a/ports/quectel/core/dataCall.py b/ports/quectel/core/dataCall.py index d07226f..237a61f 100644 --- a/ports/quectel/core/dataCall.py +++ b/ports/quectel/core/dataCall.py @@ -74,4 +74,7 @@ def setCallback(usrfun): def setAutoConnect(profileidx, enable): - return dial.setAutoConnect(profileidx, enable) \ No newline at end of file + return dial.setAutoConnect(profileidx, enable) + +def getApn(simid): + return dial.getApn(simid) \ No newline at end of file diff --git a/ports/quectel/core/gnss.py b/ports/quectel/core/gnss.py index 0e567a0..cdc812a 100644 --- a/ports/quectel/core/gnss.py +++ b/ports/quectel/core/gnss.py @@ -59,10 +59,10 @@ class GnssGetData: #获取GPS模块定位的经纬度信息 def getLocation(self): if self.isFix() is 1: - lat=float(self.r.group(0).split(",")[2])/100 #纬度 - lat_d=self.r.group(0).split(",")[3] #纬度方向,N = 北 S = 南 - log=float(self.r.group(0).split(",")[4])/100 #经度 - log_d=self.r.group(0).split(",")[5] #经度方向,E = 东,W = 西 + 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 diff --git a/ports/quectel/core/hls.py b/ports/quectel/core/hls.py new file mode 100644 index 0000000..5b08a24 --- /dev/null +++ b/ports/quectel/core/hls.py @@ -0,0 +1,434 @@ +# coding: utf-8 +import request +import audio +import utime +import _thread +import checkNet +from machine import UART + +rtmp_support = 10 + +try: + from librtmp import RTMP + rtmp_support = 10 + print('RTMP Decoder import success.') +except: + rtmp_support = 0 + print('HLS without RTMP Decoder.') + +import net +import dataCall + +PROJECT_NAME = "QuecPython_RTMP_example" +PROJECT_VERSION = "1.0.0" +checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) + +aud = audio.Audio(0) +aud.setVolume(2) +lock = _thread.allocate_lock() + + +def is_print(*args, **kwagrs): + print(*args, **kwagrs) + + +class hls_audio(): + # 音频格式,简单的后缀判断 + def parse_format(self): + af = { + 'pcm': {'sizeof': 10*1024, 'format': 1}, # 单通道,8000 + 'wav': {'sizeof': 20*1024, 'format': 2}, + 'mp3': {'sizeof': 15*1024, 'format': 3}, + 'amr': {'sizeof': 5*960, 'format': 4}, + 'aac': {'sizeof': 10*1024, 'format': 6}, + 'm4a': {'sizeof': 10*1024, 'format': 7}, + 'ts': {'sizeof': 188*1, 'format': 8}, + 'flv': {'sizeof': 100*1024, 'format': 9}, + 'rtmp': {'sizeof': 150*1024, 'format': rtmp_support}, + + 'm3u8': {'sizeof': 188*1, 'format': 20}, + } + # sizeof: 单次切片的大小;format:固件包接口不同格式的定义 + f = self.url.split('?')[0].split('.')[-1] + if f not in af.keys(): + f = self.url.split(':')[0] + if f not in af.keys(): + raise Exception('unsupported audio format.{}'.format(f)) + return af[f] + + # 播放函数 + def play_run(self, timeout = 30): + #num = 0; + stagecode, subcode = checknet.wait_network_connected(30) + print('stagecode = {}, subcode = {}'.format(stagecode, subcode)) + if stagecode != 3 and subcode != 1: + print('Network is not ready please retry later') + p = self.params + # 请求获取资源 + + if p['format'] != 10: + try: + lock.acquire() # 获取锁 + r = request.get(self.url, headers=self.headers, timeout = timeout) + lock.release() # 释放锁 + is_print('request code ==', r.status_code) + except: + print('request data failed.') + return + elif p['format'] == 10: + rtmp = RTMP(self.url) + ret = rtmp.connect() + if ret == 0: + print('rtmp connect successful.') + else: + print('rtmp connect failed.') + return -1 + ret = rtmp.connectStream() + if ret == 0: + print('rtmp connect stream successful.') + else: + print('rtmp connect stream failed.') + return -1 + + + # 播放文件头 + if p['format'] == 4 and not self.headers: # amr + head_content = r.raw.read(p['sizeof']) + p['format'] = self.parse_amr_head(head_content, p['format']) + # 循环播放文件内容 + + #如果是m3a8则进行处理 整合成一个TS 再调用TS播放 + if p['format'] == 20: # m3a8 + https_state = 0; #0:http 1:https + tsurl = "" + last_sequence = 0 + sequence = 0 + distance = 0 + num_of_ts = 0 + skip_num = 0 + self.m3u8_url_list = [] + len_cauced = 0 + ts = bytearray() + if self.url.find("https:") != -1: + https_state = 1; + else: + https_state = 0; + done = 0 + self.is_runing = True + while True: + if self.is_close: + is_print('is_close == ', self.is_close) + temp.close() + self.is_runing = False + r.close() # + self.close() + self.m3u8_url_list = [] + sequence = 0 + distance = 0 + num_of_ts = 0 + skip_num = 0 + is_print('CLOSE Successful') + return + + try: + lock.acquire() # 获取锁 + rc = request.get(self.url, timeout = 200) + lock.release() # 释放锁 + is_print('get m3u8 file request code ==', rc.status_code) + except: + rc.close() + is_print('get m3a8 file failed later retry') + continue + while True: # 获取m3u8文件 + try: + ret = rc.raw.readline() + tsurl = ret.decode() + if tsurl.find("EXT-X-TARGETDURATION") != -1: + num_of_ts = tsurl.split(':')[-1] + num_of_ts = int(num_of_ts) + + if tsurl.find("EXT-X-MEDIA-SEQUENCE") != -1: + last_sequence = sequence + sequence = tsurl.split(':')[-1] + sequence = int(sequence) + last_sequence = int(last_sequence) + + if((sequence - last_sequence) <= num_of_ts) and len_cauced == 0 : + skip_num = num_of_ts - (sequence - last_sequence) + is_print("now:",sequence) + is_print("last_sequence:",last_sequence) + is_print("skip:",skip_num) + if len_cauced == 1 and num_of_ts == skip_num: + rc.close() + len_cauced = 0 + is_print('finish loading m3u8 file') + break; + len_cauced = 1 + + if tsurl.find("//") != -1: + if tsurl.find("http") == -1: + if https_state == 0: + tsurl = "http:" + tsurl + #is_print("http url found") + elif https_state == 1: + tsurl = "https:" + tsurl + is_print("https url found") + else: + is_print('URL unknow error') + return + else: + tsurl = tsurl + tsurl = tsurl.replace("\r", "") + tsurl = tsurl.replace("\n", "") + tsurl = tsurl.replace(" ", "") + + #num_of_ts - (sequence - last_sequence) + if(skip_num != 0): + skip_num = skip_num - 1 + #is_print("already have this url skip:",skip_num) + if (skip_num == 0): + if(tsurl not in self.m3u8_url_list): + #is_print(tsurl) + self.m3u8_url_list.append(tsurl) + is_print("add:",tsurl) + else: + if(tsurl not in self.m3u8_url_list): + #is_print(tsurl) + self.m3u8_url_list.append(tsurl) + is_print("add:",tsurl) + except: + rc.close() + len_cauced = 0 + is_print('finish loading m3u8 file') + break; + + try: + is_print('list remain:',len(self.m3u8_url_list)) + if len(self.m3u8_url_list) == 0 : + + is_print('run out of list now get new list') + utime.sleep_ms(3000) + continue + is_print('begin to request TS file url:',self.m3u8_url_list[0]) + try: + lock.acquire() # 获取锁 + temp = request.get(self.m3u8_url_list[0], timeout = 3000) + lock.release() # 释放锁 + except: + temp.close() + is_print('get file failed skip frame now') + #del(self.m3u8_url_list[0]) + utime.sleep_ms(2000) + continue + is_print('request code ==', temp.status_code) + if temp.status_code == 200: + while True: + # if self.is_close: + # is_print('is_close == ', self.is_close) + # r.close() + # temp.close() + # self.is_runing = False + # return + # if self.is_close: + # is_print('is_close == ', self.is_close) + # r.close() + # self.is_runing = False + # return + try: # 读取可能会有报错,直接break + i = temp.raw.read(188) + if not i: + break + except Exception as e: + is_print('read error:{}'.format(e)) + break + ret = aud.playStream(8, i) + #temp.close() + del(self.m3u8_url_list[0]) + temp.close() + else: + is_print('request error code ==',temp.status_code) + break + + except : + is_print('is_close == ', self.is_close) + temp.close() + self.is_runing = False + r.close() # + utime.sleep_ms(1000) + self.close() + self.m3u8_url_list = [] + sequence = 0 + distance = 0 + num_of_ts = 0 + skip_num = 0 + is_print('CLOSE SUCCESSFUL') + return + + is_print('play done----------') + r.close() + temp.close() + return + + self.is_runing = True + while True: + if self.is_close: + is_print('is_close == ', self.is_close) + if p['format'] == 10: + rtmp.close() + else: + r.close() + self.is_runing = False + return + # if self.is_pause: + # utime.sleep_ms(50) + # continue + try: # 读取可能会有报错,直接break + if p['format'] == 10: + i = rtmp.read(p['sizeof']) + else: + i = r.raw.read(p['sizeof']) + if not i: + break + except Exception as e: + is_print('read error:{}'.format(e)) + break + ret = aud.playStream(p['format'], i) + #num = num +1 + #is_print('buff num:{}'.format(num)) + #is_print('play code == ', ret) + self.is_runing = False + if p['format'] == 10: + rtmp.close() + else: + r.close() + utime.sleep_ms(1000) + self.close() + is_print('CLOSE SUCCESSFUL') + is_print('play done----------') + + + # amr + def parse_amr_head(self, head_content, format): + # if head_content[:5] != b'#!AMR': + # # amr + # pass + # elif head_content[:4] != b'RIFF' and head_content[8:15] == b'WAVEfmt': + # # wav + # pass + # elif head_content[:3] == b'ID3': + # # mp3 的文件格式可能不统一,不一定是在文件头进行标记; + # # ID3V2 在文件头以 ID3 开头; + # # ID3V1 在文件尾以 TAG 开头。 + # pass + + single_amr_nb = '2321414d520a' + single_amr_wb = '2321414d522d57420a' + mult_amr_nb = '2321414d525f4d43312e300a' + mult_amr_wb = '2321414d522d57425f4d43312e300a' + + head_hexs = [] + for i in head_content[:16]: + char = hex(i).replace('0x', '') + if len(char) <= 1: + char = '0{}'.format(char) + head_hexs.append(char.lower()) + # 单声道还是多声道 + if ''.join(head_hexs[:6]) == single_amr_nb: + format = 4 # 单声道 AMR-NB + elif ''.join(head_hexs[:9]) == single_amr_wb: + format = 5 # 单声道 AMR-WB + elif ''.join(head_hexs[:12]) == mult_amr_nb: + format = 4 # 多声道 AMR-NB + elif ''.join(head_hexs[:15]) == mult_amr_wb: + format = 5 # 多声道 AMR-WB + # 播放头 + aud.playStream(format, head_content) + return format + + + # 播放前将所有参数初始化 + def play_init(self, url, range=None): + # self.is_pause = False + self.is_close = False + self.url = url + self.params = self.parse_format() + self.headers = {} + if range: # 断点续传 + self.headers['Range'] = 'bytes={}-'.format(range) + is_print(self.params) + is_print(self.headers) + + # play + def play(self, url): + while True: + net_sta = net.getState() + if net_sta != -1 and net_sta[1][0] == 1: + is_print("Net State OK") + break + else: + utime.sleep(3) + is_print(".") + continue + while True: + call_state = dataCall.getInfo(1,0) + if call_state != -1 and call_state[2][0] == 1: + is_print("Data State OK") + break + else: + utime.sleep(3) + is_print(".") + continue + + is_print(url) + self.play_init(url) + _thread.start_new_thread(self.play_run, ()) + + # pause + def pause(self, f): + if f == 1: + aud.StreamPause() + is_print('stream play pause') + else: + aud.StreamContinue() + is_print('stream play continue') + + # close + def close(self): + self.url = None + self.is_close = True + while True: + if not self.is_runing: + break + aud.stopPlayStream() + is_print('stream play close') + + + # 快进,快退 + def seek_secs(self, secs): + is_print('stream play will seek to {}s'.format(secs)) + if not self.url: + raise Exception("You can't fast forward or rewind without playing audio") + self.is_close = True + while True: + if not self.is_runing: + break + print('seek start') + seek = aud.StreamSeek(secs) + is_print('stream seek byte is {}s'.format(seek)) + utime.sleep(1) + url = self.url + + self.play_init(url, range=seek) + _thread.start_new_thread(self.play_run, ()) + + def set_volume(self,volume): + aud.setVolume(volume) + + + +if __name__ == '__main__': + # from usr.hls_point import hls_audio + hls = hls_audio() + hls.play('http://111.229.132.74/httptest/user/James/down.pcm') + + diff --git a/ports/quectel/core/modbus_utils.py b/ports/quectel/core/modbus_utils.py deleted file mode 100644 index 86ab112..0000000 --- a/ports/quectel/core/modbus_utils.py +++ /dev/null @@ -1,63 +0,0 @@ -from machine import UART -import ubinascii as binascii -import utime as time - - -class ModbusUtils: - - def __init__(self, uartN, baudrate, databits, parity, stopbit, flowctl): - self.uart = UART(uartN, baudrate, databits, parity, stopbit, flowctl) - - @staticmethod - def divmod_low_high(addr): - high, low = divmod(addr, 0x100) - return high, low - - def calc_crc(self, string_byte): - crc = 0xFFFF - for pos in string_byte: - crc ^= pos - for i in range(8): - if ((crc & 1) != 0): - crc >>= 1 - crc ^= 0xA001 - else: - crc >>= 1 - gen_crc = hex(((crc & 0xff) << 8) + (crc >> 8)) - int_crc = int(gen_crc, 16) - return self.divmod_low_high(int_crc) - - def split_return_bytes(self, ret_bytes): - ret_str = binascii.hexlify(ret_bytes, ',') - return ret_str.split(b",") - - def read_uart(self): - num = self.uart.any() - msg = self.uart.read(num) - ret_str = binascii.hexlify(msg, ',') - return ret_str - - def write_coils(self, slave, const, start, coil_qty, crc_flag=True): - start_h, start_l = self.divmod_low_high(start) - coil_qty_h, coil_qty_l = self.divmod_low_high(coil_qty) - data = bytearray([slave, const, start_h, start_l, coil_qty_h, coil_qty_l]) - print(data) - if crc_flag: - crc = self.calc_crc(data) - for num in crc: - data.append(num) - self.uart.write(data) - time.sleep_ms(1000) - return True - - def write_coils_any(self, *args, crc_flag=True): - data = bytearray(args) - print(data) - if crc_flag: - crc = self.calc_crc(data) - for num in crc: - data.append(num) - self.uart.write(data) - time.sleep_ms(1000) - return True - diff --git a/ports/quectel/core/ql_fs.py b/ports/quectel/core/ql_fs.py index 668b7dd..73d045c 100644 --- a/ports/quectel/core/ql_fs.py +++ b/ports/quectel/core/ql_fs.py @@ -16,13 +16,17 @@ # -*- coding:utf-8 -*- import uos +import ujson + class FileNotFoundError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) + def path_exists(path): if not path: return False @@ -35,10 +39,11 @@ def path_exists(path): except Exception as e: return False + def file_copy(dstFile, srcFile): if not path_exists(srcFile): return False - + dstFp = open(dstFile, 'wb+') srcFp = open(srcFile, 'rb') srcFr = srcFp.read(4096) @@ -49,16 +54,17 @@ def file_copy(dstFile, srcFile): srcFp.close() return True + def path_dirname(path): if not path: return '' - + pos = path.rfind('/') if pos < 0: return '' if pos == 0: return '/' - + dirname = '' for i in range(0, len(path)): if i == pos: @@ -66,12 +72,14 @@ def path_dirname(path): dirname = dirname + path[i] return dirname + def path_getsize(path): if path_exists(path): return uos.stat(path)[-4] else: raise FileNotFoundError("can not find: '%s'" % path) + def mkdirs(dir): dir_level_list = dir.split('/') dir_step_up = dir_level_list[0] @@ -82,6 +90,7 @@ def mkdirs(dir): break dir_step_up = dir_step_up + '/' + dir_level_list[index[0] + 1] + def rmdirs(dir): ls = uos.listdir(dir) if not ls: @@ -93,3 +102,29 @@ def rmdirs(dir): rmdirs(dir) +def touch(file, data, i=1, file_type="json"): + i = file.find("/", i) + if i != -1: + if not path_exists(file[:i]): + uos.mkdir(file[:i]) + return touch(file, data, i=i + 1, file_type=file_type) + else: + try: + with open(file, "w") as f: + if file_type == "json": + f.write(ujson.dumps(data)) + else: + f.write(data) + except Exception as e: + return -1 + else: + return 0 + + +def read_json(file): + if path_exists(file): + with open(file, "r") as f: + return ujson.load(f) + else: + return None + diff --git a/ports/quectel/core/request.py b/ports/quectel/core/request.py index a4b5e96..256c455 100644 --- a/ports/quectel/core/request.py +++ b/ports/quectel/core/request.py @@ -1,11 +1,11 @@ # 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. @@ -15,7 +15,7 @@ import usocket import ujson import ussl - +import utime class Response: def __init__(self, f, decode=True, sizeof=4096): @@ -81,8 +81,8 @@ class Response: "The data for the response cannot be converted to JSON-type data,please try use response.content method") -def request(method, url, data=None, json=None, stream=None, decode=True, sizeof=255, timeout=None, headers={}, - ssl_params={}): +def request(method, url, data=None, json=None, files=None, stream=None, decode=True, sizeof=255, timeout=None, headers=None, + ssl_params=None): global port global s_isopen s_isopen = True @@ -122,7 +122,6 @@ def request(method, url, data=None, json=None, stream=None, decode=True, sizeof= elif url.split(".")[0].isdigit() and ":" not in url: raise ValueError( "MissingSchema: Invalid URL '{}': No schema supplied. Perhaps you meant http://{}? ".format(url, url)) - else: path = "" proto = "" @@ -154,19 +153,32 @@ def request(method, url, data=None, json=None, stream=None, decode=True, sizeof= raise RuntimeError( "HTTPConnectionPool(host='{}', port=8080): Max retries exceeded with url: / (Caused by NewConnectionError Failed to establish a new connection: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。'))".format( URL)) - if proto == "https:": try: - if len(ssl_params): + if ssl_params: s = ussl.wrap_socket(s, **ssl_params) else: s = ussl.wrap_socket(s, server_hostname=host) except Exception as e: pass - s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - if not "Host" in headers: - s.write(b"Host: %s\r\n" % host) + s.write(b"Host: %s\r\n" % host) + if headers: + if files: + boundary = str(utime.time()) + if not (files.get("filepath") and files.get("filepath")): + 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) + headers['charset'] = 'UTF-8' + else: + headers = dict() + if files: + boundary = str(utime.time()) + headers['Content-Type'] = "multipart/form-data; boundary={}".format(boundary) + headers['charset'] = 'UTF-8' + if json: + headers['Content-Type'] = "application/json" for k in headers: s.write(k) s.write(b": ") @@ -175,12 +187,24 @@ def request(method, url, data=None, json=None, stream=None, decode=True, sizeof= if json is not None: assert data is None data = ujson.dumps(json) - s.write(b"Content-Type: application/json\r\n") if data: s.write(b"Content-Length: %d\r\n" % len(data)) - s.write(b"\r\n") - if data: + s.write(b"\r\n") s.write(data) + if files: + 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}'. \ + 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}'. \ + format(boundary, '\r\n', files.get("filename"), content) + s.write(b"Content-Length: %d\r\n" % len(datas)) + s.write(b"\r\n") + s.write(datas) + if not (files and data): + s.write(b"\r\n") l = s.readline() global uheaders uheaders = {} @@ -202,16 +226,11 @@ def request(method, url, data=None, json=None, stream=None, decode=True, sizeof= pass if not l or l == b"\r\n": break - # 2021-01-23 jian.yao - # if l.startswith(b"Transfer-Encoding:"): - # if b"chunked" in l: - # raise ValueError("Unsupported " + l.decode()) if l.startswith(b"Location:") and not 200 <= status <= 299: raise NotImplementedError("Redirects not yet supported") except OSError: s.close() raise - resp = Response(s, decode=decode, sizeof=sizeof) resp.status_code = status resp.reason = reason diff --git a/ports/quectel/core/source/audio_audio.c b/ports/quectel/core/source/audio_audio.c index 3b6a3b1..66cf662 100644 --- a/ports/quectel/core/source/audio_audio.c +++ b/ports/quectel/core/source/audio_audio.c @@ -18,6 +18,7 @@ #include "audio_queue.h" #include "helios_audio.h" #include "helios_debug.h" +#include "helios_gpio.h" typedef struct _audio_obj_t { mp_obj_base_t base; @@ -29,10 +30,89 @@ typedef struct _audio_obj_t { extern const mp_obj_type_t audio_audio_type; -static mp_obj_t g_audio_callback; +static c_callback_t *g_audio_callback; +static c_callback_t *g_audio_speakerpa_callback; +static int g_gpio_pa = -1; +STATIC void delay_us(unsigned int us) +{ + int cnt = 26; + volatile int i = 0; + while(us--){ + i = cnt; + while(i--); + } +} + +STATIC void set_clk_high(void) +{ + Helios_GPIO_SetLevel(g_gpio_pa, HELIOS_LVL_HIGH); +} + +STATIC void set_clk_low(void) +{ + Helios_GPIO_SetLevel(g_gpio_pa, HELIOS_LVL_LOW); +} + +STATIC void audio_open_power_amplifier(void) +{ + // 拉高 -> 低 -> 高 + set_clk_high(); + delay_us(3); + set_clk_low(); + delay_us(3); + set_clk_high(); +} + +static void user_audio_speakerpa_callback(unsigned int event) +{ + if(g_gpio_pa != -1) + { + if (event == 1) + { + //打开PA + audio_open_power_amplifier(); + HELIOS_AUDIO_LOG("audio set high, event 1.\r\n"); + } else { + //关闭PA + set_clk_low(); + HELIOS_AUDIO_LOG("audio set low, event 0.\r\n"); + } + } + if (g_audio_speakerpa_callback) + { + mp_sched_schedule_ex(g_audio_speakerpa_callback, mp_obj_new_int(event)); + } +} + +#if defined (PLAT_ASR) || defined(PLAT_Unisoc) +STATIC mp_obj_t helios_set_pa(mp_obj_t self_in, mp_obj_t gpio) +{ + int ret = 0; + int gpio_num = mp_obj_get_int(gpio); + g_gpio_pa = gpio_num; + + ret = Helios_Audio_SetPa(gpio_num); + if (ret != 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(helios_set_pa_obj, helios_set_pa); +STATIC mp_obj_t helios_set_speakerpa_callback(mp_obj_t self_in, mp_obj_t callback) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_audio_speakerpa_callback = &cb; + mp_sched_schedule_callback_register(g_audio_speakerpa_callback, callback); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(helios_set_speakerpa_callback_obj, helios_set_speakerpa_callback); +#endif + /*=============================================================================*/ /* FUNCTION: helios_set_audio_callback */ /*=============================================================================*/ @@ -44,7 +124,11 @@ static mp_obj_t g_audio_callback; /*=============================================================================*/ STATIC mp_obj_t helios_set_audio_callback(mp_obj_t self_in, mp_obj_t callback) { - g_audio_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_audio_callback = &cb; + mp_sched_schedule_callback_register(g_audio_callback, callback); + return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(helios_set_audio_callback_obj, helios_set_audio_callback); @@ -83,7 +167,7 @@ int audio_play_callback(char *ptr, size_t lens, Helios_EnumAudPlayerState state) if ((g_audio_callback != NULL) && (audio_state != AUDIO_IDLE)) { HELIOS_AUDIO_LOG("[Audio] callback start.\r\n"); - mp_sched_schedule(g_audio_callback, mp_obj_new_int(audio_event)); + mp_sched_schedule_ex(g_audio_callback, mp_obj_new_int(audio_event)); HELIOS_AUDIO_LOG("[Audio] callback end.\r\n"); } @@ -131,12 +215,15 @@ STATIC mp_obj_t audio_make_new(const mp_obj_type_t *type, size_t n_args, size_t mp_raise_ValueError("invalid device index, the value of device should be in[0,2]"); } - audio_obj_t *self = m_new_obj(audio_obj_t); + audio_obj_t *self = m_new_obj_with_finaliser(audio_obj_t); self->base.type = &audio_audio_type; self->device = device; //self->inited = 0; Helios_Audio_Init(); + #if defined(PLAT_ASR) || defined(PLAT_Unisoc) + Helios_Audio_SetPaCallback((Helios_AudOutputType)device, user_audio_speakerpa_callback); + #endif if(device == HELIOS_OUTPUT_RECEIVER||device == HELIOS_OUTPUT_SPEAKER||device == HELIOS_OUTPUT_HEADPHONE){ Helios_Audio_SetAudioChannle(device); @@ -514,7 +601,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_get_audio_state_obj, helios_get_audio_st STATIC mp_obj_t helios_set_volume(mp_obj_t self_in, mp_obj_t volume) { int vol = mp_obj_get_int(volume); - if (vol < 1 || vol > 11) + if (vol < 0 || vol > 11) { mp_raise_ValueError("invalid value,TTS volume should be array between [0,11]"); return mp_obj_new_int(-1); @@ -607,7 +694,32 @@ 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 + +STATIC mp_obj_t helios_audio___del__(mp_obj_t self_in) +{ + uint8_t i = 0; + Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); + for (i=0; iisbusy = 0; + record_state = 0; +} STATIC const mp_arg_t stream_allowed_args[] = { { MP_QSTR_format, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = FORMAT_AMR} }, @@ -273,18 +277,22 @@ 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 || time < 1 || !(samplerate == 8000 || samplerate == 16000)) { + if(format > HELIOS_AUDIO_FORMAT_MAX || !(samplerate == 8000 || samplerate == 16000)) { mp_raise_ValueError("Parameter error\n"); return mp_obj_new_int(-1); } - - Helios_OSTimerAttr OSTimerAttr = { - .ms = (uint32_t)time*1000, - .cycle_enable = 0, - .cb = helios_record_timer_cb, - .argv = (void *)self - }; - ret = Helios_OSTimer_Start(self->rec_timer, &OSTimerAttr); + + if(0 != time) + { + Helios_OSTimerAttr OSTimerAttr = { + .ms = (uint32_t)time*1000, + .cycle_enable = 0, + .cb = helios_record_stream_timer_cb, + .argv = (void *)self + }; + ret = Helios_OSTimer_Start(self->rec_timer, &OSTimerAttr); + } + if(ret) { audio_record_printf("Timer starte failed\r\n"); @@ -376,6 +384,20 @@ STATIC mp_obj_t helios_audio_record_stream_read(mp_obj_t self_in,mp_obj_t read_b STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_helios_record_stream_read_obj, helios_audio_record_stream_read); +STATIC mp_obj_t helios_audio_record_stream_stop(mp_obj_t self_in) +{ + int ret = 0; + audio_record_obj_t *self = MP_OBJ_TO_PTR(self_in); + ret = Helios_Audio_StreamRecordStop(); + self->isbusy = 0; + record_state = 0; + + if(self->rec_timer!= 0) + ret = Helios_OSTimer_Stop(self->rec_timer); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_record_stream_stop_obj, helios_audio_record_stream_stop); STATIC mp_obj_t helios_audio_record_start(mp_obj_t self_in, mp_obj_t path, mp_obj_t time_out) { @@ -505,6 +527,9 @@ STATIC mp_obj_t helios_audio_record_getFilePath(mp_obj_t self_in,mp_obj_t path) char name[256] = {0}; char *file_name = (char*)mp_obj_str_get_str(path); + if(file_name == NULL||strlen(file_name) == 0) + return mp_obj_new_int(-2); + sprintf(name, "U:/%s",file_name); audio_record_printf("name = %s\n",name); @@ -613,6 +638,9 @@ STATIC mp_obj_t helios_audio_record_getSize(mp_obj_t self_in,mp_obj_t path) char name[256] = {0}; char *file_name = (char*)mp_obj_str_get_str(path); + if(file_name == NULL||strlen(file_name) == 0) + return mp_obj_new_int(-4); + sprintf(name, "U:/%s",file_name); audio_record_printf("name = %s\n",name); @@ -668,6 +696,9 @@ STATIC mp_obj_t helios_audio_record_exists(mp_obj_t self_in,mp_obj_t path) char name[256] = {0}; char *file_name = (char*)mp_obj_str_get_str(path); + if(file_name == NULL||strlen(file_name) == 0) + return mp_obj_new_int(-1); + sprintf(name, "U:/%s",file_name); audio_record_printf("name = %s\n",name); @@ -697,15 +728,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_helios_record_file_isBusy_obj, helios_audio_ STATIC mp_obj_t helios_set_record_callback(mp_obj_t self_in, mp_obj_t callback) { audio_record_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->callback = callback; - g_record_callback = callback; + + 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, callback); + self->callback = g_record_callback; return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_helios_record_file_end_callback_obj, helios_set_record_callback); - +#ifdef PLAT_ASR STATIC mp_obj_t helios_audio_record_gain(size_t n_args, const mp_obj_t *args) { //audio_record_obj_t *self = MP_OBJ_TO_PTR(args[0]); @@ -720,18 +755,13 @@ STATIC mp_obj_t helios_audio_record_gain(size_t n_args, const mp_obj_t *args) mp_raise_ValueError("invalid dsp_gain value, must be in [-36,12]"); } - audio_record_printf("codec_gain = %d\n",codec_gain); - //qpy_set_txcodecgain(codec_gain); //gain:0~4 + audio_record_printf("codec_gain = %d, dsp_gain = %d\n",codec_gain, dsp_gain); + Helios_Audio_GainSet(codec_gain, dsp_gain); - audio_record_printf("dsp_gain = %d\n",dsp_gain); - //qpy_set_txdspgain(dsp_gain); //gain: -36~12 - - 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); +#endif static int play_callback(char *p_data, int len, Helios_EnumAudPlayerState state) { @@ -795,8 +825,12 @@ STATIC mp_obj_t helios_audio_deinit(mp_obj_t self_in) if(self->rec_timer) { Helios_OSTimer_Delete(self->rec_timer); } - + + g_record_callback = NULL; + callback_cur = NULL; + record_state = 0; ret = Helios_Audio_FileRecordStop(); + ret = Helios_Audio_StreamRecordStop(); return mp_obj_new_int(ret); } @@ -808,6 +842,7 @@ STATIC const mp_rom_map_elem_t audio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mp_helios_record_file_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stream_start), MP_ROM_PTR(&mp_helios_record_stream_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stream_read), MP_ROM_PTR(&mp_helios_record_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_stream_stop), MP_ROM_PTR(&mp_helios_record_stream_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mp_helios_record_file_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_getFilePath), MP_ROM_PTR(&mp_helios_record_file_getFilePath_obj) }, { MP_ROM_QSTR(MP_QSTR_getData), MP_ROM_PTR(&mp_helios_record_file_getData_obj) }, @@ -816,7 +851,12 @@ STATIC const mp_rom_map_elem_t audio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_exists), MP_ROM_PTR(&mp_helios_record_file_exists_obj) }, { MP_ROM_QSTR(MP_QSTR_isBusy), MP_ROM_PTR(&mp_helios_record_file_isBusy_obj) }, { MP_ROM_QSTR(MP_QSTR_end_callback), MP_ROM_PTR(&mp_helios_record_file_end_callback_obj) }, +#ifdef PLAT_ASR { MP_ROM_QSTR(MP_QSTR_gain), MP_ROM_PTR(&mp_helios_record_file_gain_obj) }, + { 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) }, +#endif { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&mp_helios_record_file_play_obj) }, #ifdef PLAT_Unisoc { MP_ROM_QSTR(MP_QSTR_PCM), MP_ROM_INT(HELIOS_AUDIO_FORMAT_PCM) }, diff --git a/ports/quectel/core/source/audio_tts.c b/ports/quectel/core/source/audio_tts.c index 7e77ac0..1041813 100644 --- a/ports/quectel/core/source/audio_tts.c +++ b/ports/quectel/core/source/audio_tts.c @@ -17,12 +17,20 @@ #include #include #include "runtime.h" -#include "utf8togbk.h" #include "audio_queue.h" #include "helios_audio.h" #include "helios_debug.h" #include "objstr.h" +#define MAX_TTS_TEXT_LEN (500) + +enum { + TTS_MOD_UCS2_BE=1, + TTS_MOD_GBK, + TTS_MOD_UCS2_LE, + TTS_MOD_UTF8, +}; + const mp_obj_type_t audio_tts_type; typedef struct _audio_tts_obj_t { @@ -31,10 +39,10 @@ typedef struct _audio_tts_obj_t { int tts_speed; } audio_tts_obj_t; -static mp_obj_t g_tts_callback; +static c_callback_t *g_tts_callback; +static audio_tts_obj_t *tts_obj = NULL; - -#define HELIOS_TTS_LOG(fmt, ...) custom_log(audio_audio, fmt, ##__VA_ARGS__) +#define HELIOS_TTS_LOG(fmt, ...) custom_log(audio_TTS, fmt, ##__VA_ARGS__) /*=============================================================================*/ /* FUNCTION: helios_set_tts_callback */ @@ -47,7 +55,11 @@ static mp_obj_t g_tts_callback; /*=============================================================================*/ STATIC mp_obj_t helios_set_tts_callback(mp_obj_t self_in, mp_obj_t callback) { - g_tts_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_tts_callback = &cb; + mp_sched_schedule_callback_register(g_tts_callback, callback); + return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(helios_set_tts_callback_obj, helios_set_tts_callback); @@ -60,7 +72,7 @@ static void user_tts_callback(Helios_TTSENvent event) if (g_tts_callback) { //uart_printf("[TTS] callback start.\r\n"); - mp_sched_schedule(g_tts_callback, mp_obj_new_int(event)); + mp_sched_schedule_ex(g_tts_callback, mp_obj_new_int(event)); //uart_printf("[TTS] callback end.\r\n"); } } @@ -127,10 +139,15 @@ STATIC mp_obj_t audio_tts_make_new(const mp_obj_type_t *type, Helios_Audio_SetAudioChannle(device); - audio_tts_obj_t *self = m_new_obj(audio_tts_obj_t); + if(NULL == tts_obj) + { + tts_obj = m_new_obj_with_finaliser(audio_tts_obj_t); + } + + audio_tts_obj_t *self = tts_obj; self->base.type = &audio_tts_type; self->inited = 0; - self->tts_speed = 5; + self->tts_speed = 4;//5 changed by freddy@20211008 if (audio.inited == 0) { @@ -169,7 +186,6 @@ STATIC mp_obj_t audio_tts_make_new(const mp_obj_type_t *type, } } -#ifdef PLAT_ASR int ret = Helios_TTS_Init(app_helios_tts_callback); if (ret == 0) { @@ -180,7 +196,7 @@ STATIC mp_obj_t audio_tts_make_new(const mp_obj_type_t *type, mp_raise_ValueError("TTS Init failed."); } Helios_TTS_SetSpeed(self->tts_speed); -#endif + return MP_OBJ_FROM_PTR(self); } @@ -218,7 +234,8 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - int new_mode = vals[ARG_mode].u_int; + int new_mode = vals[ARG_mode].u_int & 0x0000000F; + int wtts_mod_mask = vals[ARG_mode].u_int & 0x000000F0; if ((new_mode < 1) || (new_mode > 3)) { @@ -226,19 +243,16 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw mp_raise_ValueError("invalid mode"); return mp_obj_new_int(-1); } - - //char *new_data; - const char *src_data; - if (mp_obj_is_str(vals[ARG_data].u_obj)) - { - src_data = mp_obj_str_get_str(vals[ARG_data].u_obj); - } - else - { - src_data = NULL; - mp_raise_ValueError("invalid data"); - } - HELIOS_TTS_LOG("src_data is %s\n",src_data); + + if(new_mode == 2) + { + new_mode = TTS_MOD_UTF8;//UTF8 mode + } + + new_mode |= (uint8_t)wtts_mod_mask; + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(vals[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); int new_priority = vals[ARG_priority].u_int; int new_breakin = vals[ARG_breakin].u_int; @@ -249,19 +263,10 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw mp_raise_ValueError("invalid breakin value, must be in [0,1]"); } - char new_data[500] = {0}; - int gbk_len = 500; - int src_len = strlen(src_data); - if(src_len > gbk_len) { - mp_raise_ValueError("The string length cannot be greater than 500"); - } - int retval = SwitchToGbk((const unsigned char *)src_data, strlen(src_data), (unsigned char *)new_data, &gbk_len); - if (retval != 0) - { - return mp_obj_new_int(-1); + if(bufinfo.len > MAX_TTS_TEXT_LEN) { + mp_raise_msg_varg(&mp_type_ValueError, "The string length cannot be greater than %d", MAX_TTS_TEXT_LEN); } - HELIOS_TTS_LOG("gbk data len : %d, strlen = %d\r\n", gbk_len, strlen(new_data)); - + Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); if (audio.audio_state == AUDIO_IDLE) { @@ -306,7 +311,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw audio.audio_queue[new_priority].audio_data[rear].breakin = new_breakin; audio.audio_queue[new_priority].audio_data[rear].mode = new_mode; memset(audio.audio_queue[new_priority].audio_data[rear].data, 0, 500); - strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, gbk_len); + 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++; @@ -344,7 +349,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw audio.audio_queue[new_priority].audio_data[rear].breakin = new_breakin; audio.audio_queue[new_priority].audio_data[rear].mode = new_mode; memset(audio.audio_queue[new_priority].audio_data[rear].data, 0, 500); - strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, gbk_len); + 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); @@ -386,7 +391,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw audio.audio_queue[new_priority].audio_data[rear].breakin = new_breakin; audio.audio_queue[new_priority].audio_data[rear].mode = new_mode; memset(audio.audio_queue[new_priority].audio_data[rear].data, 0, 500); - strncpy(audio.audio_queue[new_priority].audio_data[rear].data, new_data, gbk_len); + 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++; @@ -401,8 +406,7 @@ STATIC mp_obj_t audio_tts_play(size_t n_args, const mp_obj_t *args, mp_map_t *kw } } -#ifdef PLAT_ASR - int ret = Helios_TTS_Start(new_mode, new_data, gbk_len); + int ret = Helios_TTS_Start(new_mode, bufinfo.buf, bufinfo.len); if (ret == -1) { Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); @@ -410,15 +414,10 @@ 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(ret); -#else - return mp_obj_new_int(0); -#endif - } MP_DEFINE_CONST_FUN_OBJ_KW(audio_tts_play_obj, 1, audio_tts_play); STATIC mp_obj_t audio_tts_init(mp_obj_t self_in) { -#ifdef PLAT_ASR audio_tts_obj_t *self = MP_OBJ_TO_PTR(self_in); int ret = Helios_TTS_Init(NULL); if (ret == -1) @@ -426,13 +425,12 @@ STATIC mp_obj_t audio_tts_init(mp_obj_t self_in) { return mp_obj_new_int(-1); } self->inited = 1; -#endif + return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(audio_tts_init_obj, audio_tts_init); STATIC mp_obj_t audio_tts_deinit(mp_obj_t self_in) { -#ifdef PLAT_ASR audio_tts_obj_t *self = MP_OBJ_TO_PTR(self_in); int ret = Helios_TTS_Deinit(); @@ -441,7 +439,7 @@ STATIC mp_obj_t audio_tts_deinit(mp_obj_t self_in) { return mp_obj_new_int(-1); } self->inited = 0; -#endif + return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(audio_tts_deinit_obj, audio_tts_deinit); @@ -449,9 +447,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(audio_tts_deinit_obj, audio_tts_deinit); STATIC mp_obj_t aduio_tts_stop(mp_obj_t self_in) { //audio_tts_obj_t *self = MP_OBJ_TO_PTR(self_in); -#ifdef PLAT_ASR Helios_TTS_Stop(); -#endif return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_stop_obj, aduio_tts_stop); @@ -469,9 +465,9 @@ STATIC mp_obj_t aduio_tts_stop_all(mp_obj_t self_in) audio.total_nums = 0; //audio.audio_state = AUDIO_IDLE; Helios_Mutex_Unlock(audio.queue_mutex); -#ifdef PLAT_ASR + Helios_TTS_Stop(); -#endif + return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_stop_all_obj, aduio_tts_stop_all); @@ -488,7 +484,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_stop_all_obj, aduio_tts_stop_all); /*=============================================================================*/ STATIC mp_obj_t aduio_tts_set_volume(mp_obj_t self_in, mp_obj_t volume) { -#ifdef PLAT_ASR int index = mp_obj_get_int(volume); if ((index > 9) || (index < 0)) { @@ -498,9 +493,6 @@ STATIC mp_obj_t aduio_tts_set_volume(mp_obj_t self_in, mp_obj_t volume) //int vol_map[10] = {-32768, -25487, -18206, -10925, -3644, 3637, 10918, 18199, 25480, 32761}; int ret = Helios_TTS_SetVolume(index); //first para only works in unisoc -#else - int ret = 0; -#endif return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(aduio_tts_set_volume_obj, aduio_tts_set_volume); @@ -519,11 +511,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(aduio_tts_set_volume_obj, aduio_tts_set_volume) /*=============================================================================*/ STATIC mp_obj_t aduio_tts_get_volume(mp_obj_t self_in) { -#ifdef PLAT_ASR int vol = Helios_TTS_GetVolume(); -#else - int vol = 0; -#endif return mp_obj_new_int(vol); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_get_volume_obj, aduio_tts_get_volume); @@ -549,16 +537,13 @@ STATIC mp_obj_t aduio_tts_set_speed(mp_obj_t self_in, mp_obj_t speed) return mp_obj_new_int(-1); } self->tts_speed = index; -#ifdef PLAT_ASR + int ret = Helios_TTS_SetSpeed(self->tts_speed); if(ret) { HELIOS_TTS_LOG("Helios_TTS_SetSpeed failed\n"); } return mp_obj_new_int(ret); -#else - return mp_obj_new_int(-1); -#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_2(aduio_tts_set_speed_obj, aduio_tts_set_speed); @@ -577,27 +562,53 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(aduio_tts_set_speed_obj, aduio_tts_set_speed); STATIC mp_obj_t aduio_tts_get_speed(mp_obj_t self_in) { audio_tts_obj_t *self = MP_OBJ_TO_PTR(self_in); -#ifdef PLAT_ASR + return mp_obj_new_int(Helios_TTS_GetSpeed()); -#else - return mp_obj_new_int(self->tts_speed); -#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_get_speed_obj, aduio_tts_get_speed); STATIC mp_obj_t aduio_tts_get_state(mp_obj_t self_in) { -#ifdef PLAT_ASR int state = Helios_TTS_GetStatus(); return mp_obj_new_int(state); -#else - return mp_obj_new_int(-1); -#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts_get_state_obj, aduio_tts_get_state); +STATIC mp_obj_t aduio_tts___del__(mp_obj_t self_in) +{ +#ifdef PLAT_ASR + audio_tts_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint8_t i = 0; + Helios_Mutex_Lock(audio.queue_mutex, HELIOS_WAIT_FOREVER); + for (i=0; iinited = 0; +#endif + tts_obj = NULL; + g_tts_callback = NULL; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(aduio_tts___del___obj, aduio_tts___del__); + STATIC const mp_rom_map_elem_t audio_tts_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&aduio_tts___del___obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&audio_tts_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audio_tts_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audio_tts_play_obj) }, @@ -610,6 +621,14 @@ STATIC const mp_rom_map_elem_t audio_tts_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_getSpeed), MP_ROM_PTR(&aduio_tts_get_speed_obj) }, { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&aduio_tts_get_state_obj) }, { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&helios_set_tts_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_text_utf16be), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_text_utf8), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_text_utf16le), MP_ROM_INT(3) }, +#if defined(CONFIG_VIOCE_CALL) + { MP_ROM_QSTR(MP_QSTR_wtts_enable), MP_ROM_INT(0x80) }, + { MP_ROM_QSTR(MP_QSTR_wtts_ul_enable), MP_ROM_INT(0x40) }, + { MP_ROM_QSTR(MP_QSTR_wtts_dl_enable), MP_ROM_INT(0x20) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(audio_tts_locals_dict, audio_tts_locals_dict_table); diff --git a/ports/quectel/core/source/camera_capture.c b/ports/quectel/core/source/camera_capture.c index d3ee743..aa54a42 100644 --- a/ports/quectel/core/source/camera_capture.c +++ b/ports/quectel/core/source/camera_capture.c @@ -1,284 +1,316 @@ -/* - * 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 camera_preview.c - @brief Add API to camera preview. - - DESCRIPTION - This module provide the camera API of micropython. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - - - =========================================================================== - Copyright (c) 2018 Quectel Wireless Solution, Co., Ltd.All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - =========================================================================== - - 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 ----------- --------- --------------------------------------------------- -27/01/2021 felix.ye Create. -**************************************************************************/ -#include -#include "runtime.h" - -#include "helios_camera.h" - -#include "jpeglib.h" -#include "jpeg_operation.h" - - -#include "helios_debug.h" - -#define CAPTURE_LOG(msg, ...) custom_log("capture", msg, ##__VA_ARGS__) - - - -#define OPEN_PREVIEW_AND_DECODE 1 -const mp_obj_type_t camera_capture_type; - -static mp_obj_t callback_cur = NULL; - -typedef struct _preview_obj_t { - mp_obj_base_t base; - unsigned short cam_w; - unsigned short cam_h; - unsigned short lcd_w; - unsigned short lcd_h; - unsigned char prebufcnt; - unsigned char perview; - unsigned char decbufcnt; - mp_obj_t callback; - //int inited; -} preview_obj_t; - -static Helios_CAMConfig camconfig = {0}; - - -static unsigned short *g_lcd_buffer = NULL; - -#define __align(x) __attribute__ ((aligned (x))) -#define CAM_W 640 -#define CAM_H 480 -#define LCD_W 160 -#define LCD_H 128 -#define DECODE_BUF_CNT 0 -#define PREVIEW_BUF_CNT 2 - -#define CAMERA_PREVIEW_TASK_PRIORITY 218 -#define CAMERA_DECODE_TASK_PRIORITY 227 - -typedef struct img_info_struct{ - int img_width; - int img_height; - unsigned char image_name[128]; -}img_info_s; - -static img_info_s image_info = {0}; - -void Helios_SaveImage(unsigned char* pYUVBuffer, int width, int height) { - int result = -1; - char name[256] = {0}; - - sprintf(name, "U:/%s.jpeg",image_info.image_name); - CAPTURE_LOG("SaveImage %d %d %d %d\n", width, height, image_info.img_width, image_info.img_height); - - if(image_info.img_width <= width && image_info.img_height <= height) { - if(0 != yuv420_NV12_to_jpg(name, image_info.img_width, image_info.img_height, pYUVBuffer, width, height)) { - CAPTURE_LOG("Helios_SaveImage fail\n"); - } else { - result = 0; - CAPTURE_LOG("Helios_SaveImage success\n"); - } - } - - if(callback_cur != NULL) { - mp_obj_t save_cb[2] = { - mp_obj_new_int(result), - mp_obj_new_str((char*)name,strlen((char*)name)), - }; - if(mp_obj_is_callable(callback_cur)){ - mp_sched_schedule(callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_list(2, save_cb))); - } - } -} - -STATIC mp_obj_t caputre_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) -{ - enum { ARG_model, ARG_cam_w, ARG_cam_h, ARG_lcd_w, ARG_lcd_h, ARG_perview_level}; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_model, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_cam_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 640} }, - { MP_QSTR_cam_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 480} }, - { MP_QSTR_lcd_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 160} }, - { MP_QSTR_lcd_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 128} }, - { MP_QSTR_perview_level, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1} }, - }; - 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); - - int model = args[ARG_model].u_int; - unsigned short camwidth = (unsigned short)args[ARG_cam_w].u_int; - unsigned short camheight = (unsigned short)args[ARG_cam_h].u_int; - unsigned short lcdprewidth = (unsigned short)args[ARG_lcd_w].u_int; - unsigned short lcdpreheight = (unsigned short)args[ARG_lcd_h].u_int; - unsigned char prebufcnt = (unsigned char)args[ARG_perview_level].u_int; - - if ( prebufcnt != 1 && prebufcnt != 2 && prebufcnt != 0) { - mp_raise_ValueError("perview_level must be [0,2]"); - } - - if ( lcdpreheight > 500) { - mp_raise_ValueError("lcd_h must be (0,500)"); - } - if ( lcdprewidth > 500) { - mp_raise_ValueError("lcd_w must be (0,500)"); - } - if ( camwidth > 640) { - mp_raise_ValueError("camwidth must be (0,640)"); - } - if ( camheight > 640) { - mp_raise_ValueError("camheight must be (0,640)"); - } - - CAPTURE_LOG("data camwidth etc = %d,%d,%d,%d,%d\n",camwidth,camheight,lcdprewidth,lcdpreheight,prebufcnt); - - preview_obj_t *self = m_new_obj(preview_obj_t); - self->base.type = &camera_capture_type; - self->cam_h = camheight; - self->cam_w = camwidth; - self->lcd_h = lcdpreheight; - self->lcd_w = lcdprewidth; - self->prebufcnt = prebufcnt; - - camconfig.model = model; - camconfig.camheight = camheight; - camconfig.camwidth = camwidth; - camconfig.lcdpreheight = lcdpreheight; - camconfig.lcdprewidth = lcdprewidth; - camconfig.prebufcnt = prebufcnt; - camconfig.saveimg_pro = Helios_SaveImage; - camconfig.decbufcnt = 1; - camconfig.preview = 1; - - if(camconfig.prebufcnt == 0) { - camconfig.preview = 0; - } - - - return MP_OBJ_FROM_PTR(self); -} - - -STATIC mp_obj_t camera_open(mp_obj_t 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); - - return mp_obj_new_int(error); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture_open_obj, camera_open); - -STATIC mp_obj_t camera_close(mp_obj_t self_in) -{ - - int error = Helios_camera_close(); - - return mp_obj_new_int(error); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture_close_obj, camera_close); - -STATIC const mp_arg_t capture_open_allowed_args[] = { - { MP_QSTR_image_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 640} }, - { MP_QSTR_image_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 480} }, - { MP_QSTR_picture_name, MP_ARG_REQUIRED | MP_ARG_OBJ,{.u_obj = MP_OBJ_NULL} }, -}; - -STATIC mp_obj_t camera_capture_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - - enum { ARG_image_w, ARG_image_h, ARG_picture_name}; - - mp_arg_val_t args[MP_ARRAY_SIZE(capture_open_allowed_args)]; - - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(capture_open_allowed_args), capture_open_allowed_args, args); - - char *picname = NULL; - if (mp_obj_is_str(args[ARG_picture_name].u_obj)) { - picname = (char*)mp_obj_str_get_str(args[ARG_picture_name].u_obj); - } - int image_w = (int)args[ARG_image_w].u_int; - int image_h = (int)args[ARG_image_h].u_int; - - if(picname == NULL) { - mp_raise_ValueError("image nane is error"); - } - - - if ( image_w < 0 || image_w > camconfig.camwidth) { - mp_raise_ValueError("image_w is less than cam_w"); - } - - if ( image_h > camconfig.camheight || image_h < 0) { - mp_raise_ValueError("image_h is less tha cam_h"); - } - - memset(&image_info, 0, sizeof(img_info_s)); - image_info.img_height = image_h; - image_info.img_width = image_w; - memcpy(image_info.image_name, picname, strlen(picname)); - - CAPTURE_LOG("capture para %d,%d,%s\n",image_w,image_h,picname); - - int ret = Helios_camera_caputre(); - return mp_obj_new_int(ret); - -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(camera_capture_start_obj,1, camera_capture_start); - -STATIC mp_obj_t camera_save_callback(mp_obj_t self_in, mp_obj_t callback) -{ - preview_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->callback = callback; - callback_cur = callback; - return mp_obj_new_int(0); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(camera_capture_callback_obj, camera_save_callback); - - - - -STATIC const mp_rom_map_elem_t Preview_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&camera_capture_open_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&camera_capture_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&camera_capture_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&camera_capture_callback_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(camCapture_locals_dict, Preview_locals_dict_table); - -const mp_obj_type_t camera_capture_type = { - { &mp_type_type }, - .name = MP_QSTR_camCaputre, - .make_new = caputre_make_new, - .locals_dict = (mp_obj_dict_t *)&camCapture_locals_dict, -}; +/* + * 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 camera_preview.c + @brief Add API to camera preview. + + DESCRIPTION + This module provide the camera API of micropython. + + INITIALIZATION AND SEQUENCING REQUIREMENTS + + + =========================================================================== + Copyright (c) 2018 Quectel Wireless Solution, Co., Ltd.All Rights Reserved. + Quectel Wireless Solution Proprietary and Confidential. + =========================================================================== + + 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 +---------- --------- --------------------------------------------------- +27/01/2021 felix.ye Create. +**************************************************************************/ +#include +#include "runtime.h" + +#include "helios_camera.h" + +#include "jpeglib.h" +#include "jpeg_operation.h" + + +#include "helios_debug.h" + +#define CAPTURE_LOG(msg, ...) custom_log("capture", msg, ##__VA_ARGS__) + + + +#define OPEN_PREVIEW_AND_DECODE 1 +const mp_obj_type_t camera_capture_type; + +static c_callback_t *callback_cur = NULL; + +typedef struct _preview_obj_t { + mp_obj_base_t base; + unsigned short cam_w; + unsigned short cam_h; + unsigned short lcd_w; + unsigned short lcd_h; + unsigned char prebufcnt; + unsigned char perview; + unsigned char decbufcnt; + c_callback_t *callback; + //int inited; +} preview_obj_t; + +static preview_obj_t *capture_obj = NULL; + +static Helios_CAMConfig camconfig = {0}; + + +static unsigned short *g_lcd_buffer = NULL; + +#define __align(x) __attribute__ ((aligned (x))) +#define CAM_W 640 +#define CAM_H 480 +#define LCD_W 160 +#define LCD_H 128 +#define DECODE_BUF_CNT 0 +#define PREVIEW_BUF_CNT 2 + +#define CAMERA_PREVIEW_TASK_PRIORITY 218 +#define CAMERA_DECODE_TASK_PRIORITY 227 + +typedef struct img_info_struct{ + int img_width; + int img_height; + unsigned char image_name[128]; +}img_info_s; + +static img_info_s image_info = {0}; + +void Helios_SaveImage(unsigned char* pYUVBuffer, int width, int height) { + int result = -1; + char name[256] = {0}; + + + sprintf(name, "U:/%s.jpeg",image_info.image_name); + CAPTURE_LOG("SaveImage %d %d %d %d\n", width, height, image_info.img_width, image_info.img_height); + + if(image_info.img_width <= width && image_info.img_height <= height && pYUVBuffer != NULL) { + +#if defined(PLAT_ASR) + if(0 != yuv420_NV12_to_jpg(name, image_info.img_width, image_info.img_height, pYUVBuffer, width, height)) +#elif defined(PLAT_Unisoc) + if(0 != yuv422_UYVY_to_jpg(name, image_info.img_width, image_info.img_height, pYUVBuffer, width, height)) +#else + error("Helios_SaveImage:Uncertain picture format"); +#endif + { + CAPTURE_LOG("Helios_SaveImage fail\n"); + } else { + result = 0; + CAPTURE_LOG("Helios_SaveImage success\n"); + } + } + + if(callback_cur != NULL) { + mp_obj_t save_cb[2] = { + mp_obj_new_int(result), + mp_obj_new_str((char*)name,strlen((char*)name)), + }; + + mp_sched_schedule_ex(callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_list(2, save_cb))); + + } +} + +STATIC mp_obj_t caputre_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_model, ARG_cam_w, ARG_cam_h, ARG_perview_level, ARG_lcd_w, ARG_lcd_h}; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_model, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cam_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 640} }, + { MP_QSTR_cam_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 480} }, + { MP_QSTR_perview_level, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_lcd_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 160} }, + { MP_QSTR_lcd_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 128} }, + + }; + 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); + + int model = args[ARG_model].u_int; + unsigned short camwidth = (unsigned short)args[ARG_cam_w].u_int; + unsigned short camheight = (unsigned short)args[ARG_cam_h].u_int; + unsigned short lcdprewidth = (unsigned short)args[ARG_lcd_w].u_int; + unsigned short lcdpreheight = (unsigned short)args[ARG_lcd_h].u_int; + unsigned char prebufcnt = (unsigned char)args[ARG_perview_level].u_int; + + if ( prebufcnt != 1 && prebufcnt != 2 && prebufcnt != 0) { + mp_raise_ValueError("perview_level must be [0,2]"); + } + + if ( lcdpreheight > 500) { + mp_raise_ValueError("lcd_h must be (0,500)"); + } + if ( lcdprewidth > 500) { + mp_raise_ValueError("lcd_w must be (0,500)"); + } + if ( camwidth > 640) { + mp_raise_ValueError("camwidth must be (0,640)"); + } + if ( camheight > 640) { + mp_raise_ValueError("camheight must be (0,640)"); + } + + CAPTURE_LOG("data camwidth etc = %d,%d,%d,%d,%d\n",camwidth,camheight,lcdprewidth,lcdpreheight,prebufcnt); + + if(capture_obj == NULL) + { + capture_obj = m_new_obj_with_finaliser(preview_obj_t); + } + preview_obj_t *self = capture_obj; + self->base.type = &camera_capture_type; + self->cam_h = camheight; + self->cam_w = camwidth; + self->lcd_h = lcdpreheight; + self->lcd_w = lcdprewidth; + self->prebufcnt = prebufcnt; + + camconfig.model = model; + camconfig.camheight = camheight; + camconfig.camwidth = camwidth; + camconfig.lcdpreheight = lcdpreheight; + camconfig.lcdprewidth = lcdprewidth; + camconfig.prebufcnt = prebufcnt; + camconfig.saveimg_pro = Helios_SaveImage; + camconfig.decbufcnt = 1; + camconfig.preview = 1; + + if(camconfig.prebufcnt == 0) { + camconfig.preview = 0; + } + + + return MP_OBJ_FROM_PTR(self); +} + + +STATIC mp_obj_t camera_open(mp_obj_t 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); + + return mp_obj_new_int(error); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture_open_obj, camera_open); + +STATIC mp_obj_t camera_close(mp_obj_t self_in) +{ + + int error = Helios_camera_close(); + + return mp_obj_new_int(error); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture_close_obj, camera_close); + +STATIC const mp_arg_t capture_open_allowed_args[] = { + { MP_QSTR_image_w, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 640} }, + { MP_QSTR_image_h, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 480} }, + { MP_QSTR_picture_name, MP_ARG_REQUIRED | MP_ARG_OBJ,{.u_obj = MP_OBJ_NULL} }, +}; + +STATIC mp_obj_t camera_capture_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + + enum { ARG_image_w, ARG_image_h, ARG_picture_name}; + + mp_arg_val_t args[MP_ARRAY_SIZE(capture_open_allowed_args)]; + + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(capture_open_allowed_args), capture_open_allowed_args, args); + + char *picname = NULL; + if (mp_obj_is_str(args[ARG_picture_name].u_obj)) { + picname = (char*)mp_obj_str_get_str(args[ARG_picture_name].u_obj); + } + int image_w = (int)args[ARG_image_w].u_int; + int image_h = (int)args[ARG_image_h].u_int; + + if(picname == NULL) { + mp_raise_ValueError("image nane is error"); + } + + + if ( image_w < 0 || image_w > camconfig.camwidth) { + mp_raise_ValueError("image_w is less than cam_w"); + } + + if ( image_h > camconfig.camheight || image_h < 0) { + mp_raise_ValueError("image_h is less tha cam_h"); + } + + memset(&image_info, 0, sizeof(img_info_s)); + image_info.img_height = image_h; + image_info.img_width = image_w; + memcpy(image_info.image_name, picname, strlen(picname)); + + CAPTURE_LOG("capture para %d,%d,%s\n",image_w,image_h,picname); + + int ret = Helios_camera_capture(); + return mp_obj_new_int(ret); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(camera_capture_start_obj,1, camera_capture_start); + +STATIC mp_obj_t camera_save_callback(mp_obj_t self_in, mp_obj_t callback) +{ + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + callback_cur = &cb; + mp_sched_schedule_callback_register(callback_cur, callback); + + self->callback = callback_cur; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(camera_capture_callback_obj, camera_save_callback); + + +STATIC mp_obj_t camera_capture_deinit(mp_obj_t self_in) +{ + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + ret = Helios_camera_close(); + callback_cur = NULL; + capture_obj = NULL; + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_capture__del__obj, camera_capture_deinit); + + +STATIC const mp_rom_map_elem_t Preview_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&camera_capture__del__obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&camera_capture_open_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&camera_capture_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&camera_capture_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&camera_capture_callback_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(camCapture_locals_dict, Preview_locals_dict_table); + +const mp_obj_type_t camera_capture_type = { + { &mp_type_type }, + .name = MP_QSTR_camCapture, + .make_new = caputre_make_new, + .locals_dict = (mp_obj_dict_t *)&camCapture_locals_dict, +}; diff --git a/ports/quectel/core/source/camera_preview.c b/ports/quectel/core/source/camera_preview.c index eaeb245..f11ff5c 100644 --- a/ports/quectel/core/source/camera_preview.c +++ b/ports/quectel/core/source/camera_preview.c @@ -58,6 +58,7 @@ typedef struct _preview_obj_t { } preview_obj_t; static Helios_CAMConfig camconfig = {0}; +static preview_obj_t *preview_obj = NULL; STATIC mp_obj_t preview_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) @@ -100,8 +101,13 @@ STATIC mp_obj_t preview_make_new(const mp_obj_type_t *type, size_t n_args, size_ } printf("data camwidth etc = %d,%d,%d,%d,%d\n",camwidth,camheight,lcdprewidth,lcdpreheight,prebufcnt); + + if(preview_obj == NULL) + { + preview_obj = m_new_obj_with_finaliser(preview_obj_t); + } - preview_obj_t *self = m_new_obj(preview_obj_t); + preview_obj_t *self = preview_obj; self->base.type = &camera_preview_type; self->cam_h = camheight; self->cam_w = camwidth; @@ -144,10 +150,20 @@ STATIC mp_obj_t camera_close(mp_obj_t self_in) } STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_preview_close_obj, camera_close); +STATIC mp_obj_t camera_preview_deinit(mp_obj_t self_in) +{ + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + preview_obj = NULL; + ret = Helios_camera_close(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_preview__del__obj, camera_preview_deinit); STATIC const mp_rom_map_elem_t Preview_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&camera_preview__del__obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&camera_preview_open_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&camera_preview_close_obj) }, diff --git a/ports/quectel/core/source/camera_scandecode.c b/ports/quectel/core/source/camera_scandecode.c index 74d2e56..92c2803 100644 --- a/ports/quectel/core/source/camera_scandecode.c +++ b/ports/quectel/core/source/camera_scandecode.c @@ -53,7 +53,7 @@ WHEN WHO WHAT,WHERE,WHY #define OPEN_PREVIEW_AND_DECODE 1 const mp_obj_type_t camera_scandecode_type; -static mp_obj_t callback_cur = NULL; +static c_callback_t *callback_cur = NULL; static Helios_CAMConfig camconfig = {0}; @@ -74,10 +74,13 @@ typedef struct _preview_obj_t { unsigned char prebufcnt; unsigned char perview; unsigned char decbufcnt; - mp_obj_t callback; + c_callback_t *callback; //int inited; } preview_obj_t; +static preview_obj_t *scandecode_obj = NULL; + + zbar_image_scanner_t *scanner = NULL; void camDecode(unsigned char* raw, int width, int height) { @@ -125,9 +128,9 @@ zbar_image_scanner_t *scanner = NULL; mp_obj_new_int(0), mp_obj_new_str((char*)data,strlen((char*)data)), }; - if(mp_obj_is_callable(callback_cur)){ - mp_sched_schedule(callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_list(2, decode_cb))); - } + + mp_sched_schedule_ex(callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_list(2, decode_cb))); + } } @@ -194,8 +197,12 @@ STATIC mp_obj_t scandecode_make_new(const mp_obj_type_t *type, size_t n_args, si SCANDE_LOG("data camwidth etc = %d,%d,%d,%d,%d\n",camwidth,camheight,lcdprewidth,lcdpreheight,prebufcnt); + if(scandecode_obj == NULL) + { + scandecode_obj = m_new_obj_with_finaliser(preview_obj_t); + } - preview_obj_t *self = m_new_obj(preview_obj_t); + preview_obj_t *self = scandecode_obj; self->base.type = &camera_scandecode_type; self->cam_h = camheight; self->cam_w = camwidth; @@ -275,8 +282,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_scandecode_resume_obj, camera_scandecode STATIC mp_obj_t camera_scandecode_stop(mp_obj_t self_in) { - camera_switch(DECODE_CLOSE); int error = Helios_camera_scandecode_stop(); + //camera_switch(DECODE_CLOSE); return mp_obj_new_int(error); } @@ -287,14 +294,33 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_scandecode_stop_obj, camera_scandecode_s STATIC mp_obj_t camera_scandecode_callback(mp_obj_t self_in, mp_obj_t callback) { preview_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->callback = callback; - callback_cur = callback; + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + callback_cur = &cb; + mp_sched_schedule_callback_register(callback_cur, callback); + + self->callback = callback_cur; return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(camera_scandecode_callback_obj, camera_scandecode_callback); +STATIC mp_obj_t camera_scandecode_deinit(mp_obj_t self_in) +{ + preview_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + ret = Helios_camera_close(); + callback_cur = NULL; + scandecode_obj = NULL; + self->callback = NULL; + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_scandecode__del__obj, camera_scandecode_deinit); + + STATIC const mp_rom_map_elem_t scandecode_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&camera_scandecode__del__obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&camera_scandecode_open_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&camera_scandecode_close_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&camera_scandecode_start_obj) }, diff --git a/ports/quectel/core/source/machine_extint.c b/ports/quectel/core/source/machine_extint.c index 4db09eb..5824e97 100644 --- a/ports/quectel/core/source/machine_extint.c +++ b/ports/quectel/core/source/machine_extint.c @@ -23,80 +23,61 @@ #include "mphal.h" #include "helios_extint.h" +#include "helios_debug.h" -extern int Helios_GPIO_GetLevel(Helios_GPIONUM gpio_num); +#define EXTINT_LOG(msg, ...) custom_log("extint", msg, ##__VA_ARGS__) + + +extern int Helios_GPIO_GetLevel(Helios_GPIONum gpio_num); -enum { - GPIO0 = 0, - GPIO1, - GPIO2, - GPIO3, - GPIO4, - GPIO5, - GPIO6, - GPIO7, - GPIO8, - GPIO9, - GPIO10, - GPIO11, - GPIO12, - GPIO13, - GPIO14, - GPIO15, - GPIO16, - GPIO17, - GPIO18, - GPIO19, - GPIO20, - GPIO21, - GPIO22, - GPIO23, - GPIO24, - GPIO25, - GPIO26, - GPIO27, - GPIO28, - GPIO29, - GPIO30, - GPIO31, - GPIOMAX, -}; typedef struct { mp_obj_base_t base; mp_int_t line; mp_int_t mode; mp_int_t pull; - mp_obj_t callback; + c_callback_t callback; } extint_obj_t; +typedef struct { + mp_int_t rising_count; + mp_int_t falling_count; +} extint_count_t; + typedef void(*eint_handler_t)(void); -static extint_obj_t extint_obj[HELIOS_GPIOMAX]; +static extint_obj_t *extint_obj[HELIOS_GPIOMAX]; +static extint_count_t extint_count[HELIOS_GPIOMAX] = {0}; enum { HELIOS_EXTINT_RISING, HELIOS_EXTINT_FALLING, }; +#define EINT_HANDLER_DEF(n) handler##n +#define PLAT_EINT_HANDLER_DEF(n) BOOST_PP_REPEAT_1(n,EINT_HANDLER_DEF) + + /* ** Jayceon-20200908: -** Replace function mp_call_function_1_protected() with mp_sched_schedule to slove the dump problem. +** Replace function mp_call_function_1_protected() with mp_sched_schedule_ex to slove the dump problem. */ -#define HANDLER_FUN(X) \ -static void handler##X(void) \ -{ \ - int edge = HELIOS_EXTINT_RISING; \ - if (extint_obj[X].callback != mp_const_none) { \ - if(Helios_GPIO_GetLevel((Helios_GPIONUM)X) == 0) \ - {edge = HELIOS_EXTINT_FALLING;} \ - mp_obj_t extint_list[2] = { \ - mp_obj_new_int(X), \ - mp_obj_new_int(edge), \ - }; \ - mp_sched_schedule(extint_obj[X].callback, mp_obj_new_list(2, extint_list)); \ - } \ - Helios_ExtInt_Enable(extint_obj[X].line); \ +#define HANDLER_FUN(X) \ +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 && \ + ((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)); \ + } \ + Helios_ExtInt_Enable(extint_obj[X]->line); \ } @@ -132,17 +113,26 @@ HANDLER_FUN(28) HANDLER_FUN(29) HANDLER_FUN(30) HANDLER_FUN(31) - +HANDLER_FUN(32) +HANDLER_FUN(33) +HANDLER_FUN(34) +HANDLER_FUN(35) +HANDLER_FUN(36) +HANDLER_FUN(37) +HANDLER_FUN(38) +HANDLER_FUN(39) +HANDLER_FUN(40) +HANDLER_FUN(41) eint_handler_t eint_handler[HELIOS_GPIOMAX] = { - handler0, handler1, handler2, handler3, handler4, handler5, handler6, handler7, handler8, handler9, - handler10, handler11, handler12, handler13, handler14, handler15, handler16, handler17, handler18, handler19, - handler20, handler21, handler22, handler23, handler24, handler25, handler26, handler27, handler28, handler29, - handler30, handler31, + handler0, PLAT_EINT_HANDLER_DEF(PLAT_GPIO_NUM) }; - +static void extint_count_reset(int offset) { + extint_count[offset].falling_count = 0; + extint_count[offset].rising_count = 0; +} /// \method line() /// Return the line number that the pin is mapped to. @@ -156,7 +146,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_line_obj, extint_obj_line); /// Enable a disabled interrupt. STATIC mp_obj_t extint_obj_enable(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = Helios_ExtInt_Enable((Helios_GPIONUM) self->line); + int ret = Helios_ExtInt_Enable((Helios_GPIONum) self->line); return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable); @@ -166,7 +156,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_enable_obj, extint_obj_enable); /// This could be useful for debouncing. STATIC mp_obj_t extint_obj_disable(mp_obj_t self_in) { extint_obj_t *self = MP_OBJ_TO_PTR(self_in); - int ret = Helios_ExtInt_Disable((Helios_GPIONUM) self->line); + int ret = Helios_ExtInt_Disable((Helios_GPIONum) self->line); return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_disable_obj, extint_obj_disable); @@ -204,7 +194,12 @@ STATIC mp_obj_t extint_make_new(const mp_obj_type_t *type, size_t n_args, size_t if (vals[0].u_int < HELIOS_GPIO0 || vals[0].u_int > HELIOS_GPIOMAX) { mp_raise_ValueError("invalid pin value"); } - extint_obj_t *self = &extint_obj[vals[0].u_int]; + + if (extint_obj[vals[0].u_int] == NULL) + { + extint_obj[vals[0].u_int] = m_new_obj_with_finaliser(extint_obj_t); + } + extint_obj_t *self = extint_obj[vals[0].u_int]; self->base.type = type; self->line = vals[0].u_int; @@ -217,20 +212,22 @@ STATIC mp_obj_t extint_make_new(const mp_obj_type_t *type, size_t n_args, size_t if (self->pull < HELIOS_PULL_NONE || self->pull > HELIOS_PULL_DOWN) { mp_raise_ValueError("invalid pull value"); } - if (vals[3].u_obj == mp_const_none) { - mp_raise_ValueError("callback is none"); - } - self->callback = vals[3].u_obj; + + mp_sched_schedule_callback_register(&self->callback, vals[3].u_obj); Helios_ExtIntStruct extint_struct = {0}; extint_struct.gpio_trigger = HELIOS_EDGE_TRIGGER; extint_struct.gpio_edge = self->mode; extint_struct.gpio_debounce = HELIOS_DEBOUNCE_EN; extint_struct.gpio_pull = self->pull; - extint_struct.eint_cb = eint_handler[self->line]; - extint_struct.wakeup_eint_cb = NULL; + extint_struct.eint_cb = NULL; + extint_struct.wakeup_eint_cb = eint_handler[self->line]; - Helios_ExtInt_Init((Helios_GPIONUM) self->line, &extint_struct); + if(0 != Helios_ExtInt_Init((Helios_GPIONum) self->line, &extint_struct)) { + mp_raise_ValueError("Interrupt initialization failed"); + } + + extint_count_reset(self->line); return MP_OBJ_FROM_PTR(self); } @@ -240,10 +237,60 @@ STATIC void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print mp_printf(print, "", self->line); } +STATIC mp_obj_t extint_obj_read_count(mp_obj_t self_in, mp_obj_t is_reset) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int reset_flag = mp_obj_get_int(is_reset); + + if(reset_flag != 0 && reset_flag != 1) { + mp_raise_ValueError("invalid is_reset value, must in [0,1]"); + } + + mp_obj_t extint_list[2] = { + mp_obj_new_int(extint_count[self->line].rising_count), + mp_obj_new_int(extint_count[self->line].falling_count), + }; + + if(1 == reset_flag) { + extint_count_reset(self->line); + } + return mp_obj_new_list(2, extint_list); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(extint_obj_read_count_obj, extint_obj_read_count); + +STATIC mp_obj_t extint_obj_count_reset(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + extint_count_reset(self->line); + + return mp_obj_new_int(0); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_count_reset_obj, extint_obj_count_reset); + +STATIC mp_obj_t extint_obj_Deinit(mp_obj_t self_in) { + extint_obj_t *self = MP_OBJ_TO_PTR(self_in); + int ret = -1; + //EXTINT_LOG("extint deinit"); + + extint_obj[self->line] = NULL; + extint_count_reset(self->line); + + if((0 == Helios_ExtInt_Disable((Helios_GPIONum) self->line)) && (0 == Helios_ExtInt_Deinit((Helios_GPIONum) self->line))) { + ret = 0; + } + + return mp_obj_new_int(ret); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint__del__obj, extint_obj_Deinit); + + STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&extint__del__obj) }, { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&extint_obj_line_obj) }, { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&extint_obj_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_count), MP_ROM_PTR(&extint_obj_read_count_obj) }, + { MP_ROM_QSTR(MP_QSTR_count_reset), MP_ROM_PTR(&extint_obj_count_reset_obj) }, //{ MP_ROM_QSTR(MP_QSTR_swint), MP_ROM_PTR(&extint_obj_swint_obj) }, //{ MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&extint_regs_obj) }, @@ -258,43 +305,25 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_INT(HELIOS_GPIO0) }, - { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, +#if defined(PLAT_Qualcomm) { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_INT(HELIOS_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_INT(HELIOS_GPIO5) }, { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_INT(HELIOS_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, { MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_INT(HELIOS_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_INT(HELIOS_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_INT(HELIOS_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, - -#if defined(PLAT_ASR) { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, - { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, - { MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_INT(HELIOS_GPIO24) }, - { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_INT(HELIOS_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_GPIO27), MP_ROM_INT(HELIOS_GPIO27) }, - { MP_ROM_QSTR(MP_QSTR_GPIO28), MP_ROM_INT(HELIOS_GPIO28) }, - { MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_INT(HELIOS_GPIO29) }, - { MP_ROM_QSTR(MP_QSTR_GPIO30), MP_ROM_INT(HELIOS_GPIO30) }, +#else + PLAT_GPIO_DEF(PLAT_GPIO_NUM), #endif - - //{ MP_ROM_QSTR(MP_QSTR_EVT_RISING), MP_ROM_INT(GPIO_MODE_EVT_RISING) }, - //{ MP_ROM_QSTR(MP_QSTR_EVT_FALLING), MP_ROM_INT(GPIO_MODE_EVT_FALLING) }, - //{ MP_ROM_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_ROM_INT(GPIO_MODE_EVT_RISING_FALLING) }, }; STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table); diff --git a/ports/quectel/core/source/machine_hw_spi.c b/ports/quectel/core/source/machine_hw_spi.c index d967898..94fbe08 100644 --- a/ports/quectel/core/source/machine_hw_spi.c +++ b/ports/quectel/core/source/machine_hw_spi.c @@ -22,7 +22,9 @@ #include "gc.h" #include "mphal.h" #include "mperrno.h" -//#include "machine_spi.h" + +#include "mphalport.h" + #include "helios_spi.h" @@ -68,13 +70,22 @@ mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz if ( mode > 3) { mp_raise_ValueError("mode must be (0~3)"); } - - if (clk > 6) { - mp_raise_ValueError("clk must be (0~6)"); + +#if defined(PLAT_Unisoc) + if (clk > 9) { + mp_raise_ValueError("clk must be (0~9)"); + } +#elif defined(PLAT_RDA) + if (clk > 39) { + mp_raise_ValueError("clk must be (0~39)"); } +#else + if (clk > 6) { + mp_raise_ValueError("clk must be (0~6)"); + } +#endif - machine_hard_spi_obj_t *self = m_new_obj(machine_hard_spi_obj_t); self->base.type = &machine_hard_spi_type; @@ -83,6 +94,9 @@ mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz self->clk = clk; ret = Helios_SPI_Init((Helios_SPINum) self->port, (Helios_SPIMode) self->mode, (uint32_t) self->clk); + if(ret != 0) { + mp_raise_ValueError("spi init fail"); + } HELIOS_SPI_LOG("Helios_SPI_Init %d\r\n",ret); return MP_OBJ_FROM_PTR(self); @@ -177,7 +191,9 @@ STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_read), MP_ROM_PTR(&machine_spi_write_read_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI0), MP_ROM_INT(HELIOS_SPI0) }, +#if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_SPI1), MP_ROM_INT(HELIOS_SPI1) }, +#endif }; MP_DEFINE_CONST_DICT(mp_machine_hard_spi_locals_dict, machine_spi_locals_dict_table); diff --git a/ports/quectel/core/source/machine_iic.c b/ports/quectel/core/source/machine_iic.c index 186dd8d..416a556 100644 --- a/ports/quectel/core/source/machine_iic.c +++ b/ports/quectel/core/source/machine_iic.c @@ -25,6 +25,8 @@ #include "machine_i2c.h" #include "helios_iic.h" +#include "mphalport.h" + const mp_obj_type_t machine_hard_i2c_type; @@ -145,15 +147,17 @@ 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_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) }, -#if 1 // class constants { MP_ROM_QSTR(MP_QSTR_I2C0), MP_ROM_INT(HELIOS_I2C0) }, +#if !defined(PLAT_Qualcomm) { 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) }, { MP_ROM_QSTR(MP_QSTR_I2C3), MP_ROM_INT(HELIOS_I2C3) }, +#endif +#endif { 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) }, -#endif }; MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table); diff --git a/ports/quectel/core/source/machine_keypad.c b/ports/quectel/core/source/machine_keypad.c new file mode 100644 index 0000000..43ea459 --- /dev/null +++ b/ports/quectel/core/source/machine_keypad.c @@ -0,0 +1,172 @@ +/* + * 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 mod_keypad.h + * @author burols.wang + * @version V1.0.0 + * @date 2021/10/29 + * @brief IOT data interaction function module + ****************************************************************************** + */ + +#if defined(PLAT_ASR) +#include +#include +#include + + +#include "compile.h" +#include "runtime.h" +#include "repl.h" +#include "mperrno.h" +#include "helios_keypad.h" +#include "helios_debug.h" +#ifdef MICROPY_PY_MACHINE + + +static c_callback_t *helios_keypad_callback = NULL; + +typedef struct _machine_keypad_obj_t { + mp_obj_base_t base; +} machine_keypad_obj_t; + +static machine_keypad_obj_t *keypad_obj = NULL; + +uint32_t helios_keypad_callback_to_python(Helios_KeyPad_Event event) +{ + mp_obj_t decode_cb[5] = { + mp_obj_new_int((mp_int_t)event.event_id), + mp_obj_new_int((mp_int_t)event.param_01), + mp_obj_new_int((mp_int_t)event.param_02), + mp_obj_new_int((mp_int_t)event.param_03), + mp_obj_new_int((mp_int_t)event.key_v), + }; + + if( helios_keypad_callback == NULL) { + return -1; + } + + mp_sched_schedule_ex(helios_keypad_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(5, decode_cb))); + return 0; +} + +STATIC mp_obj_t helios_keypad_set_callback(mp_obj_t self_in,mp_obj_t callback) +{ + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + helios_keypad_callback = &cb; + mp_sched_schedule_callback_register(helios_keypad_callback, callback); + + Helios_KeyPad_SetCb((Helios_KeyPad_CallBack_t )helios_keypad_callback_to_python); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(keypad_uart_set_callback_obj, helios_keypad_set_callback); + +STATIC mp_obj_t keypad_set_mulikeyen(mp_obj_t self_in,mp_obj_t value) +{ + int en_de = mp_obj_get_int(value); + if (en_de !=0 && en_de !=1 ) + { + mp_raise_ValueError("invalid value must be 0 or 1"); + } + Helios_KeyPad_MuliKeyEn(en_de); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(keypad_set_mulikeyen_obj, keypad_set_mulikeyen); + +STATIC mp_obj_t keypad_set_light(mp_obj_t self_in,mp_obj_t value) +{ + int on_off = mp_obj_get_int(value); + if (on_off !=0 && on_off !=1 ) + { + mp_raise_ValueError("invalid value must be 0 or 1"); + } + int ret = Helios_KeyPad_Light_Ctl(on_off); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(keypad_set_light_obj, keypad_set_light); + +STATIC mp_obj_t keypad_set_lightlevel(mp_obj_t self_in,mp_obj_t value) +{ + int level = mp_obj_get_int(value); + if (!(Helios_KeyPad_Light_Level_0 <= level && level < Helios_KeyPad_Light_Level_MAX ) ) + { + mp_raise_ValueError("invalid value shuld be in [Helios_KeyPad_Light_Level_0,...,Helios_KeyPad_Light_Level_MAX]"); + } + int ret = Helios_KeyPad_Light_Level(level); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(keypad_set_lightlevel_obj, keypad_set_lightlevel); + +STATIC mp_obj_t keypad_init(mp_obj_t self_in) +{ + int ret = Helios_KeyPad_Init(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(keypad_init_obj, keypad_init); + +STATIC mp_obj_t keypad_deinit(mp_obj_t self_in) +{ + helios_keypad_callback = NULL; + keypad_obj = NULL; + + int ret = Helios_KeyPad_Deinit(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(keypad_deinit_obj, keypad_deinit); + + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(keypad__del__obj, keypad_deinit); + + +STATIC const mp_rom_map_elem_t keypad_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_keypad) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&keypad__del__obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&keypad_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_setMuliKeyen), MP_ROM_PTR(&keypad_set_mulikeyen_obj) }, + { MP_ROM_QSTR(MP_QSTR_setLight), MP_ROM_PTR(&keypad_set_light_obj) }, + { MP_ROM_QSTR(MP_QSTR_setLightLeve), MP_ROM_PTR(&keypad_set_lightlevel_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&keypad_uart_set_callback_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(keypad_module_globals, keypad_module_globals_table); +STATIC mp_obj_t machine_keypad_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_keypad_type = { + { &mp_type_type }, + .name = MP_QSTR_KeyPad, + .make_new = machine_keypad_make_new, + .locals_dict = (mp_obj_dict_t *)&keypad_module_globals, +}; + +STATIC mp_obj_t machine_keypad_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); + if(keypad_obj == NULL) + { + keypad_obj = m_new_obj_with_finaliser(machine_keypad_obj_t); + } + machine_keypad_obj_t *self = keypad_obj; + self->base.type = &machine_keypad_type; + return MP_OBJ_FROM_PTR(self); +} + +#endif +#endif /* MICROPY_PY_KEYPAD && PLAT_ASR */ diff --git a/ports/quectel/core/source/machine_lcd.c b/ports/quectel/core/source/machine_lcd.c index 4ef19bb..7705d2b 100644 --- a/ports/quectel/core/source/machine_lcd.c +++ b/ports/quectel/core/source/machine_lcd.c @@ -101,6 +101,9 @@ STATIC mp_obj_t machine_lcd_brightness(mp_obj_t self_in, mp_obj_t data) return mp_obj_new_int(-1); } ret = Helios_LCD_Brightness(bright_level); + if(ret == 1001) { + mp_raise_ValueError("The platform does not support LCD backlight adjustment"); + } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_lcd_brightness_obj, machine_lcd_brightness); @@ -327,6 +330,56 @@ STATIC mp_obj_t machine_lcd_make_new(const mp_obj_type_t *type, size_t n_args, s return MP_OBJ_FROM_PTR(self_lcd); } +enum { + FORMAT_BIN, + FORMAT_JPEG, + FORMAT_JPG, + FORMAT_MAX, +}; + + +STATIC int check_format(char *path) { + if(path == NULL) return -1; + + if(strlen(path) < 1) { + return -2; + } + + char *st_old = NULL; + char *st_now = NULL; + + int is_first = 1; + while(1) { + if(is_first == 1) { + is_first = 0; + st_now = strchr(path, '.'); + } else { + st_now = strchr(st_now+1, '.'); + } + if(st_now != NULL){ + st_old = st_now+1; + } else { + break; + } + } + if(st_old == NULL) return -1; + + if(strncmp(st_old, "bin", 3)==0){ + return FORMAT_BIN; + } else if(strncmp(st_old, "jpeg", 4)==0) { + return FORMAT_JPEG; + }else if(strncmp(st_old, "jpg", 3)==0) { + return FORMAT_JPG; + } else { + return -1; + } +} + +#define CHECK_IS_JPEG(x) (check_format(x) == FORMAT_JPEG) +#define CHEKC_IS_BIN(x) (check_format(x) == FORMAT_BIN) +#define CHEKC_IS_JPG(x) (check_format(x) == FORMAT_JPG) + + static int Helios_lcd_write_data_by_file(char* file_name, unsigned int start_x, unsigned int start_y) { HeliosFILE *fileID = NULL; @@ -423,79 +476,99 @@ static int Helios_lcd_write_data_by_file_wh(char* file_name, unsigned int start_ return ret; } -STATIC mp_obj_t machine_lcd_show_data(size_t n_args, const mp_obj_t *args) -{ -#if 1 - int ret = 0; - int start_x = 0; - int start_y = 0; - int width = 0; - int hight = 0; - //machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]); - char *file_name = (char*)mp_obj_str_get_str(args[1]); - start_x = mp_obj_get_int(args[2]); - start_y = mp_obj_get_int(args[3]); - if(n_args == 4) { - ret = Helios_lcd_write_data_by_file(file_name,start_x,start_y); - } else if(n_args == 6) { - width = mp_obj_get_int(args[4]); - hight = mp_obj_get_int(args[5]); - ret = Helios_lcd_write_data_by_file_wh(file_name,start_x,start_y,width,hight); - } else { - mp_raise_ValueError("wrong number of parameters"); - } + +#ifdef CONFIG_JPEG +STATIC int quec_lcd_show_jpeg(char *file_name, uint32_t start_x, uint32_t start_y){ + char name[256] = {0}; + rgb_struct lcd_data = {0}; + int ret = 0; + uint32_t end_x = 0; + uint32_t end_y = 0; + + sprintf(name, "U:/%s",file_name); + ret = JPEG2RGB565(name,&lcd_data); if(ret != 0) { - return mp_obj_new_int(-1); + LCD_LOG("JPEG2RGB565 fail ret = %d\n",ret); + return (-1); } -#endif - return mp_obj_new_int(0); + + end_x = start_x + lcd_data.width-1; + end_y = start_y + lcd_data.height -1; + + ret = Helios_LCD_Write(lcd_data.buf, start_x, start_y, end_x, end_y); + if(lcd_data.buf) { + free(lcd_data.buf); + } + return ret; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_obj, 4, 6, machine_lcd_show_data); -#ifdef CONFIG_JPEG STATIC mp_obj_t machine_lcd_show_jpeg(size_t n_args, const mp_obj_t *args) { int ret = 0; int start_x = 0; int start_y = 0; - int end_x = 0; - int end_y = 0; start_x = mp_obj_get_int(args[2]); start_y = mp_obj_get_int(args[3]); //machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]); char *file_name = (char*)mp_obj_str_get_str(args[1]); - - char name[256] = {0}; - sprintf(name, "U:/%s",file_name); - - rgb_struct lcd_data = {0}; - ret = JPEG2RGB565(name,&lcd_data); - - LCD_LOG("JPEG2RGB565 ret = %d\n",ret); - - if(ret != 0) return mp_obj_new_int(ret); - - end_x = start_x + lcd_data.width-1; - end_y = start_y + lcd_data.height -1; + if(!CHECK_IS_JPEG(file_name) && !CHEKC_IS_JPG(file_name)) { + mp_raise_ValueError("This kind of picture format is not supported at present"); + } - ret = Helios_LCD_Write(lcd_data.buf, start_x, start_y, end_x, end_y); + ret = quec_lcd_show_jpeg(file_name, start_x, start_y); - if(lcd_data.buf) { - free(lcd_data.buf); - } - return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_jpeg_obj, 4, 4, machine_lcd_show_jpeg); #endif +STATIC mp_obj_t machine_lcd_show_data(size_t n_args, const mp_obj_t *args) +{ + + int ret = 0; + int start_x = 0; + int start_y = 0; + int width = 0; + int hight = 0; + //machine_lcd_obj_t *self = MP_OBJ_TO_PTR(args[0]); + char *file_name = (char*)mp_obj_str_get_str(args[1]); + start_x = mp_obj_get_int(args[2]); + start_y = mp_obj_get_int(args[3]); + if(CHEKC_IS_BIN(file_name)) { + if(n_args == 4) { + ret = Helios_lcd_write_data_by_file(file_name,start_x,start_y); + } else if(n_args == 6) { + width = mp_obj_get_int(args[4]); + hight = mp_obj_get_int(args[5]); + ret = Helios_lcd_write_data_by_file_wh(file_name,start_x,start_y,width,hight); + } else { + mp_raise_ValueError("wrong number of parameters"); + } + } +#ifdef CONFIG_JPEG + else if(CHECK_IS_JPEG(file_name) || CHEKC_IS_JPG(file_name)) { + ret = quec_lcd_show_jpeg(file_name, start_x, start_y); + } +#endif + else { + mp_raise_ValueError("This kind of picture format is not supported at present"); + } + + if(ret != 0) { + return mp_obj_new_int(-1); + } + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lcd_show_obj, 4, 6, machine_lcd_show_data); + + STATIC const mp_rom_map_elem_t lcd_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_lcd_init), MP_ROM_PTR(&machine_lcd_init_obj) }, diff --git a/ports/quectel/core/source/machine_nandflash.c b/ports/quectel/core/source/machine_nandflash.c index 2c282aa..dbd19e6 100644 --- a/ports/quectel/core/source/machine_nandflash.c +++ b/ports/quectel/core/source/machine_nandflash.c @@ -82,11 +82,11 @@ STATIC mp_obj_t machine_nandflash_make_new(const mp_obj_type_t *type, size_t n_a -#define FILE_OPEN_FLAGS_R (YAFFS_RDONLY) -#define FILE_OPEN_FLAGS_W (YAFFS_WRONLY | YAFFS_CREAT | YAFFS_TRUNC) -#define FILE_OPEN_FLAGS_A (YAFFS_WRONLY | YAFFS_CREAT | YAFFS_APPEND) -#define FILE_OPEN_FLAGS_RPluse (YAFFS_RDWR) -#define FILE_OPEN_FLAGS_WPluse (YAFFS_RDWR | YAFFS_CREAT | YAFFS_TRUNC) +#define FILE_OPEN_FLAGS_R (YAFFS_RDONLY) +#define FILE_OPEN_FLAGS_W (YAFFS_WRONLY | YAFFS_CREAT | YAFFS_TRUNC) +#define FILE_OPEN_FLAGS_A (YAFFS_WRONLY | YAFFS_CREAT | YAFFS_APPEND) +#define FILE_OPEN_FLAGS_RPluse (YAFFS_RDWR) +#define FILE_OPEN_FLAGS_WPluse (YAFFS_RDWR | YAFFS_CREAT | YAFFS_TRUNC) #define FILE_OPEN_FLAGS_APluse (YAFFS_RDWR | YAFFS_CREAT | YAFFS_APPEND) static int Helios_file_open_mode2flags(const char * mode) diff --git a/ports/quectel/core/source/machine_pin.c b/ports/quectel/core/source/machine_pin.c index de2f291..2dd43fe 100644 --- a/ports/quectel/core/source/machine_pin.c +++ b/ports/quectel/core/source/machine_pin.c @@ -25,9 +25,11 @@ #include "helios_gpio.h" #include "helios_debug.h" -#define HELIOS_PIN_LOG(msg, ...) custom_log("machine pin", msg, ##__VA_ARGS__) +#define HELIOS_PIN_LOG(msg, ...) custom_log("machine_pin", msg, ##__VA_ARGS__) //#define HELIOS_PIN_LOG(msg, ...) QL_LOG_PUSH("machine pin", msg, ##__VA_ARGS__) +#define GPIO_OBJ_DEF(n) {{&machine_pin_type}, HELIOS_GPIO##n, 0, 0, 0} +#define PLAT_GPIO_OBJ_DEF(n) BOOST_PP_REPEAT_1(n,GPIO_OBJ_DEF) typedef struct _machine_pin_obj_t { @@ -41,122 +43,7 @@ typedef struct _machine_pin_obj_t { const mp_obj_type_t machine_pin_type; -enum { - GPIO0 = 0, - GPIO1, - GPIO2, - GPIO3, - GPIO4, - GPIO5, - GPIO6, - GPIO7, - GPIO8, - GPIO9, - GPIO10, - GPIO11, - GPIO12, - GPIO13, - GPIO14, - GPIO15, - GPIO16, - GPIO17, - GPIO18, - GPIO19, - GPIO20, - GPIO21, - GPIO22, - GPIO23, - GPIO24, - GPIO25, - GPIO26, - GPIO27, - GPIO28, - GPIO29, - GPIO30, - GPIO31, - GPIOMAX, -}; - -const mp_obj_type_t machine_pin_type; - -struct pin_map_t{ - int export_pin; - int internal_pin; -}; - -static struct pin_map_t pin_map[] = { - {GPIO0,HELIOS_GPIO0}, - {GPIO1,HELIOS_GPIO1}, - {GPIO2,HELIOS_GPIO2}, - {GPIO3,HELIOS_GPIO3}, - {GPIO4,HELIOS_GPIO4}, - {GPIO5,HELIOS_GPIO5}, - {GPIO6,HELIOS_GPIO6}, - {GPIO7,HELIOS_GPIO7}, - {GPIO8,HELIOS_GPIO8}, - {GPIO9,HELIOS_GPIO9}, - {GPIO10,HELIOS_GPIO10}, - {GPIO11,HELIOS_GPIO11}, - {GPIO12,HELIOS_GPIO12}, - {GPIO13,HELIOS_GPIO13}, - {GPIO14,HELIOS_GPIO14}, - {GPIO15,HELIOS_GPIO15}, - {GPIO16,HELIOS_GPIO16}, - {GPIO17,HELIOS_GPIO17}, - {GPIO18,HELIOS_GPIO18}, - {GPIO19,HELIOS_GPIO19}, - {GPIO20,HELIOS_GPIO20}, - {GPIO21,HELIOS_GPIO21}, - {GPIO22,HELIOS_GPIO22}, - {GPIO23,HELIOS_GPIO23}, - {GPIO24,HELIOS_GPIO24}, - {GPIO25,HELIOS_GPIO25}, - {GPIO26,HELIOS_GPIO26}, - {GPIO27,HELIOS_GPIO27}, - {GPIO28,HELIOS_GPIO28}, - {GPIO29,HELIOS_GPIO29}, - {GPIO30,HELIOS_GPIO30}, - {GPIO31,HELIOS_GPIO31}, - {GPIOMAX,HELIOS_GPIOMAX}, - -}; - - - -STATIC machine_pin_obj_t machine_pin_obj[HELIOS_GPIOMAX] = { - {{&machine_pin_type}, HELIOS_GPIO0, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO1, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO2, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO3, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO4, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO5, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO6, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO7, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO8, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO9, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO10, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO11, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO12, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO13, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO14, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO15, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO16, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO17, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO18, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO19, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO20, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO21, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO22, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO23, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO24, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO25, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO26, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO27, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO28, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO29, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO30, 0, 0, 0}, - {{&machine_pin_type}, HELIOS_GPIO31, 0, 0, 0}, -}; +STATIC machine_pin_obj_t *machine_pin_obj[PLAT_GPIO_NUM] = {NULL}; STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -231,28 +118,24 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, Helios_Debug_Enable(); // get the wanted pin object - unsigned int i = 0; - int tmp_pin = 0,wanted_pin = -1; - tmp_pin = mp_obj_get_int(args[0]); - //gpio map from export to inter - for (i=0;i< sizeof(pin_map);i++){ - if(pin_map[i].export_pin == tmp_pin){ - wanted_pin=pin_map[i].internal_pin; - break; - } - } - if(wanted_pin == -1) { + //unsigned int i = 0; + int wanted_pin = 0; + wanted_pin = mp_obj_get_int(args[0]); + + if(wanted_pin == 0 || wanted_pin > PLAT_GPIO_NUM) { mp_raise_ValueError("invalid pin"); } HELIOS_PIN_LOG("wanted_pin = %d\n",wanted_pin); machine_pin_obj_t *self = NULL; - if (HELIOS_GPIO0 <= wanted_pin && wanted_pin < HELIOS_GPIOMAX) { - self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin]; - } - if (self == NULL || self->base.type == NULL) { - mp_raise_ValueError("invalid pin"); - } + + if (machine_pin_obj[wanted_pin-1] == NULL) + { + machine_pin_obj[wanted_pin-1] = m_new_obj_with_finaliser(machine_pin_obj_t); + } + self = machine_pin_obj[wanted_pin-1]; + self->base.type = &machine_pin_type; + self->pin = wanted_pin; // default settings self->dir = HELIOS_GPIO_OUTPUT; @@ -352,14 +235,57 @@ STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ return -1; } +STATIC mp_obj_t machine_pin_set_dir(mp_obj_t self_in, mp_obj_t dir) +{ + machine_pin_obj_t *self = self_in; + int ret = -1; + + int pin_value = mp_obj_get_int(dir); + if((pin_value != HELIOS_GPIO_INPUT) && (pin_value != HELIOS_GPIO_OUTPUT)){ + mp_raise_ValueError("Invalid direction parameter"); + } + ret = Helios_GPIO_SetDirection((Helios_GPIONum) self->pin, (Helios_GPIODir) pin_value); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_pin_set_dir_obj, machine_pin_set_dir); + +STATIC mp_obj_t machine_pin_get_dir(mp_obj_t self_in) +{ + machine_pin_obj_t *self = self_in; + int ret = Helios_GPIO_GetDirection((Helios_GPIONum) self->pin); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_get_dir_obj, machine_pin_get_dir); + + +STATIC mp_obj_t machine_pin_deinit(mp_obj_t self_in) { + machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in); + //HELIOS_PIN_LOG("machine pin deinit.pin=%d.\r\n", self->pin); + + machine_pin_obj[self->pin - 1] = NULL; + + int ret = Helios_GPIO_Deinit((Helios_GPIONum)self->pin); + if (ret != 0) + { + HELIOS_PIN_LOG("GPIO%d deinit failed.\r\n", self->pin); + } + return mp_obj_new_int(ret); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_deinit_obj, machine_pin_deinit); + + STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { // instance methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_pin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_off_obj) }, { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_pin_write_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_pin_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_dir), MP_ROM_PTR(&machine_pin_set_dir_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_dir), MP_ROM_PTR(&machine_pin_get_dir_obj) }, // class constants //GPIO DEFINE { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(HELIOS_GPIO_INPUT) }, @@ -367,39 +293,7 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_PULL_PU), MP_ROM_INT(HELIOS_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_PD), MP_ROM_INT(HELIOS_PULL_DOWN) }, { MP_ROM_QSTR(MP_QSTR_PULL_DISABLE), MP_ROM_INT(HELIOS_PULL_NONE) }, - { MP_ROM_QSTR(MP_QSTR_GPIO0), MP_ROM_INT(HELIOS_GPIO0) }, - { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, - { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_INT(HELIOS_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_INT(HELIOS_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, - { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_INT(HELIOS_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_INT(HELIOS_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_INT(HELIOS_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_INT(HELIOS_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, -#if defined(PLAT_ASR) - { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_GPIO20), MP_ROM_INT(HELIOS_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_GPIO21), MP_ROM_INT(HELIOS_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_GPIO22), MP_ROM_INT(HELIOS_GPIO22) }, - { MP_ROM_QSTR(MP_QSTR_GPIO23), MP_ROM_INT(HELIOS_GPIO23) }, - { MP_ROM_QSTR(MP_QSTR_GPIO24), MP_ROM_INT(HELIOS_GPIO24) }, - { MP_ROM_QSTR(MP_QSTR_GPIO25), MP_ROM_INT(HELIOS_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_GPIO26), MP_ROM_INT(HELIOS_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_GPIO27), MP_ROM_INT(HELIOS_GPIO27) }, - { MP_ROM_QSTR(MP_QSTR_GPIO28), MP_ROM_INT(HELIOS_GPIO28) }, - { MP_ROM_QSTR(MP_QSTR_GPIO29), MP_ROM_INT(HELIOS_GPIO29) }, - { MP_ROM_QSTR(MP_QSTR_GPIO30), MP_ROM_INT(HELIOS_GPIO30) }, -#endif + PLAT_GPIO_DEF(PLAT_GPIO_NUM), }; STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); diff --git a/ports/quectel/core/source/machine_rtc.c b/ports/quectel/core/source/machine_rtc.c index d3d381d..9ce24fe 100644 --- a/ports/quectel/core/source/machine_rtc.c +++ b/ports/quectel/core/source/machine_rtc.c @@ -26,27 +26,36 @@ //#include "timeutils.h" #include "modmachine.h" - +#include "helios_debug.h" #include "helios_rtc.h" +#define HELIOS_RTC_LOG(fmt, ...) custom_log(machine_rtc, fmt, ##__VA_ARGS__) + + typedef struct _machine_rtc_obj_t { mp_obj_base_t base; } machine_rtc_obj_t; -static mp_obj_t callback_cur = NULL; +static c_callback_t *callback_cur = NULL; // singleton RTC object -STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; +//STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; +STATIC machine_rtc_obj_t *machine_rtc_obj_ptr = NULL; STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return constant object - return (mp_obj_t)&machine_rtc_obj; + if (machine_rtc_obj_ptr != NULL) + { + // singleton RTC object + return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); + } + machine_rtc_obj_ptr = m_new_obj_with_finaliser(machine_rtc_obj_t); + machine_rtc_obj_ptr->base.type = &machine_rtc_type; + return MP_OBJ_FROM_PTR(machine_rtc_obj_ptr); } @@ -151,14 +160,15 @@ void rtc_callback_to_python(void) return; } - if(mp_obj_is_callable(callback_cur)){ - mp_sched_schedule(callback_cur, NULL); - } + mp_sched_schedule_ex(callback_cur, NULL); } STATIC mp_obj_t machine_rtc_register_callback(mp_obj_t self_in, mp_obj_t callback) { - callback_cur = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + callback_cur = &cb; + mp_sched_schedule_callback_register(callback_cur, callback); int ret = Helios_RTC_Register_cb(rtc_callback_to_python); @@ -175,8 +185,18 @@ STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); +STATIC mp_obj_t machine_rtc_deinit(mp_obj_t self_in) { + HELIOS_RTC_LOG("machine rtc deinit.\r\n"); + callback_cur = NULL; + machine_rtc_obj_ptr = NULL; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rtc_deinit_obj, machine_rtc_deinit); + + STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_rtc_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, { MP_ROM_QSTR(MP_QSTR_set_alarm), MP_ROM_PTR(&machine_rtc_set_alarm_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_alarm), MP_ROM_PTR(&machine_rtc_enable_alarm_obj) }, diff --git a/ports/quectel/core/source/machine_timer.c b/ports/quectel/core/source/machine_timer.c index 0c3efd1..a2c6d19 100644 --- a/ports/quectel/core/source/machine_timer.c +++ b/ports/quectel/core/source/machine_timer.c @@ -54,7 +54,7 @@ typedef struct _machine_timer_obj_t { //ONE_SHOT OR PERIODIC mp_uint_t mode; mp_uint_t period; - mp_obj_t callback; + c_callback_t callback; mp_int_t timer_id; mp_int_t timer_id_real; MP_TIMER_STATUS timer_status; @@ -63,6 +63,8 @@ typedef struct _machine_timer_obj_t { } machine_timer_obj_t; STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)(print); + (void)(kind); machine_timer_obj_t *self = self_in; HELIOS_TIMER_LOG("period=%d\r\n", self->period); HELIOS_TIMER_LOG("timer_id=%d\r\n", self->timer_id); @@ -71,16 +73,12 @@ STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_pr STATIC void machine_timer_isr(UINT32 self_in) { - //HELIOS_TIMER_LOG("timer cb1,self_in=%#X\r\n",self_in); - machine_timer_obj_t *self = (void*)self_in; - - if((self!=NULL )&& (mp_obj_is_callable(self->callback))) + + if(self != NULL) { - //HELIOS_TIMER_LOG("timer mp_obj_is_callable"); - mp_sched_schedule(self->callback, self); + mp_sched_schedule_ex(&self->callback, self); } - // mp_hal_wake_main_task_from_isr(); } @@ -124,16 +122,25 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n } self->mode = args[ARG_mode].u_int; - self->callback = args[ARG_callback].u_obj; + + mp_sched_schedule_callback_register(&self->callback, args[ARG_callback].u_obj); - HELIOS_TIMER_LOG("mode: %d, period: %d,callback:%#X\r\n", self->mode, self->period,self->callback); + HELIOS_TIMER_LOG("mode: %d, period: %d,callback:%#X\r\n", self->mode, self->period,self->callback.cb); // Check whether the timer is already running, if so return 0 if (MP_TIMER_RUNNING == self->timer_status) { return mp_obj_new_int(0); } - - int timer = Helios_Timer_init( (void* )machine_timer_isr, self); + + int timer = 0; + if(0 == self->timer_id_real) + { + timer = Helios_Timer_init( (void* )machine_timer_isr, self); + } + else + { + timer = self->timer_id_real; + } if(!timer) { return mp_const_false; @@ -164,6 +171,7 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + (void)(type); mp_int_t timer_id=0; if (n_args > 0) { @@ -187,6 +195,7 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); self->base.type = &machine_timer_type; self->timer_id = timer_id; + self->timer_id_real = 0; self->timer_status = MP_TIMER_CREATED; if (n_args > 0 || n_kw > 0) { @@ -211,17 +220,29 @@ STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); +STATIC mp_obj_t machine_timer_stop(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if(self->timer_id_real) + { + HELIOS_TIMER_LOG("machine_timer_stop (%#X) \r\n",self->timer_id_real); + Helios_Timer_Stop(self->timer_id_real); + self->timer_status = MP_TIMER_STOP; + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_stop_obj, machine_timer_stop); STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { - int ret=0; machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - HELIOS_TIMER_LOG("timer deinit: id (%#X) \r\n",self->timer_id_real); if(self->timer_id_real) { - HELIOS_TIMER_LOG("timer Helios_Timer_Deinit (%#X) \r\n",self->timer_id_real); + HELIOS_TIMER_LOG("machine_timer_deinit (%#X) \r\n",self->timer_id_real); + Helios_Timer_Stop(self->timer_id_real); Helios_Timer_Deinit(self->timer_id_real); self->timer_id_real = 0; self->timer_status = MP_TIMER_STOP; @@ -260,7 +281,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_timer_initialize_obj, machine_timer_ini STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&machine_timer_initialize_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_timer_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_timer_init_obj) }, // { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_timer_value_obj) }, { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_AUTO_DELETE) }, diff --git a/ports/quectel/core/source/machine_uart.c b/ports/quectel/core/source/machine_uart.c index dfb33ba..20f2d99 100644 --- a/ports/quectel/core/source/machine_uart.c +++ b/ports/quectel/core/source/machine_uart.c @@ -22,7 +22,10 @@ #include "stream.h" #include "mperrno.h" +#include "mphalport.h" #include "helios_uart.h" +#include "helios_pin.h" + typedef struct _machine_uart_obj_t { mp_obj_base_t base; @@ -30,9 +33,9 @@ typedef struct _machine_uart_obj_t { Helios_UARTConfig config; } machine_uart_obj_t; -static mp_obj_t callback_cur[4] = {0}; +static c_callback_t *callback_cur[4] = {0}; -machine_uart_obj_t uart_self_obj[HELIOS_UARTMAX] = {0}; +static machine_uart_obj_t *uart_self_obj[HELIOS_UARTMAX] = {0}; const mp_obj_type_t machine_uart_type; @@ -63,8 +66,6 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co // get baudrate bits switch (args[ARG_baudrate].u_int) { - case 0: - break; case HELIOS_UART_BAUD_300: case HELIOS_UART_BAUD_600: case HELIOS_UART_BAUD_1200: @@ -106,8 +107,6 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co } #else switch (args[ARG_bits].u_int) { - case 0: - break; case 5: self->config.data_bit = HELIOS_UART_DATABIT_5; break; @@ -127,8 +126,6 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co #endif // get parity bits switch (args[ARG_parity].u_int) { - case -1: - break; case 0: self->config.parity_bit = HELIOS_UART_PARITY_NONE; break; @@ -145,10 +142,6 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co // get stop bits switch (args[ARG_stop].u_int) { - case -1: - break; - case 0: - break; case 1: self->config.stop_bit = HELIOS_UART_STOP_1; break; @@ -162,8 +155,6 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co // get flow bits switch (args[ARG_flow].u_int) { - case -1: - break; case 0: self->config.flow_ctrl = HELIOS_UART_FC_NONE; break; @@ -179,9 +170,13 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co uart_para.uart_config = &uart_config; memcpy((void*)&uart_config,(void*)&self->config, sizeof(Helios_UARTConfig)); - + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(0); + } + + Helios_UART_Deinit((Helios_UARTNum) self->uart_num); if(Helios_UART_Init((Helios_UARTNum) self->uart_num, &uart_para) != 0) { - mp_raise_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", self->uart_num); + mp_raise_msg_varg(&mp_type_ValueError, "UART(%d) init fail", self->uart_num); } } @@ -195,7 +190,11 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, } // create instance - machine_uart_obj_t *self = (machine_uart_obj_t*)&uart_self_obj[uart_num]; + if (uart_self_obj[uart_num] == NULL) + { + uart_self_obj[uart_num] = m_new_obj_with_finaliser(machine_uart_obj_t); + } + machine_uart_obj_t *self = uart_self_obj[uart_num]; self->base.type = &machine_uart_type; self->uart_num = uart_num; @@ -222,6 +221,9 @@ STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); int ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(1); + } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); @@ -235,6 +237,20 @@ 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) +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); + if ( !(mp_obj_is_small_int(gpio_n) && mp_obj_is_small_int(direc)) ){ + return mp_obj_new_int(ret); + } + size_t gpio = mp_obj_get_int(gpio_n); + Helios_UART_Direc dire = (Helios_UART_Direc)mp_obj_get_int(direc); + ret = Helios_UART_SetCtl_485(self->uart_num,gpio,dire); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_uart_485_control_obj, machine_uart_485_control); +#endif /* STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) { @@ -259,48 +275,69 @@ void helios_uart_callback_to_python(uint64_t ind_type, Helios_UARTNum port, uint if(callback_cur[port] == NULL) { return; } - if(mp_obj_is_callable(callback_cur[port])){ - mp_sched_schedule(callback_cur[port], MP_OBJ_FROM_PTR(mp_obj_new_list(3, decode_cb))); - } + + mp_sched_schedule_ex(callback_cur[port], MP_OBJ_FROM_PTR(mp_obj_new_list(3, decode_cb))); } STATIC mp_obj_t helios_uart_set_callback(mp_obj_t self_in, mp_obj_t callback) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - callback_cur[self->uart_num] = callback; + static c_callback_t cb[sizeof(callback_cur) / sizeof(callback_cur[0])] = {0}; + memset(&cb[self->uart_num], 0, sizeof(c_callback_t)); + callback_cur[self->uart_num] = &cb[self->uart_num]; + mp_sched_schedule_callback_register(callback_cur[self->uart_num], callback); int ret = Helios_UART_SetCallback((Helios_UARTNum) self->uart_num, (Helios_UARTCallback) helios_uart_callback_to_python); return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_set_callback_obj, helios_uart_set_callback); +STATIC mp_obj_t helios_uart_deinit(mp_obj_t self_in) +{ + int ret = 0; + + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uart_self_obj[self->uart_num] = NULL; + callback_cur[self->uart_num] = NULL; + ret = Helios_UART_Deinit((Helios_UARTNum) self->uart_num); + + if(self->uart_num == QPY_REPL_UART) { + mp_hal_port_open(1); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(helios_uart_deinit_obj, helios_uart_deinit); STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&helios_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&machine_uart_set_callback_obj) }, - // { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - // { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - // { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, + // { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, #if defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, #endif #if defined (PLAT_ASR) - { MP_ROM_QSTR(MP_QSTR_UART0), MP_ROM_INT(HELIOS_UART0) }, + { 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_RDA) { MP_ROM_QSTR(MP_QSTR_UART1), MP_ROM_INT(HELIOS_UART1) }, { MP_ROM_QSTR(MP_QSTR_UART2), MP_ROM_INT(HELIOS_UART2) }, { MP_ROM_QSTR(MP_QSTR_UART3), MP_ROM_INT(HELIOS_UART3) }, #endif - //{ MP_ROM_QSTR(MP_QSTR_UART4), MP_ROM_INT(HELIOS_UART4) }, - // { MP_ROM_QSTR(MP_QSTR_UART5), MP_ROM_INT(HELIOS_UART5) }, }; STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); diff --git a/ports/quectel/core/source/machine_wdt.c b/ports/quectel/core/source/machine_wdt.c index c6ef358..abb2d18 100644 --- a/ports/quectel/core/source/machine_wdt.c +++ b/ports/quectel/core/source/machine_wdt.c @@ -37,12 +37,14 @@ typedef struct _machine_wdt_obj_t int period; }machine_wdt_obj_t; +STATIC machine_wdt_init_t machine_wdt_obj = {0}; + STATIC mp_obj_t machine_wdt_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, 1, true); - - machine_wdt_init_t *self = m_new_obj(machine_wdt_init_t); + + machine_wdt_init_t *self = &machine_wdt_obj; machine_wdt_obj_t info = {0}; self->base.type = &machine_wdt_type; if (n_args > 0) @@ -51,7 +53,7 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, s --n_args; ++args; } - + Helios_WDT_Deinit(); if(0 != Helios_WDT_Init((uint64_t) info.period)) { return mp_const_false; } diff --git a/ports/quectel/core/source/misc_adc.c b/ports/quectel/core/source/misc_adc.c index 69d9094..2550ae7 100644 --- a/ports/quectel/core/source/misc_adc.c +++ b/ports/quectel/core/source/misc_adc.c @@ -128,9 +128,11 @@ STATIC const mp_rom_map_elem_t misc_adc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&Helios_adc_read_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&Helios_adc_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_INT(ADC0) }, +#if !defined(PLAT_Qualcomm) { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_INT(ADC1) }, { MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_INT(ADC2) }, { MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_INT(ADC3) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(misc_adc_locals_dict, misc_adc_locals_dict_table); diff --git a/ports/quectel/core/source/misc_power.c b/ports/quectel/core/source/misc_power.c index 69ed851..5d64f7a 100644 --- a/ports/quectel/core/source/misc_power.c +++ b/ports/quectel/core/source/misc_power.c @@ -31,7 +31,7 @@ STATIC mp_obj_t misc_power_reset() { int ret = 1; Helios_Power_Reset(ret); - return mp_const_true; + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_power_reset_obj, misc_power_reset); @@ -40,19 +40,20 @@ STATIC mp_obj_t misc_power_down() { int ret = 1; Helios_Power_Down(ret); - return mp_const_true; + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_power_down_obj, misc_power_down); - STATIC mp_obj_t misc_power_get_down_reason() { int ret; ret = Helios_Power_GetDownReason(); return mp_obj_new_int(ret); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_down_reason_obj, misc_power_get_down_reason); +#if !defined(PLAT_RDA) +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_down_reason_obj, misc_power_get_down_reason); +#endif STATIC mp_obj_t misc_power_get_up_reason() { @@ -71,13 +72,14 @@ STATIC mp_obj_t misc_power_get_batt() } STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_power_get_batt_obj, misc_power_get_batt); - STATIC const mp_rom_map_elem_t misc_power_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, { MP_ROM_QSTR(MP_QSTR_powerRestart), MP_ROM_PTR(&misc_power_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_powerDown), MP_ROM_PTR(&misc_power_down_obj) }, { MP_ROM_QSTR(MP_QSTR_powerOnReason), MP_ROM_PTR(&misc_power_get_up_reason_obj) }, +#if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_powerDownReason), MP_ROM_PTR(&misc_power_get_down_reason_obj) }, +#endif { MP_ROM_QSTR(MP_QSTR_getVbatt), MP_ROM_PTR(&misc_power_get_batt_obj) }, }; diff --git a/ports/quectel/core/source/misc_powerkey.c b/ports/quectel/core/source/misc_powerkey.c index db56f5e..59e2593 100644 --- a/ports/quectel/core/source/misc_powerkey.c +++ b/ports/quectel/core/source/misc_powerkey.c @@ -15,6 +15,7 @@ */ #include +#include #include "runtime.h" #include "helios_power.h" #include "helios_debug.h" @@ -26,15 +27,17 @@ typedef struct _misc_powerkey_obj_t { mp_obj_base_t base; } misc_powerkey_obj_t; +STATIC misc_powerkey_obj_t *powerkey_obj = NULL; -STATIC mp_obj_t g_user_callback = NULL; + +STATIC c_callback_t *g_user_callback = NULL; STATIC void powerkey_event_callback(uint8_t status) { if(g_user_callback) { MOD_POWERKEY_LOG("powerkey event callback, status = %d\r\n", status); - mp_sched_schedule(g_user_callback, mp_obj_new_int(status)); + mp_sched_schedule_ex(g_user_callback, mp_obj_new_int(status)); } } @@ -43,7 +46,10 @@ STATIC mp_obj_t powerkey_event_register(mp_obj_t self_in, mp_obj_t usr_callback) int ret = 1; Helios_PowerInitStruct info = {powerkey_event_callback}; - g_user_callback = usr_callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_user_callback = &cb; + mp_sched_schedule_callback_register(g_user_callback, usr_callback); MOD_POWERKEY_LOG("powerkey_event_register\r\n"); ret = Helios_Power_Init(&info); @@ -51,8 +57,21 @@ STATIC mp_obj_t powerkey_event_register(mp_obj_t self_in, mp_obj_t usr_callback) } STATIC MP_DEFINE_CONST_FUN_OBJ_2(misc_powerkey_event_register_obj, powerkey_event_register); +STATIC mp_obj_t misc_powerkey_deinit(mp_obj_t self_in) +{ + int ret = -1; + g_user_callback = NULL; + powerkey_obj = NULL; + ret = Helios_Power_DeInit(); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_powerkey__del__obj, misc_powerkey_deinit); + + STATIC const mp_rom_map_elem_t misc_powerkey_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&misc_powerkey__del__obj) }, { MP_ROM_QSTR(MP_QSTR_powerKeyEventRegister), MP_ROM_PTR(&misc_powerkey_event_register_obj) }, }; STATIC MP_DEFINE_CONST_DICT(misc_powerkey_locals_dict, misc_powerkey_locals_dict_table); @@ -68,7 +87,13 @@ const mp_obj_type_t misc_powerkey_type = { STATIC mp_obj_t misc_powerkey_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - misc_powerkey_obj_t *self = m_new_obj(misc_powerkey_obj_t); + misc_powerkey_obj_t *self = NULL; + if(powerkey_obj == NULL) + { + powerkey_obj = m_new_obj_with_finaliser(misc_powerkey_obj_t); + } + + self = powerkey_obj; self->base.type = &misc_powerkey_type; return MP_OBJ_FROM_PTR(self); } diff --git a/ports/quectel/core/source/misc_pwm.c b/ports/quectel/core/source/misc_pwm.c index 9b0440c..507fd09 100644 --- a/ports/quectel/core/source/misc_pwm.c +++ b/ports/quectel/core/source/misc_pwm.c @@ -35,6 +35,7 @@ typedef enum PWM1 = 1, PWM2 = 2, PWM3 = 3, + PWMMAX, }PWMn; @@ -54,6 +55,8 @@ typedef enum HELIOS_PWM_CYCLE_RANGE_ENUM HELIOS_PWM_CYCLE_ABOVE_BELOW_US, } HELIOS_PWM_CYCLE_RANGE_E; +STATIC misc_pwm_obj_t *misc_pwm_obj[PWMMAX] = {NULL}; + STATIC void misc_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -103,14 +106,23 @@ 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, 1, MP_OBJ_FUN_ARGS_MAX, true); + 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]); PWM_LOG("n_args = %d\n",n_args); + int pwm_num = pin_id; + if ((pwm_num < 0) || (pwm_num > PWMMAX-1)) + { + mp_raise_ValueError("invalid PWMn value, must be in {0~3}."); + } // create PWM object from the given pin - misc_pwm_obj_t *self = m_new_obj(misc_pwm_obj_t); + if (misc_pwm_obj[pin_id] == NULL) + { + misc_pwm_obj[pin_id] = m_new_obj_with_finaliser(misc_pwm_obj_t); + } + misc_pwm_obj_t *self = misc_pwm_obj[pin_id]; self->base.type = &misc_pwm_type; self->pin = pin_id; self->high_time = 0; @@ -135,17 +147,19 @@ 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); - uint32_t frequency = 0; + double frequency = 0; float duty = 0; if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1US || self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_10US) { - frequency = 1000000 /self->cycle_time; + frequency = 1000000 /(double)self->cycle_time; } else if (self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_1MS) { - frequency = 1000 /self->cycle_time; + frequency = 1000 /(double)self->cycle_time; } else if(self->cycle_range == HELIOS_PWM_CYCLE_ABOVE_BELOW_US) { - frequency = 1000000000 /self->cycle_time; + frequency = 1000000000 /(double)self->cycle_time; } duty = (float)self->high_time / (float)self->cycle_time; + PWM_LOG("misc_pwm_enable = %lf %f\n",frequency, duty); + int ret = Helios_PWM_Start(self->pin, frequency, duty); @@ -166,8 +180,26 @@ STATIC mp_obj_t misc_pwm_disable(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_disable_obj, misc_pwm_disable); +STATIC mp_obj_t misc_pwm_deinit(mp_obj_t self_in) { + misc_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + //PWM_LOG("misc pwm deinit.pwm=%d.\r\n", self->pin); + + misc_pwm_obj[self->pin] = NULL; + + int ret = Helios_PWM_Deinit((Helios_PwnNum)self->pin); + if (ret != 0) + { + PWM_LOG("pwm%d deinit failed.\r\n", self->pin); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_pwm_deinit_obj, misc_pwm_deinit); + + STATIC const mp_rom_map_elem_t misc_pwm_locals_dict_table[] = { // { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&misc_pwm_init_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&misc_pwm_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&misc_pwm_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&misc_pwm_disable_obj) }, { MP_ROM_QSTR(MP_QSTR_PWM0), MP_ROM_INT(PWM0) }, diff --git a/ports/quectel/core/source/misc_usb.c b/ports/quectel/core/source/misc_usb.c index 20403e6..6f0cbd6 100644 --- a/ports/quectel/core/source/misc_usb.c +++ b/ports/quectel/core/source/misc_usb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "mpconfigport.h" #include "obj.h" #include "compile.h" @@ -32,7 +33,8 @@ typedef struct _misc_usb_obj_t }misc_usb_obj_t; -static mp_obj_t g_py_callback = NULL; +static c_callback_t *g_py_callback = NULL; +static misc_usb_obj_t *usb_obj = NULL; static void ql_usb_detect_handler(Helios_USB_Status_e status) @@ -40,14 +42,18 @@ static void ql_usb_detect_handler(Helios_USB_Status_e status) if (g_py_callback) { HELIOS_MODUSB_LOG("callback start, status = %u.\r\n", status); - mp_sched_schedule(g_py_callback, mp_obj_new_int(status)); + mp_sched_schedule_ex(g_py_callback, mp_obj_new_int(status)); HELIOS_MODUSB_LOG("callback end.\r\n"); } } STATIC mp_obj_t misc_usb_register_cb(mp_obj_t self_in, mp_obj_t usr_callback) { - g_py_callback = usr_callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_py_callback = &cb; + mp_sched_schedule_callback_register(g_py_callback, usr_callback); + Helios_USBInitStruct info = {ql_usb_detect_handler}; int ret = Helios_USB_Init(&info); return mp_obj_new_int(ret); @@ -62,10 +68,20 @@ STATIC mp_obj_t misc_usb_get_status(mp_obj_t self_in) } STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usb_get_status_obj, misc_usb_get_status); +STATIC mp_obj_t misc_usb__Deint(mp_obj_t self_in) +{ + int ret = -1; + g_py_callback = NULL; + usb_obj = NULL; + ret = Helios_USB_DeInit(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usb__del__obj, misc_usb__Deint); STATIC const mp_rom_map_elem_t misc_usb_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&misc_usb__del__obj) }, { MP_ROM_QSTR(MP_QSTR_getStatus), MP_ROM_PTR(&misc_usb_get_status_obj) }, { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&misc_usb_register_cb_obj) }, }; @@ -84,9 +100,15 @@ const mp_obj_type_t misc_usb_type = { STATIC mp_obj_t misc_usb_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); - - misc_usb_obj_t *self = m_new_obj(misc_usb_obj_t); + misc_usb_obj_t *self = NULL; + + if(usb_obj == NULL) + { + usb_obj = m_new_obj_with_finaliser(misc_usb_obj_t); + } + + self = usb_obj; self->base.type = &misc_usb_type; return MP_OBJ_FROM_PTR(self); -} \ No newline at end of file +} diff --git a/ports/quectel/core/source/misc_usbnet.c b/ports/quectel/core/source/misc_usbnet.c new file mode 100644 index 0000000..43ef4a5 --- /dev/null +++ b/ports/quectel/core/source/misc_usbnet.c @@ -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. + */ + +#include +#include +#include +#include "mpconfigport.h" +#include "obj.h" +#include "compile.h" +#include "runtime.h" +#include "helios_usbnet.h" +#include "helios_debug.h" + +#define HELIOS_MODUSB_LOG(msg, ...) custom_log("modusbnet", msg, ##__VA_ARGS__) + +STATIC mp_obj_t misc_usbnet_set_type(mp_obj_t type_in) +{ + int type = mp_obj_get_int(type_in); + if(type != HELIOS_USBNET_TYPE_ECM && type != HELIOS_USBNET_TYPE_RNDIS) + { + mp_raise_ValueError("USBNET type must be Type_ECM or Type_RNDIS."); + } + int ret = Helios_USBNET_SetType(type); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(misc_usbnet_set_type_obj, misc_usbnet_set_type); + + +STATIC mp_obj_t misc_usbnet_open(void) +{ + int ret = Helios_USBNET_Open(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(misc_usbnet_open_obj, misc_usbnet_open); + + + + +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) }, +}; + +STATIC MP_DEFINE_CONST_DICT(misc_usbnet_locals_dict, misc_usbnet_locals_dict_table); + + +const mp_obj_module_t misc_usbnet_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&misc_usbnet_locals_dict, +}; + diff --git a/ports/quectel/core/source/modaudio.c b/ports/quectel/core/source/modaudio.c index 5d7a5b4..ad435c2 100644 --- a/ports/quectel/core/source/modaudio.c +++ b/ports/quectel/core/source/modaudio.c @@ -31,7 +31,9 @@ STATIC const mp_rom_map_elem_t mp_module_audio_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audio) }, +#if defined(CONFIG_TTS) { MP_ROM_QSTR(MP_QSTR_TTS), MP_ROM_PTR(&audio_tts_type) }, +#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) }, }; diff --git a/ports/quectel/core/source/modaudio.h b/ports/quectel/core/source/modaudio.h index a44f6f5..55aea7b 100644 --- a/ports/quectel/core/source/modaudio.h +++ b/ports/quectel/core/source/modaudio.h @@ -23,7 +23,9 @@ extern "C" { #include "obj.h" +#if defined(CONFIG_TTS) extern const mp_obj_type_t audio_tts_type; +#endif extern const mp_obj_type_t audio_audio_type; extern const mp_obj_type_t audio_record_type; diff --git a/ports/quectel/core/source/modble.c b/ports/quectel/core/source/modble.c index 08dde80..5621008 100644 --- a/ports/quectel/core/source/modble.c +++ b/ports/quectel/core/source/modble.c @@ -27,10 +27,10 @@ #include "helios_debug.h" #include "helios_ble.h" -#define MOD_BLE_LOG(msg, ...) custom_log(ble, msg, ##__VA_ARGS__) +#define MOD_BLE_LOG(msg, ...) custom_log(modble, msg, ##__VA_ARGS__) -static mp_obj_t g_ble_server_callback = NULL; -static mp_obj_t g_ble_client_callback = NULL; +static c_callback_t *g_ble_server_callback = NULL; +static c_callback_t *g_ble_client_callback = NULL; static void qpy_ble_data_print(size_t len, void *data) @@ -86,7 +86,7 @@ static void qpy_ble_server_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_server_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_server_callback, mp_obj_new_tuple(2, tuple)); + mp_sched_schedule_ex(g_ble_server_callback, mp_obj_new_tuple(2, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -121,7 +121,7 @@ static void qpy_ble_server_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_server_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_server_callback, mp_obj_new_tuple(4, tuple)); + mp_sched_schedule_ex(g_ble_server_callback, mp_obj_new_tuple(4, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } @@ -144,7 +144,7 @@ static void qpy_ble_server_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_server_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_server_callback, mp_obj_new_tuple(7, tuple)); + mp_sched_schedule_ex(g_ble_server_callback, mp_obj_new_tuple(7, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -166,7 +166,7 @@ static void qpy_ble_server_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_server_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_server_callback, mp_obj_new_tuple(4, tuple)); + mp_sched_schedule_ex(g_ble_server_callback, mp_obj_new_tuple(4, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } @@ -191,7 +191,7 @@ static void qpy_ble_server_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_server_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_server_callback, mp_obj_new_tuple(7, tuple)); + mp_sched_schedule_ex(g_ble_server_callback, mp_obj_new_tuple(7, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } @@ -235,6 +235,20 @@ STATIC mp_obj_t qpy_ble_get_status(void) } STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_ble_get_status_obj, qpy_ble_get_status); +STATIC mp_obj_t qpy_ble_get_public_addr(void) +{ + int ret = 0; + Helios_BtBleAddr ble_addr = {0}; + ret = Helios_BLE_GetPublic_addr(&ble_addr); + if (ret == 0) + { + return mp_obj_new_bytes(ble_addr.addr, HELIOS_BT_MAC_ADDRESS_SIZE); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_ble_get_public_addr_obj, qpy_ble_get_public_addr); + + #if 0 STATIC mp_obj_t qpy_ble_get_connect_status(mp_obj_t addr) { @@ -289,7 +303,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_ble_gatt_set_local_name_obj, qpy_ble_gatt_s STATIC mp_obj_t qpy_ble_gatt_server_init(mp_obj_t callback) { Helios_BLEInitStruct info = {0}; - g_ble_server_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_ble_server_callback = &cb; + mp_sched_schedule_callback_register(g_ble_server_callback, callback); + info.ble_user_cb = qpy_ble_server_user_callback; int ret = Helios_BLE_GattServerInit(&info); return mp_obj_new_int(ret); @@ -300,6 +318,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ble_gatt_server_init_obj, qpy_ble_gatt_serv STATIC mp_obj_t qpy_ble_gatt_server_release(void) { int ret = 0; + g_ble_server_callback = NULL; ret = Helios_BLE_GattServerRelease(); return mp_obj_new_int(ret); } @@ -657,7 +676,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(2, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(2, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -690,7 +709,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(9, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(9, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -718,7 +737,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -740,7 +759,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(7, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(7, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -762,7 +781,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -782,7 +801,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(5, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(5, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -808,7 +827,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(4, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } free(pinfo->pay_load); @@ -827,7 +846,7 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) if (g_ble_client_callback) { MOD_BLE_LOG("[ble] callback start.\r\n"); - mp_sched_schedule(g_ble_client_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_ble_client_callback, mp_obj_new_tuple(3, tuple)); MOD_BLE_LOG("[ble] callback end.\r\n"); } break; @@ -841,7 +860,11 @@ static void qpy_ble_client_user_callback(void *ind_msg_buf, void *ctx) STATIC mp_obj_t qpy_ble_gatt_client_init(mp_obj_t callback) { Helios_BLEInitStruct info = {0}; - g_ble_client_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_ble_client_callback = &cb; + mp_sched_schedule_callback_register(g_ble_client_callback, callback); + info.ble_user_cb = qpy_ble_client_user_callback; int ret = Helios_BLE_GattClientInit(&info); return mp_obj_new_int(ret); @@ -852,6 +875,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ble_gatt_client_init_obj, qpy_ble_gatt_clie STATIC mp_obj_t qpy_ble_gatt_client_release(void) { int ret = 0; + g_ble_client_callback = NULL; ret = Helios_BLE_GattClientRelease(); return mp_obj_new_int(ret); } @@ -1191,14 +1215,49 @@ STATIC mp_obj_t qpy_ble_gatt_write_chara_no_rsp(size_t n_args, const mp_obj_t *a } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_ble_gatt_write_chara_norsp_obj, 3, 3, qpy_ble_gatt_write_chara_no_rsp); +STATIC mp_obj_t qpy_ble_gatt_set_scanreport_filter(mp_obj_t act) +{ + uint16_t switch_filter = mp_obj_get_int(act); + if ((switch_filter != 0) && (switch_filter != 1)) + { + mp_raise_ValueError("invalid value, act should be in [0,1]."); + } + int ret = Helios_BLE_SetScanReportFilter(switch_filter); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ble_set_scanreport_filter_obj, qpy_ble_gatt_set_scanreport_filter); + +STATIC mp_obj_t qpy_module_ble_deinit(void) +{ + MOD_BLE_LOG("ble module deinit.\r\n"); + if (g_ble_server_callback != NULL) + { + MOD_BLE_LOG("ble server deinit.\r\n"); + Helios_BLE_GattStop(); + Helios_BLE_GattServerRelease(); + g_ble_server_callback = NULL; + } + if (g_ble_client_callback != NULL) + { + MOD_BLE_LOG("ble client deinit.\r\n"); + Helios_BLE_GattStop(); + Helios_BLE_GattClientRelease(); + g_ble_client_callback = NULL; + } + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_ble_deinit_obj, qpy_module_ble_deinit); + STATIC const mp_rom_map_elem_t mp_module_ble_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ble) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_ble_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_serverInit), MP_ROM_PTR(&qpy_ble_gatt_server_init_obj) }, { MP_ROM_QSTR(MP_QSTR_serverRelease), MP_ROM_PTR(&qpy_ble_gatt_server_release_obj) }, { MP_ROM_QSTR(MP_QSTR_gattStart), MP_ROM_PTR(&qpy_ble_gatt_start_obj) }, { MP_ROM_QSTR(MP_QSTR_gattStop), MP_ROM_PTR(&qpy_ble_gatt_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_getStatus), MP_ROM_PTR(&qpy_ble_get_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_getPublicAddr), MP_ROM_PTR(&qpy_ble_get_public_addr_obj) }, //{ MP_ROM_QSTR(MP_QSTR_getConnStatus), MP_ROM_PTR(&qpy_ble_get_conn_status_obj) }, { MP_ROM_QSTR(MP_QSTR_setLocalName), MP_ROM_PTR(&qpy_ble_gatt_set_local_name_obj) }, { MP_ROM_QSTR(MP_QSTR_setAdvParam), MP_ROM_PTR(&qpy_ble_set_adv_param_obj) }, @@ -1234,6 +1293,7 @@ STATIC const mp_rom_map_elem_t mp_module_ble_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_writeChara), MP_ROM_PTR(&qpy_ble_gatt_write_chara_obj) }, { MP_ROM_QSTR(MP_QSTR_writeCharaDesc), MP_ROM_PTR(&qpy_ble_gatt_write_chara_desc_obj) }, { MP_ROM_QSTR(MP_QSTR_writeCharaNoRsp), MP_ROM_PTR(&qpy_ble_gatt_write_chara_norsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_setScanFilter), MP_ROM_PTR(&qpy_ble_set_scanreport_filter_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_ble_globals, mp_module_ble_globals_table); diff --git a/ports/quectel/core/source/modcamera.c b/ports/quectel/core/source/modcamera.c index bda5e52..6aeacee 100644 --- a/ports/quectel/core/source/modcamera.c +++ b/ports/quectel/core/source/modcamera.c @@ -47,7 +47,7 @@ STATIC const mp_rom_map_elem_t mp_module_camera_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_camPreview), MP_ROM_PTR(&camera_preview_type) }, // { MP_ROM_QSTR(MP_QSTR_camRecord), MP_ROM_PTR(&camer_record_type) }, #ifdef CONFIG_CAMERA_SAVEPHOTOS - { MP_ROM_QSTR(MP_QSTR_camCaputre), MP_ROM_PTR(&camera_capture_type) }, + { MP_ROM_QSTR(MP_QSTR_camCapture), MP_ROM_PTR(&camera_capture_type) }, #endif #ifdef CONFIG_CAMERA_DECODE { MP_ROM_QSTR(MP_QSTR_camScandecode), MP_ROM_PTR(&camera_scandecode_type) }, diff --git a/ports/quectel/core/source/modcelllocator.c b/ports/quectel/core/source/modcelllocator.c index 831484d..727bf28 100644 --- a/ports/quectel/core/source/modcelllocator.c +++ b/ports/quectel/core/source/modcelllocator.c @@ -97,16 +97,18 @@ STATIC mp_obj_t qpy_lbs_get_cell_coordinates(size_t n_args, const mp_obj_t *args config_info.timeout = timeout; config_info.profile_idx = profile_idx; + MP_THREAD_GIL_EXIT(); ret = Helios_LBS_SetConfiguration(0, &config_info); + MP_THREAD_GIL_ENTER(); if (ret != 0) { QPY_MODLBS_LOG("para config failed!\r\n"); return mp_obj_new_int(-1); } - MP_THREAD_GIL_EXIT(); + //MP_THREAD_GIL_EXIT(); ret = Helios_LBS_GetPosition(&position); - MP_THREAD_GIL_ENTER(); + //MP_THREAD_GIL_ENTER(); if (ret != 0) { return mp_obj_new_int(-6); diff --git a/ports/quectel/core/source/moddatacall.c b/ports/quectel/core/source/moddatacall.c index fdf8d7e..60b014f 100644 --- a/ports/quectel/core/source/moddatacall.c +++ b/ports/quectel/core/source/moddatacall.c @@ -311,7 +311,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_datacall_get_info_obj, 1, 2, qpy_ -static mp_obj_t g_usr_callback = NULL; +static c_callback_t * g_usr_callback = NULL; static void datacall_callback(int32_t profile_idx, uint8_t sim_id, int32_t nw_status) { @@ -325,7 +325,7 @@ static void datacall_callback(int32_t profile_idx, uint8_t sim_id, int32_t nw_st if (g_usr_callback) { MOD_DATACALL_LOG("[datacall] callback start.\r\n"); - mp_sched_schedule(g_usr_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_usr_callback, mp_obj_new_tuple(3, tuple)); MOD_DATACALL_LOG("[datacall] callback end.\r\n"); } } @@ -343,7 +343,11 @@ static void datacall_callback(int32_t profile_idx, uint8_t sim_id, int32_t nw_st /*=============================================================================*/ STATIC mp_obj_t qpy_datacall_register_usr_callback(mp_obj_t callback) { - g_usr_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_usr_callback = &cb; + mp_sched_schedule_callback_register(g_usr_callback, callback); + Helios_DataCallInitStruct DataCallInitStruct = {datacall_callback}; Helios_DataCall_Init((int32_t)Helios_DataCall_GetCurrentPDP(), 0, &DataCallInitStruct); return mp_obj_new_int(0); @@ -364,10 +368,41 @@ 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) +{ +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + int sim_id = mp_obj_get_int(simid); + int ret = 0; + char apn[99+1] = {0}; + + ret = Helios_DataCall_GetApn(sim_id, apn); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); +#else + return mp_obj_new_int(-1); +#endif +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_datacall_get_apn_obj, qpy_datacall_get_apn); +//#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); +} +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[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_dial) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_datacall_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&qpy_datacall_start_obj) }, { MP_ROM_QSTR(MP_QSTR_setAutoConnect), MP_ROM_PTR(&qpy_datacall_set_autoconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_getInfo), MP_ROM_PTR(&qpy_datacall_get_info_obj) }, @@ -375,6 +410,9 @@ 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 }; STATIC MP_DEFINE_CONST_DICT(mp_module_datacall_globals, mp_module_datacall_globals_table); diff --git a/ports/quectel/core/source/moddev.c b/ports/quectel/core/source/moddev.c index 596cb70..2679848 100644 --- a/ports/quectel/core/source/moddev.c +++ b/ports/quectel/core/source/moddev.c @@ -94,6 +94,26 @@ STATIC mp_obj_t queclib_dev_imei() STATIC MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_imei_obj, queclib_dev_imei); +#if defined (PLAT_Qualcomm) +STATIC mp_obj_t queclib_dev_backup() +{ + int ret = Helios_Dev_Backup(); + if( ret != 0 ) return mp_obj_new_int(-1); + return mp_obj_new_int(0); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_0(queclib_dev_backup_obj, queclib_dev_backup); + +STATIC mp_obj_t set_usbmode(mp_obj_t usbmode) { + int mode = mp_obj_get_int(usbmode); + extern int Helios_Dev_SetUSBMode(int mode); + return mp_obj_new_int(Helios_Dev_SetUSBMode(mode)); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_usbmode_obj, set_usbmode); + +#endif + STATIC const mp_rom_map_elem_t mp_module_modem_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_modem) }, @@ -102,6 +122,10 @@ STATIC const mp_rom_map_elem_t mp_module_modem_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getDevModel), MP_ROM_PTR(&queclib_dev_model_obj) }, { MP_ROM_QSTR(MP_QSTR_getDevFwVersion), MP_ROM_PTR(&queclib_dev_fw_version_obj) }, { MP_ROM_QSTR(MP_QSTR_getDevProductId), MP_ROM_PTR(&queclib_dev_product_id_obj) }, +#if defined (PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_backup), MP_ROM_PTR(&queclib_dev_backup_obj) }, + { MP_ROM_QSTR(MP_QSTR_setUSBMode), MP_ROM_PTR(&set_usbmode_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_modem_globals, mp_module_modem_globals_table); diff --git a/ports/quectel/core/source/modethernet.c b/ports/quectel/core/source/modethernet.c new file mode 100644 index 0000000..7d3ba08 --- /dev/null +++ b/ports/quectel/core/source/modethernet.c @@ -0,0 +1,21 @@ +#include +#include + +#include "obj.h" +#include "runtime.h" + +/* 定义的ethernet全局字典,之后我们添加type和function就要添加在这里 */ +extern const mp_obj_type_t ethernet_DM9051_type; +STATIC const mp_rom_map_elem_t ethernet_globals_table[] = { + {MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ethernet)}, //这个对应python层面的__name__ 属性 + {MP_OBJ_NEW_QSTR(MP_QSTR_DM9051), MP_ROM_PTR(ðernet_DM9051_type)}, +}; + +/* 把ethernet_globals_table注册到 mp_module_ethernet_globals里面去 */ +STATIC MP_DEFINE_CONST_DICT(mp_module_ethernet_globals, ethernet_globals_table); + +/* 定义一个module类型 */ +const mp_obj_module_t mp_module_ethernet = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mp_module_ethernet_globals, +}; \ No newline at end of file diff --git a/ports/quectel/core/source/modethernet_dm9051.c b/ports/quectel/core/source/modethernet_dm9051.c new file mode 100644 index 0000000..7ae4b65 --- /dev/null +++ b/ports/quectel/core/source/modethernet_dm9051.c @@ -0,0 +1,235 @@ +#include +#include +#include + +#include "obj.h" +#include "runtime.h" +#include "mperrno.h" +#include "sockets.h" +#include "helios_pin.h" +#include "helios_dm9051.h" + +/* 定义DM9051_obj_t结构体 */ +typedef struct _DM9051_obj_t +{ + mp_obj_base_t base; //定义的对象结构体要包含该成员 +}DM9051_obj_t; + +const mp_obj_type_t ethernet_DM9051_type; +STATIC mp_obj_t ethernet_DM9051_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, 6, false); //检查参数个数 + DM9051_obj_t *self = m_new_obj(DM9051_obj_t); //创建对象,分配空间 + self->base.type = ðernet_DM9051_type; //定义对象的类型 + + uint8_t mac[6] = {0}; + char *ip_str = NULL, *mask_str = NULL, *gw_str = NULL; + int spi_port = -1, spi_cs_pin = -1; + + switch(n_args) { + case 6: { + extern int export2internal_pin(Helios_GPIONum export_pin); + spi_cs_pin = mp_obj_get_int(args[5]); + if(spi_cs_pin != -1) { + if(!(spi_cs_pin >= HELIOS_GPIO0 && spi_cs_pin <= HELIOS_GPIOMAX)) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid spi cs pin")); + break; + } + spi_cs_pin = export2internal_pin((Helios_GPIONum)spi_cs_pin); + } + // no break + } + + case 5: { + spi_port = mp_obj_get_int(args[4]); + if(spi_port != -1) { + if(spi_port != 0 && spi_port != 1) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid spi port")); + break; + } + } + // no break + } + + case 4: { + char *_gw_str = (char *)mp_obj_str_get_str(args[3]); + gw_str = (_gw_str[0] == '\0' ? NULL : _gw_str); + // no break + } + + case 3: { + char *_mask_str = (char *)mp_obj_str_get_str(args[2]); + mask_str = (_mask_str[0] == '\0' ? NULL : _mask_str); + // no break + } + + case 2: { + char *_ip_str = (char *)mp_obj_str_get_str(args[1]); + ip_str = (_ip_str[0] == '\0' ? NULL : _ip_str); + // no break + } + + case 1: { + mp_buffer_info_t macinfo; + mp_get_buffer_raise(args[0], &macinfo, MP_BUFFER_READ); + memcpy(&mac, macinfo.buf, 6); + break; + } + + default: + mp_raise_OSError(MP_EFAULT); + break; + } + + Helios_DM9051_NICSetSPI(spi_port, spi_cs_pin); + if(Helios_DM9051_NICRegister(mac, ip_str, mask_str, gw_str)) + mp_raise_OSError(MP_EIO); + + return MP_OBJ_FROM_PTR(self); //返回对象的指针 +} + +/* 定义set_addr函数 */ + +STATIC const mp_arg_t ethernet_dm9051_set_addr_allowed_args[] = { + { MP_QSTR_ipaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_maskaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_gwaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +}; +STATIC mp_obj_t set_addr(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[MP_ARRAY_SIZE(ethernet_dm9051_set_addr_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(ethernet_dm9051_set_addr_allowed_args), ethernet_dm9051_set_addr_allowed_args, args); + + DM9051_obj_t *self = (DM9051_obj_t *)MP_OBJ_TO_PTR(pos_args[0]); + mp_buffer_info_t ipaddrinfo, maskaddrinfo, gwaddrinfo; + mp_get_buffer_raise(args[0].u_obj, &ipaddrinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[1].u_obj, &maskaddrinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[2].u_obj, &gwaddrinfo, MP_BUFFER_READ); + + char ip_str[16] = {0}, mask_str[16] = {0}, gw_str[16] = {0}; + char *ip_str_fin = NULL, *mask_str_fin = NULL, *gw_str_fin = NULL; + + if(ipaddrinfo.len) { + memcpy(ip_str, ipaddrinfo.buf, ipaddrinfo.len); + ip_str_fin = ip_str; + } + + if(maskaddrinfo.len) { + memcpy(mask_str, maskaddrinfo.buf, maskaddrinfo.len); + mask_str_fin = mask_str; + } + + if(gwaddrinfo.len) { + memcpy(gw_str, gwaddrinfo.buf, gwaddrinfo.len); + gw_str_fin = gw_str; + } + + return mp_obj_new_int(Helios_DM9051_NICSetAddr(ip_str_fin, mask_str_fin, gw_str_fin)); +} + +/* 定义set_dns函数 */ +STATIC mp_obj_t set_dns(mp_obj_t self_in, mp_obj_t pri_addr, mp_obj_t sec_addr) { + (void)self_in; + char *pri_str = NULL, *sec_str = NULL; + + char *_pri_str = (char *)mp_obj_str_get_str(pri_addr); + if (_pri_str[0] != '\0') + pri_str = _pri_str; + + char *_sec_str = (char *)mp_obj_str_get_str(sec_addr); + if (_sec_str[0] != '\0') + sec_str = _sec_str; + + Helios_DM9051_NICSetDNS(pri_str, sec_str); + + return mp_const_none; +} + +/* 定义set_up函数 */ +STATIC mp_obj_t set_up(mp_obj_t self_in) { + (void)self_in; + return mp_obj_new_int(Helios_DM9051_NICSetUp()); +} + +/* 定义set_down函数 */ +STATIC mp_obj_t set_down(mp_obj_t self_in) { + (void)self_in; + return mp_obj_new_int(Helios_DM9051_NICSetDown()); +} + +/* 定义start_dhcp函数 */ +STATIC mp_obj_t start_dhcp(mp_obj_t self_in) { + (void)self_in; + return mp_obj_new_int(Helios_DM9051_NICDHCP()); +} + +/* 定义ipconfig函数 */ +STATIC mp_obj_t ipconfig(mp_obj_t self_in) { + (void)self_in; + dm_ethnetif_ipconfig_t ipconfig = {0}; + char mac[24] = {0}; + char ip[16] = {0}; + char mask[16] = {0}; + char gw[16] = {0}; + char dns1[16] = {0}; + char dns2[16] = {0}; + + Helios_DM9051_IPConfig(&ipconfig); + + sprintf(mac, "%02X-%02X-%02X-%02X-%02X-%02X", ipconfig.mac[0], ipconfig.mac[1], ipconfig.mac[2], ipconfig.mac[3], ipconfig.mac[4], ipconfig.mac[5]); + + mp_obj_t generic_tuple[2] = { + mp_obj_new_str(mac, strlen(mac)), + mp_obj_new_str(ipconfig.hostname, strlen(ipconfig.hostname)) + }; + + inet_ntop(AF_INET, (void *)&ipconfig.ipv4_info.ipaddr, ip, sizeof(ip)); + inet_ntop(AF_INET, (void *)&ipconfig.ipv4_info.netmask, mask, sizeof(mask)); + inet_ntop(AF_INET, (void *)&ipconfig.ipv4_info.gw, gw, sizeof(gw)); + inet_ntop(AF_INET, (void *)&ipconfig.ipv4_info.dns_server[0], dns1, sizeof(dns1)); + inet_ntop(AF_INET, (void *)&ipconfig.ipv4_info.dns_server[1], dns2, sizeof(dns2)); + + mp_obj_t ipv4info_tuple[6] = { + mp_obj_new_int(ipconfig.ipv4_info.iptype), + mp_obj_new_str(ip, strlen(ip)), + mp_obj_new_str(mask, strlen(mask)), + mp_obj_new_str(gw, strlen(gw)), + mp_obj_new_str(dns1, strlen(dns1)), + mp_obj_new_str(dns2, strlen(dns2)) + }; + + mp_obj_t ipconfig_list[2] = { + mp_obj_new_tuple(2, generic_tuple), + mp_obj_new_tuple(6, ipv4info_tuple) + }; + + return mp_obj_new_list(2, ipconfig_list); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(set_addr_obj, 4, set_addr); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(set_dns_obj, set_dns); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_up_obj, set_up); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_down_obj, set_down); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(start_dhcp_obj, start_dhcp); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(ipconfig_obj, ipconfig); + +/* 定义type的本地字典 */ +STATIC const mp_rom_map_elem_t DM9051_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_set_addr), MP_ROM_PTR(&set_addr_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_dns), MP_ROM_PTR(&set_dns_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_up), MP_ROM_PTR(&set_up_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_down), MP_ROM_PTR(&set_down_obj) }, + { MP_ROM_QSTR(MP_QSTR_dhcp), MP_ROM_PTR(&start_dhcp_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&ipconfig_obj) }, +}; + +/* 把DM9051_locals_dict_table注册到DM9051_locals_dict里面去 */ +STATIC MP_DEFINE_CONST_DICT(DM9051_locals_dict, DM9051_locals_dict_table); + +/* 定义mp_obj_type_t类型的结构体;注意这里和定义module使用的类型是不一样的 */ +const mp_obj_type_t ethernet_DM9051_type = { + .base={ &mp_type_type }, + .name = MP_QSTR_DM9051, //type类的name属性是放在这里定义,而不是放在DICT中 + .make_new = ethernet_DM9051_make_new, //添加的make new属性 + .locals_dict = (mp_obj_dict_t*)&DM9051_locals_dict, //注册DM9051_locals_dict +}; \ No newline at end of file diff --git a/ports/quectel/core/source/modexample.c b/ports/quectel/core/source/modexample.c index 6a4b7dc..97c3d08 100644 --- a/ports/quectel/core/source/modexample.c +++ b/ports/quectel/core/source/modexample.c @@ -29,6 +29,7 @@ #include "stream.h" #include "mperrno.h" #include "pyexec.h" +#include "interrupt_char.h" //void do_str(const char *src, mp_parse_input_kind_t input_kind) { // nlr_buf_t nlr; @@ -119,12 +120,20 @@ STATIC mp_obj_t example_exec(const mp_obj_t arg0) { snprintf(fname, sizeof(fname), "%s", (char *)bufinfo.buf); } + MAINPY_RUNNING_FLAG_SET(); ret = pyexec_file_if_exists(fname); + MAINPY_RUNNING_FLAG_CLEAR(); } if ( ret == -1 ) { mp_raise_msg_varg(&mp_type_OSError, "File path error or not exist: [%s]", (char *)bufinfo.buf); } + 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"); + } // Pawn 2021-01-18 for JIRA STASR3601-2428 end return mp_const_none; } diff --git a/ports/quectel/core/source/modfota.c b/ports/quectel/core/source/modfota.c index c845f50..d72c37d 100644 --- a/ports/quectel/core/source/modfota.c +++ b/ports/quectel/core/source/modfota.c @@ -90,8 +90,9 @@ STATIC mp_obj_t fota_write(size_t n_args, const mp_obj_t *args) return mp_obj_new_int(0); } +#if !defined(PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fota_write_obj, 1, 3, fota_write); - +#endif STATIC mp_obj_t fota_flush(const mp_obj_t arg0) @@ -109,8 +110,9 @@ STATIC mp_obj_t fota_flush(const mp_obj_t arg0) return mp_obj_new_int(0); } +#if !defined(PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_1(fota_flush_obj, fota_flush); - +#endif STATIC mp_obj_t fota_verify(const mp_obj_t arg0) { int ret = 0; @@ -126,9 +128,10 @@ STATIC mp_obj_t fota_verify(const mp_obj_t arg0) return mp_obj_new_int(0); } +#if !defined(PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_1(fota_verify_obj, fota_verify); - -STATIC mp_obj_t fota_callback = NULL; +#endif +STATIC c_callback_t *fota_callback = NULL; static void mpFotaProgressCB(int sta, int progress) @@ -139,7 +142,7 @@ static void mpFotaProgressCB(int sta, int progress) mp_obj_new_int(progress), }; - mp_sched_schedule(fota_callback, mp_obj_new_list(2, fota_list)); + mp_sched_schedule_ex(fota_callback, mp_obj_new_list(2, fota_list)); } if(sta == 1) @@ -192,7 +195,10 @@ STATIC mp_obj_t fota_firmware_download(size_t n_args, const mp_obj_t *args, mp_m } if (args_parse[ARG_callback].u_obj != mp_const_none) { - fota_callback = args_parse[ARG_callback].u_obj; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + fota_callback = &cb; + mp_sched_schedule_callback_register(fota_callback, args_parse[ARG_callback].u_obj); } ret = Helios_Fota_firmware_download(server_address1, server_address2, mpFotaProgressCB); @@ -208,13 +214,26 @@ STATIC mp_obj_t fota_firmware_download(size_t n_args, const mp_obj_t *args, mp_m STATIC MP_DEFINE_CONST_FUN_OBJ_KW(fota_firmware_download_obj, 1, fota_firmware_download); +STATIC mp_obj_t fota___del__(mp_obj_t self_in) +{ + fota_obj_t *self = MP_OBJ_TO_PTR(self_in); + + Helios_Fota_Deinit(self->ctx); + fota_callback = NULL; + + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fota___del___obj, fota___del__); STATIC const mp_rom_map_elem_t fota_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fota___del___obj) }, { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_fota) }, +#if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&fota_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&fota_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&fota_verify_obj) }, +#endif { MP_ROM_QSTR(MP_QSTR_httpDownload), MP_ROM_PTR(&fota_firmware_download_obj) }, }; STATIC MP_DEFINE_CONST_DICT(fota_locals_dict, fota_locals_dict_table); diff --git a/ports/quectel/core/source/modlpm.c b/ports/quectel/core/source/modlpm.c index f20f285..4159b06 100644 --- a/ports/quectel/core/source/modlpm.c +++ b/ports/quectel/core/source/modlpm.c @@ -87,7 +87,10 @@ STATIC mp_obj_t Helios_lpm_wakelock_lock_mp(const mp_obj_t lpm_fd) return mp_obj_new_int(-1); } +#if !defined(PLAT_RDA) + STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_lpm_wakelock_lock_mp_obj, Helios_lpm_wakelock_lock_mp); +#endif /*=============================================================================*/ @@ -115,8 +118,10 @@ STATIC mp_obj_t Helios_lpm_wakelock_unlock_mp(const mp_obj_t lpm_fd) return mp_obj_new_int(-1); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_lpm_wakelock_unlock_mp_obj, Helios_lpm_wakelock_unlock_mp); +#if !defined(PLAT_RDA) +STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_lpm_wakelock_unlock_mp_obj, Helios_lpm_wakelock_unlock_mp); +#endif /*=============================================================================*/ /* FUNCTION: Helios_lpm_wakelock_create_mp */ @@ -156,8 +161,10 @@ STATIC mp_obj_t Helios_lpm_wakelock_create_mp(size_t n_args, const mp_obj_t *arg return mp_obj_new_int(wakelock_fd); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Helios_lpm_wakelock_create_mp_obj, 1, 2, Helios_lpm_wakelock_create_mp); +#if !defined(PLAT_RDA) +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Helios_lpm_wakelock_create_mp_obj, 1, 2, Helios_lpm_wakelock_create_mp); +#endif /*=============================================================================*/ /* FUNCTION: Helios_lpm_wakelock_delete_mp */ @@ -178,8 +185,9 @@ STATIC mp_obj_t Helios_lpm_wakelock_delete_mp(const mp_obj_t lpm_fd) ret = Helios_LPM_WakeLockDeInit(g_lpm_fd); return mp_obj_new_int(ret); } +#if !defined(PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_1(Helios_lpm_wakelock_delete_mp_obj, Helios_lpm_wakelock_delete_mp); - +#endif /*=============================================================================*/ /* FUNCTION: Helios_lpm_get_wakelock_num_mp */ @@ -200,7 +208,9 @@ STATIC mp_obj_t Helios_lpm_get_wakelock_num_mp() return mp_obj_new_int(num); } +#if !defined(PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_0(Helios_lpm_get_wakelock_num_mp_obj, Helios_lpm_get_wakelock_num_mp); +#endif /* @@ -218,12 +228,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_free_size_obj, mp_get_free_size); STATIC const mp_rom_map_elem_t pm_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pm) }, +#if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_create_wakelock), MP_ROM_PTR(&Helios_lpm_wakelock_create_mp_obj) }, { MP_ROM_QSTR(MP_QSTR_delete_wakelock), MP_ROM_PTR(&Helios_lpm_wakelock_delete_mp_obj) }, { MP_ROM_QSTR(MP_QSTR_wakelock_lock), MP_ROM_PTR(&Helios_lpm_wakelock_lock_mp_obj) }, { MP_ROM_QSTR(MP_QSTR_wakelock_unlock), MP_ROM_PTR(&Helios_lpm_wakelock_unlock_mp_obj) }, - { MP_ROM_QSTR(MP_QSTR_autosleep), MP_ROM_PTR(&Helios_sleep_enable_mp_obj) }, { MP_ROM_QSTR(MP_QSTR_get_wakelock_num), MP_ROM_PTR(&Helios_lpm_get_wakelock_num_mp_obj) }, +#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) }, }; 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 a7b842e..c3f359f 100644 --- a/ports/quectel/core/source/modlvgl.c +++ b/ports/quectel/core/source/modlvgl.c @@ -32048,17 +32048,34 @@ STATIC mp_obj_t mp_lv_draw_img(size_t mp_n_args, const mp_obj_t *mp_args) STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_draw_img_obj, 5, mp_lv_draw_img, lv_draw_img); +#if 0 + +STATIC const mp_lv_struct_t mp_lv_font_chinese_16 = { + { &mp_lv_font_t_type }, + (lv_font_t*)&lv_font_chinese_16 +}; + +#endif + +STATIC const mp_lv_struct_t mp_quec_font = { + { &mp_lv_font_t_type }, + (lv_font_t*)&quec_font +}; + +#if 0 STATIC const mp_lv_struct_t mp_lv_font_chinese_11 = { { &mp_lv_font_t_type }, (lv_font_t*)&lv_font_chinese_11 }; +#endif STATIC const mp_lv_struct_t mp_lv_font_chinese_9 = { { &mp_lv_font_t_type }, (lv_font_t*)&lv_font_chinese_9 }; +#if 0 /* @@ -32086,7 +32103,7 @@ STATIC const mp_lv_struct_t mp_lv_font_roboto_28 = { (lv_font_t*)&lv_font_roboto_28 }; - +#endif /* * lvgl lv_style_scr global definitions */ @@ -33122,11 +33139,13 @@ STATIC const mp_rom_map_elem_t lvgl_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_color_t), MP_ROM_PTR(&mp_lv_color32_t_type) }, - { MP_ROM_QSTR(MP_QSTR_font_chinese_11), MP_ROM_PTR(&mp_lv_font_chinese_11) }, + + //{ MP_ROM_QSTR(MP_QSTR_font_chinese_16), MP_ROM_PTR(&mp_lv_font_chinese_16) }, + //{ MP_ROM_QSTR(MP_QSTR_font_chinese_11), MP_ROM_PTR(&mp_lv_font_chinese_11) }, { MP_ROM_QSTR(MP_QSTR_font_chinese_9), MP_ROM_PTR(&mp_lv_font_chinese_9) }, - { MP_ROM_QSTR(MP_QSTR_font_roboto_16), MP_ROM_PTR(&mp_lv_font_roboto_16) }, + //{ MP_ROM_QSTR(MP_QSTR_font_roboto_16), MP_ROM_PTR(&mp_lv_font_roboto_16) }, { MP_ROM_QSTR(MP_QSTR_font_quec), MP_ROM_PTR(&mp_quec_font) }, - { MP_ROM_QSTR(MP_QSTR_font_roboto_28), MP_ROM_PTR(&mp_lv_font_roboto_28) }, + //{ MP_ROM_QSTR(MP_QSTR_font_roboto_28), MP_ROM_PTR(&mp_lv_font_roboto_28) }, { MP_ROM_QSTR(MP_QSTR_style_scr), MP_ROM_PTR(&mp_lv_style_scr) }, { MP_ROM_QSTR(MP_QSTR_style_transp), MP_ROM_PTR(&mp_lv_style_transp) }, { MP_ROM_QSTR(MP_QSTR_style_transp_fit), MP_ROM_PTR(&mp_lv_style_transp_fit) }, diff --git a/ports/quectel/core/source/modmachine.c b/ports/quectel/core/source/modmachine.c index 657e56d..d6bfe53 100644 --- a/ports/quectel/core/source/modmachine.c +++ b/ports/quectel/core/source/modmachine.c @@ -41,23 +41,28 @@ - STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&machine_extint_type) }, + { 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_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) }, #if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&machine_lcd_type) }, - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, - { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&machine_extint_type) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, #endif +#if defined(PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_KeyPad), MP_ROM_PTR(&machine_keypad_type) }, +#endif + #ifdef CONFIG_SPINAND { MP_ROM_QSTR(MP_QSTR_NANDFLASH), MP_ROM_PTR(&machine_nandflash_type) }, #endif +#endif }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/ports/quectel/core/source/modmachine.h b/ports/quectel/core/source/modmachine.h index ee6a2aa..e5fc4fa 100644 --- a/ports/quectel/core/source/modmachine.h +++ b/ports/quectel/core/source/modmachine.h @@ -39,6 +39,9 @@ extern const mp_obj_type_t machine_hard_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) +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 9d4f0b7..13676da 100644 --- a/ports/quectel/core/source/modmisc.c +++ b/ports/quectel/core/source/modmisc.c @@ -56,15 +56,21 @@ STATIC mp_obj_t qpy_misc_set_replEnable(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_misc_set_replEnable_obj, 1, 2, qpy_misc_set_replEnable); - STATIC const mp_rom_map_elem_t misc_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_misc) }, { MP_ROM_QSTR(MP_QSTR_Power), MP_ROM_PTR(&misc_power_type) }, + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&misc_adc_type) }, { MP_ROM_QSTR(MP_QSTR_PowerKey), MP_ROM_PTR(&misc_powerkey_type) }, +#if !defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_replEnable), MP_ROM_PTR(&qpy_misc_set_replEnable_obj) }, +#if !defined(PLAT_RDA) { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&misc_pwm_type) }, - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&misc_adc_type) }, { MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&misc_usb_type) }, - { MP_ROM_QSTR(MP_QSTR_replEnable), MP_ROM_PTR(&qpy_misc_set_replEnable_obj) }, +#endif +#endif +#if defined(PLAT_ASR) + { MP_ROM_QSTR(MP_QSTR_USBNET), MP_ROM_PTR(&misc_usbnet_module) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(misc_module_globals, misc_module_globals_table); diff --git a/ports/quectel/core/source/modmisc.h b/ports/quectel/core/source/modmisc.h index aeeb2a9..4b42750 100644 --- a/ports/quectel/core/source/modmisc.h +++ b/ports/quectel/core/source/modmisc.h @@ -34,6 +34,9 @@ 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) +extern const mp_obj_module_t misc_usbnet_module; +#endif extern const mp_obj_type_t misc_powerkey_type; diff --git a/ports/quectel/core/source/modnb.c b/ports/quectel/core/source/modnb.c new file mode 100644 index 0000000..a0e7216 --- /dev/null +++ b/ports/quectel/core/source/modnb.c @@ -0,0 +1,66 @@ +/* + * 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 modnb.h + * @author burols.wang + * @version V1.0.0 + * @date 2021/08/23 + * @brief IOT data interaction function module + ****************************************************************************** + */ + +#if defined(PLAT_RDA) +#include +#include + + +#include "compile.h" +#include "runtime.h" +#include "repl.h" +#include "mperrno.h" + +#include "modnb.h" + + + +#if MICROPY_PY_NB + +STATIC const mp_rom_map_elem_t nb_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___NB__), MP_ROM_QSTR(MP_QSTR_NB) }, + + #if MICROPY_PY_NB_OC + { MP_ROM_QSTR(MP_QSTR_OC), MP_ROM_PTR(&nb_oc_type) }, + #endif + #if MICROPY_PY_NB_AEP + { MP_OBJ_NEW_QSTR(MP_QSTR_AEP), MP_ROM_PTR(&nb_aep_type) }, + #endif + + #if MICROPY_PY_NB_ONENET + { MP_ROM_QSTR(MP_QSTR_ONENET), MP_ROM_PTR(&module_onenet) }, + #endif +}; + +STATIC MP_DEFINE_CONST_DICT(nb_module_globals, nb_module_globals_table); + +const mp_obj_module_t mp_module_nb = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&nb_module_globals, +}; + +#endif /* MICROPY_PY_NB */ +#endif /* END PLAT_RDA*/ diff --git a/ports/quectel/core/source/modnb.h b/ports/quectel/core/source/modnb.h new file mode 100644 index 0000000..3a4e065 --- /dev/null +++ b/ports/quectel/core/source/modnb.h @@ -0,0 +1,46 @@ +/* + * 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 modnb.h + * @author burols.wang + * @version V1.0.0 + * @date 2021/08/23 + * @brief IOT data interaction function module + ****************************************************************************** + */ + +#ifndef __MOD_NB_H_ +#define __MOD_NB_H_ + +#include "mpconfigport.h" +#include "obj.h" + +#if defined(MICROPY_PY_NB_OC) +extern const mp_obj_type_t nb_oc_type; +#endif + +#if defined(MICROPY_PY_NB_AEP) +extern const mp_obj_type_t nb_aep_type; +#endif + +#if defined(MICROPY_PY_NB_ONENET) +extern const mp_obj_module_t module_onenet; +#endif + +#endif /* __MOD_NB_H_ */ + diff --git a/ports/quectel/core/source/modnet.c b/ports/quectel/core/source/modnet.c index 4f52ffc..5c2d80f 100644 --- a/ports/quectel/core/source/modnet.c +++ b/ports/quectel/core/source/modnet.c @@ -1,859 +1,938 @@ -/* - * 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 "obj.h" -#include "runtime.h" -#include "mphalport.h" -#include "helios_debug.h" -#include "helios_nw.h" -#include "helios_dev.h" -#if !defined(PLAT_RDA) -#include "helios_sim.h" -#endif - -#define QPY_NET_LOG(msg, ...) custom_log(modnet, msg, ##__VA_ARGS__) - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_set_mode */ -/*=============================================================================*/ -/*!@brief: set network mode - * - * @mode [in] network mode - * @roaming [in] enable or disable roaming - * - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_set_configuration(size_t n_args, const mp_obj_t *args) -{ - int mode; - int roaming; - int ret = 0; - Helios_NwConfigInfoStruct config_info = {0}; - - mode = mp_obj_get_int(args[0]); - QPY_NET_LOG("[network] set config, mode=%d\r\n", mode); - if (n_args == 2) - { - roaming = mp_obj_get_int(args[1]); - if((roaming != 0) && (roaming != 1)) - { - QPY_NET_LOG("[network] invalid roaming value, roaming=%d\r\n", roaming); - return mp_obj_new_int(-1); - } - config_info.roaming_switch = roaming; - QPY_NET_LOG("[network] set config, roaming=%d\r\n", roaming); - } - - config_info.net_mode = mode; - - ret = Helios_Nw_SetConfiguration(0, &config_info); - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_configuration_obj, 1, 2, qpy_net_set_configuration); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_mode */ -/*=============================================================================*/ -/*!@brief: get network mode - * - * @return: - * returns net mode on success. - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_configuration(void) -{ - int ret = 0; - Helios_NwConfigInfoStruct config_info = {0}; - - ret = Helios_Nw_GetConfiguration(0, &config_info); - if(ret == 0) - { - mp_obj_t tuple[2] = {mp_obj_new_int(config_info.net_mode), mp_obj_new_bool(config_info.roaming_switch)}; - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_configuration_obj, qpy_net_get_configuration); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_csq */ -/*=============================================================================*/ -/*!@brief: get CSQ signal strength - * - * @return: - * returns CSQ on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_csq(void) -{ - int ret = 0; - int csq = -1; - -#if !defined(PLAT_RDA) - Helios_SIM_Status_e status = 0; - ret = Helios_SIM_GetCardStatus(0, &status); - if (ret == 0) - { - if (status == 0) - { - return mp_obj_new_int(99); - } - } - else - { - return mp_obj_new_int(-1); - } -#endif - csq = Helios_Nw_GetCSQ(0); - if(csq != -1) - { - return mp_obj_new_int(csq); - } - - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_csq_obj, qpy_net_get_csq); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_nitz_time */ -/*=============================================================================*/ -/*!@brief: get nitz time - * - * @return: - * returns nitz time on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_nitz_time(void) -{ - int ret = 0; - Helios_NwNITZTimeInfoStruct info = {0}; - - ret = Helios_Nw_GetNITZTime(&info); - if (ret == 0) - { - QPY_NET_LOG("nitz_time:%s\r\n",info.nitz_time); - mp_obj_t tuple[3] = { - mp_obj_new_str(info.nitz_time, strlen(info.nitz_time)), - mp_obj_new_int_from_ull(info.abs_time), - mp_obj_new_int(info.leap_sec)}; - - return mp_obj_new_tuple(3, tuple); - } - - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_nitz_time_obj, qpy_net_get_nitz_time); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_operator_name */ -/*=============================================================================*/ -/*!@brief: get operator name - * - * @return: - * returns operator name on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_operator_name(void) -{ - int ret = 0; - Helios_NwOperatorInfoStruct info = {0}; - Helios_NwRegisterStatusInfoStruct reg_info = {0}; - - ret = Helios_Nw_GetRegisterStatus(0, ®_info); - if (ret == 0) - { - if ((reg_info.data_reg.status != 1) && (reg_info.data_reg.status != 5)) - { - QPY_NET_LOG("nw is not registered\r\n"); - return mp_obj_new_int(-1); - } - } - else - { - QPY_NET_LOG("get nw register status failed.\r\n"); - return mp_obj_new_int(-1); - } - - ret = Helios_Nw_GetOperatorName(0, &info); - if (ret == 0) - { - mp_obj_t tuple[4] = { - mp_obj_new_str(info.long_name, strlen(info.long_name)), - mp_obj_new_str(info.short_name, strlen(info.short_name)), - mp_obj_new_str(info.mcc, strlen(info.mcc)), - mp_obj_new_str(info.mnc, strlen(info.mnc))}; - - return mp_obj_new_tuple(4, tuple); - } - - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_operator_name_obj, qpy_net_get_operator_name); - -#if 0 -/*=============================================================================*/ -/* FUNCTION: qpy_net_set_selection */ -/*=============================================================================*/ -/*!@brief: set network selection - * - * @mode [in] 0 - automatic, 1 - manual - * @mcc [in] mobile device country code - * @mnc [in] mobile device network code - * @act [in] network mode - * - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_set_selection(size_t n_args, const mp_obj_t *args) -{ - int ret = 0; - Helios_NwSelectionInfoStruct info = {0}; - mp_buffer_info_t bufinfo_mc = {0}; - mp_buffer_info_t bufinfo_mn = {0}; - mp_int_t mode = 0; - mp_int_t nw_act = 0; - - mode = mp_obj_get_int(args[0]); - nw_act = mp_obj_get_int(args[3]); - mp_get_buffer_raise(args[1], &bufinfo_mc, MP_BUFFER_READ); - mp_get_buffer_raise(args[2], &bufinfo_mn, MP_BUFFER_READ); - - if ((mode != 0) && (mode != 1)) - { - QPY_NET_LOG("[network] set selection failed, mode=%d\r\n", mode); - return mp_obj_new_int(-1); - } - - if ((nw_act < 0) || (nw_act > 7)) - { - QPY_NET_LOG("[network] set selection failed, act=%d\r\n", nw_act); - return mp_obj_new_int(-1); - } - - if (strlen(bufinfo_mc.buf) > 4) - { - QPY_NET_LOG("[network] set selection failed, mcc=%s\r\n", bufinfo_mc.buf); - return mp_obj_new_int(-1); - } - - if (strlen(bufinfo_mn.buf) > 4) - { - QPY_NET_LOG("[network] set selection failed, mnc=%s\r\n", bufinfo_mn.buf); - return mp_obj_new_int(-1); - } - info.nw_selection_mode = mode; - strcpy(info.mcc, bufinfo_mc.buf); - strcpy(info.mnc, bufinfo_mn.buf); - info.act = nw_act; - - ret = Helios_Nw_SetSelection(0, &info); - if (ret == 0) - { - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_selection_obj, 3, 4, qpy_net_set_selection); -#endif - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_selection */ -/*=============================================================================*/ -/*!@brief: get network selection - * - * @return: - * returns (nw_selection,mcc, mnc, act) on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_selection(void) -{ - int ret = 0; - Helios_NwSelectionInfoStruct info = {0}; - - ret = Helios_Nw_GetSelection(0, &info); - if (ret == 0) - { - mp_obj_t tuple[4] = { - mp_obj_new_int(info.nw_selection_mode), - mp_obj_new_str(info.mcc, strlen(info.mcc)), - mp_obj_new_str(info.mnc, strlen(info.mnc)), - mp_obj_new_int(info.act)}; - - return mp_obj_new_tuple(4, tuple); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_selection_obj, qpy_net_get_selection); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_reg_status */ -/*=============================================================================*/ -/*!@brief: get information about network registration - * - * @return: - * returns information about network registration on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_reg_status(void) -{ - int ret = 0; - Helios_NwRegisterStatusInfoStruct info = {0}; - - ret = Helios_Nw_GetRegisterStatus(0, &info); - if (ret == 0) - { - mp_obj_t voice_list[6] = { - mp_obj_new_int(info.voice_reg.status), - mp_obj_new_int(info.voice_reg.lac), - mp_obj_new_int(info.voice_reg.cid), - mp_obj_new_int(info.voice_reg.act), - mp_obj_new_int(info.voice_reg.reject_cause), - mp_obj_new_int(info.voice_reg.psc) - }; - - mp_obj_t data_list[6] = { - mp_obj_new_int(info.data_reg.status), - mp_obj_new_int(info.data_reg.lac), - mp_obj_new_int(info.data_reg.cid), - mp_obj_new_int(info.data_reg.act), - mp_obj_new_int(info.data_reg.reject_cause), - mp_obj_new_int(info.data_reg.psc) - }; - - mp_obj_t tuple[2] = { - mp_obj_new_list(6,voice_list), - mp_obj_new_list(6,data_list)}; - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_reg_status_obj, qpy_net_get_reg_status); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_signal_strength */ -/*=============================================================================*/ -/*!@brief: get signal strength - * - * @return: - * returns information about signal strength on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_signal_strength(void) -{ - int ret = 0; - Helios_NwSignalStrengthInfoStruct info = {0}; - - ret = Helios_Nw_GetSignalStrength(0, &info); - if (ret == 0) - { - mp_obj_t gw_list[4] = { - mp_obj_new_int(info.gw_signal_strength.rssi), - mp_obj_new_int(info.gw_signal_strength.bit_error_rate), - mp_obj_new_int(info.gw_signal_strength.rscp), - mp_obj_new_int(info.gw_signal_strength.ecno)}; - - mp_obj_t lte_list[4] = { - mp_obj_new_int(info.lte_signal_strength.rssi), - mp_obj_new_int(info.lte_signal_strength.rsrp), - mp_obj_new_int(info.lte_signal_strength.rsrq), - mp_obj_new_int(info.lte_signal_strength.cqi)}; - - mp_obj_t tuple[2] = { - mp_obj_new_list(4,gw_list), - mp_obj_new_list(4,lte_list)}; - - return mp_obj_new_tuple(2, tuple); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_signal_strength_obj, qpy_net_get_signal_strength); - - -/*=============================================================================*/ -/* FUNCTION: qpy_net_get_mnc */ -/*=============================================================================*/ -/*!@brief: get mnc - * - * @return: - * returns mnc on success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_get_mnc(void) -{ - int ret = 0; - int i = 0; - mp_obj_t mnc_list = mp_obj_new_list(0, NULL); - Helios_NwCellInfoStruct info = {0}; - - ret = Helios_Nw_GetCellInfo(0, &info); - if (ret == 0) - { - if (info.gsm_info_num > 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 0) - { - for (i=0; i 1 ) - { - rst = mp_obj_get_int(args[1]); - } - - modem_fun = (uint8_t)mp_obj_get_int(args[0]); - - ret = Helios_Dev_SetModemFunction(modem_fun, rst); - if (ret == 0) - { - return mp_obj_new_int(0); - } - return mp_obj_new_int(-1); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_modem_fun_obj, 1, 2, qpy_net_set_modem_fun); - - -static mp_obj_t g_net_user_callback = NULL; - -static void qpy_net_event_handler(uint8_t sim_id, int32_t event_id, void *ctx) -{ - switch (event_id) - { - case HELIOS_NW_DATA_REG_STATUS_IND: - { - Helios_NwRegisterInfoStruct *nw_register_status = (Helios_NwRegisterInfoStruct *)ctx; - mp_obj_t tuple[5] = - { - mp_obj_new_int(event_id), - mp_obj_new_int(nw_register_status->status), - mp_obj_new_int(nw_register_status->lac), - mp_obj_new_int(nw_register_status->cid), - mp_obj_new_int(nw_register_status->act), - }; - - if (g_net_user_callback) - { - QPY_NET_LOG("[net] callback start.\r\n"); - mp_sched_schedule(g_net_user_callback, mp_obj_new_tuple(5, tuple)); - QPY_NET_LOG("[net] callback end.\r\n"); - } - break; - } - case HELIOS_NW_VOICE_REG_STATUS_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - case HELIOS_NW_NITZ_TIME_UPDATE_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - case HELIOS_NW_SIGNAL_QUALITY_IND: - /* ... */ - QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); - break; - default: - QPY_NET_LOG("[net] event handler, ind=%x\r\n", event_id); - break; - } -} - -/*=============================================================================*/ -/* FUNCTION: qpy_net_add_event_handler */ -/*=============================================================================*/ -/*!@brief: registered user callback function - * - * @handler [in] callback function - * - * @return: - * 0 - success - * -1 - error - */ -/*=============================================================================*/ -STATIC mp_obj_t qpy_net_add_event_handler(mp_obj_t handler) -{ - g_net_user_callback = handler; - Helios_NwInitStruct info = {0}; - - info.user_cb = qpy_net_event_handler; - Helios_Nw_Init(&info); - return mp_obj_new_int(0); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_add_event_handler_obj, qpy_net_add_event_handler); - - - -STATIC const mp_rom_map_elem_t net_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_net) }, - { MP_ROM_QSTR(MP_QSTR_csqQueryPoll), MP_ROM_PTR(&qpy_net_get_csq_obj) }, - { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&qpy_net_get_reg_status_obj) }, - { MP_ROM_QSTR(MP_QSTR_getConfig), MP_ROM_PTR(&qpy_net_get_configuration_obj) }, - { MP_ROM_QSTR(MP_QSTR_setConfig), MP_ROM_PTR(&qpy_net_set_configuration_obj) }, - { MP_ROM_QSTR(MP_QSTR_nitzTime), MP_ROM_PTR(&qpy_net_get_nitz_time_obj) }, - { MP_ROM_QSTR(MP_QSTR_operatorName), MP_ROM_PTR(&qpy_net_get_operator_name_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_setNetMode), MP_ROM_PTR(&qpy_net_set_selection_obj) }, - { MP_ROM_QSTR(MP_QSTR_getNetMode), MP_ROM_PTR(&qpy_net_get_selection_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSignal), MP_ROM_PTR(&qpy_net_get_signal_strength_obj)}, - { MP_ROM_QSTR(MP_QSTR_getCellInfo), MP_ROM_PTR(&qpy_net_get_cell_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCi), MP_ROM_PTR(&qpy_net_get_cid_obj) }, - { MP_ROM_QSTR(MP_QSTR_getLac), MP_ROM_PTR(&qpy_net_get_lac_obj) }, - { MP_ROM_QSTR(MP_QSTR_getMnc), MP_ROM_PTR(&qpy_net_get_mnc_obj) }, - { MP_ROM_QSTR(MP_QSTR_getMcc), MP_ROM_PTR(&qpy_net_get_mcc_obj) }, - { MP_ROM_QSTR(MP_QSTR_setModemFun), MP_ROM_PTR(&qpy_net_set_modem_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_getModemFun), MP_ROM_PTR(&qpy_net_get_modem_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_net_add_event_handler_obj) }, - -}; - -STATIC MP_DEFINE_CONST_DICT(net_module_globals, net_module_globals_table); - -const mp_obj_module_t mp_module_net = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&net_module_globals, -}; +/* + * 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 "obj.h" +#include "runtime.h" +#include "mphalport.h" +#include "helios_debug.h" +#include "helios_nw.h" +#include "helios_dev.h" +#if !defined(PLAT_RDA) +#include "helios_sim.h" +#endif + +#define QPY_NET_LOG(msg, ...) custom_log(modnet, msg, ##__VA_ARGS__) + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_set_mode */ +/*=============================================================================*/ +/*!@brief: set network mode + * + * @mode [in] network mode + * @roaming [in] enable or disable roaming + * + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_set_configuration(size_t n_args, const mp_obj_t *args) +{ + int mode; + int roaming; + int ret = 0; + Helios_NwConfigInfoStruct config_info = {0}; + + mode = mp_obj_get_int(args[0]); + QPY_NET_LOG("[network] set config, mode=%d\r\n", mode); + if (n_args == 2) + { + roaming = mp_obj_get_int(args[1]); + if((roaming != 0) && (roaming != 1)) + { + QPY_NET_LOG("[network] invalid roaming value, roaming=%d\r\n", roaming); + return mp_obj_new_int(-1); + } + config_info.roaming_switch = roaming; + QPY_NET_LOG("[network] set config, roaming=%d\r\n", roaming); + } + + config_info.net_mode = mode; + + ret = Helios_Nw_SetConfiguration(0, &config_info); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_configuration_obj, 1, 2, qpy_net_set_configuration); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_mode */ +/*=============================================================================*/ +/*!@brief: get network mode + * + * @return: + * returns net mode on success. + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_configuration(void) +{ + int ret = 0; + Helios_NwConfigInfoStruct config_info = {0}; + + ret = Helios_Nw_GetConfiguration(0, &config_info); + if(ret == 0) + { + mp_obj_t tuple[2] = {mp_obj_new_int(config_info.net_mode), mp_obj_new_bool(config_info.roaming_switch)}; + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_configuration_obj, qpy_net_get_configuration); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_csq */ +/*=============================================================================*/ +/*!@brief: get CSQ signal strength + * + * @return: + * returns CSQ on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_csq(void) +{ + int ret = 0; + int csq = -1; + +#if !defined(PLAT_RDA) + Helios_SIM_Status_e status = 0; + ret = Helios_SIM_GetCardStatus(0, &status); + if (ret == 0) + { + if (status == 0) + { + return mp_obj_new_int(99); + } + } + else + { + return mp_obj_new_int(-1); + } +#endif + csq = Helios_Nw_GetCSQ(0); + if(csq != -1) + { + return mp_obj_new_int(csq); + } + + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_csq_obj, qpy_net_get_csq); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_nitz_time */ +/*=============================================================================*/ +/*!@brief: get nitz time + * + * @return: + * returns nitz time on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_nitz_time(void) +{ + int ret = 0; + Helios_NwNITZTimeInfoStruct info = {0}; + + ret = Helios_Nw_GetNITZTime(&info); + if (ret == 0) + { + QPY_NET_LOG("nitz_time:%s\r\n",info.nitz_time); + mp_obj_t tuple[3] = { + mp_obj_new_str(info.nitz_time, strlen(info.nitz_time)), + mp_obj_new_int_from_ull(info.abs_time), + mp_obj_new_int(info.leap_sec)}; + + return mp_obj_new_tuple(3, tuple); + } + + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_nitz_time_obj, qpy_net_get_nitz_time); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_operator_name */ +/*=============================================================================*/ +/*!@brief: get operator name + * + * @return: + * returns operator name on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_operator_name(void) +{ + int ret = 0; + Helios_NwOperatorInfoStruct info = {0}; + Helios_NwRegisterStatusInfoStruct reg_info = {0}; + + ret = Helios_Nw_GetRegisterStatus(0, ®_info); + if (ret == 0) + { + if ((reg_info.data_reg.status != 1) && (reg_info.data_reg.status != 5)) + { + QPY_NET_LOG("nw is not registered\r\n"); + return mp_obj_new_int(-1); + } + } + else + { + QPY_NET_LOG("get nw register status failed.\r\n"); + return mp_obj_new_int(-1); + } + + ret = Helios_Nw_GetOperatorName(0, &info); + if (ret == 0) + { + mp_obj_t tuple[4] = { + mp_obj_new_str(info.long_name, strlen(info.long_name)), + mp_obj_new_str(info.short_name, strlen(info.short_name)), + mp_obj_new_str(info.mcc, strlen(info.mcc)), + mp_obj_new_str(info.mnc, strlen(info.mnc))}; + + return mp_obj_new_tuple(4, tuple); + } + + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_operator_name_obj, qpy_net_get_operator_name); + +#if 0 +/*=============================================================================*/ +/* FUNCTION: qpy_net_set_selection */ +/*=============================================================================*/ +/*!@brief: set network selection + * + * @mode [in] 0 - automatic, 1 - manual + * @mcc [in] mobile device country code + * @mnc [in] mobile device network code + * @act [in] network mode + * + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_set_selection(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + Helios_NwSelectionInfoStruct info = {0}; + mp_buffer_info_t bufinfo_mc = {0}; + mp_buffer_info_t bufinfo_mn = {0}; + mp_int_t mode = 0; + mp_int_t nw_act = 0; + + mode = mp_obj_get_int(args[0]); + nw_act = mp_obj_get_int(args[3]); + mp_get_buffer_raise(args[1], &bufinfo_mc, MP_BUFFER_READ); + mp_get_buffer_raise(args[2], &bufinfo_mn, MP_BUFFER_READ); + + if ((mode != 0) && (mode != 1)) + { + QPY_NET_LOG("[network] set selection failed, mode=%d\r\n", mode); + return mp_obj_new_int(-1); + } + + if ((nw_act < 0) || (nw_act > 7)) + { + QPY_NET_LOG("[network] set selection failed, act=%d\r\n", nw_act); + return mp_obj_new_int(-1); + } + + if (strlen(bufinfo_mc.buf) > 4) + { + QPY_NET_LOG("[network] set selection failed, mcc=%s\r\n", bufinfo_mc.buf); + return mp_obj_new_int(-1); + } + + if (strlen(bufinfo_mn.buf) > 4) + { + QPY_NET_LOG("[network] set selection failed, mnc=%s\r\n", bufinfo_mn.buf); + return mp_obj_new_int(-1); + } + info.nw_selection_mode = mode; + strcpy(info.mcc, bufinfo_mc.buf); + strcpy(info.mnc, bufinfo_mn.buf); + info.act = nw_act; + + ret = Helios_Nw_SetSelection(0, &info); + if (ret == 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_selection_obj, 3, 4, qpy_net_set_selection); +#endif + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_selection */ +/*=============================================================================*/ +/*!@brief: get network selection + * + * @return: + * returns (nw_selection,mcc, mnc, act) on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_selection(void) +{ + int ret = 0; + Helios_NwSelectionInfoStruct info = {0}; + + ret = Helios_Nw_GetSelection(0, &info); + if (ret == 0) + { + mp_obj_t tuple[4] = { + mp_obj_new_int(info.nw_selection_mode), + mp_obj_new_str(info.mcc, strlen(info.mcc)), + mp_obj_new_str(info.mnc, strlen(info.mnc)), + mp_obj_new_int(info.act)}; + + return mp_obj_new_tuple(4, tuple); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_selection_obj, qpy_net_get_selection); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_reg_status */ +/*=============================================================================*/ +/*!@brief: get information about network registration + * + * @return: + * returns information about network registration on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_reg_status(void) +{ + int ret = 0; + Helios_NwRegisterStatusInfoStruct info = {0}; + + ret = Helios_Nw_GetRegisterStatus(0, &info); + if (ret == 0) + { + mp_obj_t voice_list[6] = { + mp_obj_new_int(info.voice_reg.status), + mp_obj_new_int(info.voice_reg.lac), + mp_obj_new_int(info.voice_reg.cid), + mp_obj_new_int(info.voice_reg.act), + mp_obj_new_int(info.voice_reg.reject_cause), + mp_obj_new_int(info.voice_reg.psc) + }; + + mp_obj_t data_list[6] = { + mp_obj_new_int(info.data_reg.status), + mp_obj_new_int(info.data_reg.lac), + mp_obj_new_int(info.data_reg.cid), + mp_obj_new_int(info.data_reg.act), + mp_obj_new_int(info.data_reg.reject_cause), + mp_obj_new_int(info.data_reg.psc) + }; + + mp_obj_t tuple[2] = { + mp_obj_new_list(6,voice_list), + mp_obj_new_list(6,data_list)}; + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_reg_status_obj, qpy_net_get_reg_status); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_signal_strength */ +/*=============================================================================*/ +/*!@brief: get signal strength + * + * @return: + * returns information about signal strength on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_signal_strength(void) +{ + int ret = 0; + Helios_NwSignalStrengthInfoStruct info = {0}; + + ret = Helios_Nw_GetSignalStrength(0, &info); + if (ret == 0) + { + mp_obj_t gw_list[4] = { + mp_obj_new_int(info.gw_signal_strength.rssi), + mp_obj_new_int(info.gw_signal_strength.bit_error_rate), + mp_obj_new_int(info.gw_signal_strength.rscp), + mp_obj_new_int(info.gw_signal_strength.ecno)}; + + mp_obj_t lte_list[4] = { + mp_obj_new_int(info.lte_signal_strength.rssi), + mp_obj_new_int(info.lte_signal_strength.rsrp), + mp_obj_new_int(info.lte_signal_strength.rsrq), + mp_obj_new_int(info.lte_signal_strength.cqi)}; + + mp_obj_t tuple[2] = { + mp_obj_new_list(4,gw_list), + mp_obj_new_list(4,lte_list)}; + + return mp_obj_new_tuple(2, tuple); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_net_get_signal_strength_obj, qpy_net_get_signal_strength); + + +/*=============================================================================*/ +/* FUNCTION: qpy_net_get_mnc */ +/*=============================================================================*/ +/*!@brief: get mnc + * + * @return: + * returns mnc on success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_get_mnc(void) +{ + int ret = 0; + int i = 0; + mp_obj_t mnc_list = mp_obj_new_list(0, NULL); + Helios_NwCellInfoStruct info = {0}; + + ret = Helios_Nw_GetCellInfo(0, &info); + if (ret == 0) + { + if (info.gsm_info_num > 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 0) + { + for (i=0; i 1 ) + { + rst = mp_obj_get_int(args[1]); + } + + modem_fun = (uint8_t)mp_obj_get_int(args[0]); + + MP_THREAD_GIL_EXIT(); + ret = Helios_Dev_SetModemFunction(modem_fun, rst); + MP_THREAD_GIL_ENTER(); + if (ret == 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qpy_net_set_modem_fun_obj, 1, 2, qpy_net_set_modem_fun); + +STATIC mp_obj_t qpy_net_set_apn(mp_obj_t apn, mp_obj_t simid) +{ +#if defined(PLAT_ASR)// || defined(PLAT_Unisoc) + char *net_apn = (char *)mp_obj_str_get_str(apn); + uint8_t net_simid = mp_obj_get_int(simid); + int ret = 0; + + if ((net_simid != 0) && (net_simid != 1)) + { + mp_raise_ValueError("invalid simid."); + } + + ret = Helios_Nw_SetApn(net_apn, net_simid); + if (ret == 0) + { + return mp_obj_new_int(0); + } + return mp_obj_new_int(-1); +#else + return mp_obj_new_int(-1); +#endif +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_net_set_apn_obj, qpy_net_set_apn); + +STATIC mp_obj_t qpy_net_get_apn(mp_obj_t simid) +{ +#if defined(PLAT_ASR)// || defined(PLAT_Unisoc) + uint8_t net_simid = mp_obj_get_int(simid); + int ret = 0; + char apn[99+1] = {0}; + + if ((net_simid != 0) && (net_simid != 1)) + { + mp_raise_ValueError("invalid simid."); + } + + ret = Helios_Nw_GetApn(apn, net_simid); + if (ret == 0) + { + return mp_obj_new_str(apn, strlen(apn)); + } + return mp_obj_new_int(-1); +#else + return mp_obj_new_int(-1); +#endif +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_get_apn_obj, qpy_net_get_apn); + +static c_callback_t *g_net_user_callback = NULL; + +static void qpy_net_event_handler(uint8_t sim_id, int32_t event_id, void *ctx) +{ + switch (event_id) + { + case HELIOS_NW_DATA_REG_STATUS_IND: + { + Helios_NwRegisterInfoStruct *nw_register_status = (Helios_NwRegisterInfoStruct *)ctx; + mp_obj_t tuple[5] = + { + mp_obj_new_int(event_id), + mp_obj_new_int(nw_register_status->status), + mp_obj_new_int(nw_register_status->lac), + mp_obj_new_int(nw_register_status->cid), + mp_obj_new_int(nw_register_status->act), + }; + + if (g_net_user_callback) + { + QPY_NET_LOG("[net] callback start.\r\n"); + mp_sched_schedule_ex(g_net_user_callback, mp_obj_new_tuple(5, tuple)); + QPY_NET_LOG("[net] callback end.\r\n"); + } + break; + } + case HELIOS_NW_VOICE_REG_STATUS_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + case HELIOS_NW_NITZ_TIME_UPDATE_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + case HELIOS_NW_SIGNAL_QUALITY_IND: + /* ... */ + QPY_NET_LOG("[net] ind_flag = %x\r\n", event_id); + break; + default: + QPY_NET_LOG("[net] event handler, ind=%x\r\n", event_id); + break; + } +} + +/*=============================================================================*/ +/* FUNCTION: qpy_net_add_event_handler */ +/*=============================================================================*/ +/*!@brief: registered user callback function + * + * @handler [in] callback function + * + * @return: + * 0 - success + * -1 - error + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_net_add_event_handler(mp_obj_t handler) +{ + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_net_user_callback = &cb; + mp_sched_schedule_callback_register(g_net_user_callback, handler); + Helios_NwInitStruct info = {0}; + + info.user_cb = qpy_net_event_handler; + Helios_Nw_Init(&info); + return mp_obj_new_int(0); +} +#if !defined (PLAT_RDA) +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_net_add_event_handler_obj, qpy_net_add_event_handler); +#endif + +/*=============================================================================*/ +/* FUNCTION: qpy_module_net_deinit */ +/*=============================================================================*/ +/*!@brief: deinit net module + * + * + * @return: + * 0 - success + */ +/*=============================================================================*/ +STATIC mp_obj_t qpy_module_net_deinit(void) +{ + QPY_NET_LOG("module net deinit.\r\n"); +#if defined(PLAT_ASR) || defined(PLAT_Unisoc) + Helios_Nw_Deinit(); +#endif + g_net_user_callback = NULL; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_net_deinit_obj, qpy_module_net_deinit); + + +STATIC const mp_rom_map_elem_t net_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_net) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_net_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_csqQueryPoll), MP_ROM_PTR(&qpy_net_get_csq_obj) }, + { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&qpy_net_get_reg_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_getConfig), MP_ROM_PTR(&qpy_net_get_configuration_obj) }, + { MP_ROM_QSTR(MP_QSTR_setConfig), MP_ROM_PTR(&qpy_net_set_configuration_obj) }, + { MP_ROM_QSTR(MP_QSTR_nitzTime), MP_ROM_PTR(&qpy_net_get_nitz_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_operatorName), MP_ROM_PTR(&qpy_net_get_operator_name_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_setNetMode), MP_ROM_PTR(&qpy_net_set_selection_obj) }, + { MP_ROM_QSTR(MP_QSTR_getNetMode), MP_ROM_PTR(&qpy_net_get_selection_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSignal), MP_ROM_PTR(&qpy_net_get_signal_strength_obj)}, + { MP_ROM_QSTR(MP_QSTR_getCellInfo), MP_ROM_PTR(&qpy_net_get_cell_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_getCi), MP_ROM_PTR(&qpy_net_get_cid_obj) }, + { MP_ROM_QSTR(MP_QSTR_getLac), MP_ROM_PTR(&qpy_net_get_lac_obj) }, + { MP_ROM_QSTR(MP_QSTR_getMnc), MP_ROM_PTR(&qpy_net_get_mnc_obj) }, + { MP_ROM_QSTR(MP_QSTR_getMcc), MP_ROM_PTR(&qpy_net_get_mcc_obj) }, + { MP_ROM_QSTR(MP_QSTR_setModemFun), MP_ROM_PTR(&qpy_net_set_modem_fun_obj) }, + { MP_ROM_QSTR(MP_QSTR_getModemFun), MP_ROM_PTR(&qpy_net_get_modem_fun_obj) }, +#if !defined (PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_net_add_event_handler_obj) }, +#endif + { 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) }, +}; + +STATIC MP_DEFINE_CONST_DICT(net_module_globals, net_module_globals_table); + +const mp_obj_module_t mp_module_net = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&net_module_globals, +}; diff --git a/ports/quectel/core/source/modostimer.c b/ports/quectel/core/source/modostimer.c index dc2d1f5..2416556 100644 --- a/ports/quectel/core/source/modostimer.c +++ b/ports/quectel/core/source/modostimer.c @@ -30,8 +30,11 @@ #include "mperrno.h" #include "obj.h" #include "helios_os.h" +#include "helios_debug.h" +#define HELIOS_OSTIMER_LOG(msg, ...) custom_log("osTimer", msg, ##__VA_ARGS__) + typedef struct _mod_ostimer_obj_t { @@ -39,16 +42,16 @@ typedef struct _mod_ostimer_obj_t Helios_OSTimer_t handle; /* OS supplied timer reference */ unsigned int initialTime; /* initial expiration time in ms */ bool cyclicalEn; /* wether to enable the cyclical mode or not */ - mp_obj_t callback; /* timer call-back routine */ + c_callback_t callback; /* timer call-back routine */ bool deleteFlagh; } mod_ostimer_obj_t; const mp_obj_type_t mp_ostimer_type; -STATIC void mod_ostimer_isr(void *self_in) { - mod_ostimer_obj_t *self = (mod_ostimer_obj_t *)self_in; - if(mp_obj_is_callable(self->callback)){ - mp_sched_schedule(self->callback, self); +STATIC void mod_ostimer_isr(void *cb) { + c_callback_t *callback = (c_callback_t *)cb; + if(NULL != callback){ + mp_sched_schedule_ex(callback, mp_const_none); } // mp_hal_wake_main_task_from_isr(); } @@ -72,19 +75,27 @@ STATIC mp_obj_t mod_ostimer_start(uint n_args, const mp_obj_t *args) mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(args[0]); - self->initialTime = mp_obj_get_int(args[1]); - - self->cyclicalEn = !!mp_obj_get_int(args[2]); - - self->callback = args[3]; - - Helios_OSTimerAttr OSTimerAttr = { - .ms = (uint32_t)self->initialTime, - .cycle_enable = self->cyclicalEn, - .cb = mod_ostimer_isr, - .argv = (void *)self - }; - ret = Helios_OSTimer_Start(self->handle, &OSTimerAttr); + if (!(self->deleteFlagh)) + { + self->initialTime = mp_obj_get_int(args[1]); + + self->cyclicalEn = !!mp_obj_get_int(args[2]); + + //self->callback = args[3]; + mp_sched_schedule_callback_register(&self->callback, args[3]); + + Helios_OSTimerAttr OSTimerAttr = { + .ms = (uint32_t)self->initialTime, + .cycle_enable = self->cyclicalEn, + .cb = mod_ostimer_isr, + .argv = (void *)&self->callback + }; + ret = Helios_OSTimer_Start(self->handle, &OSTimerAttr); + } + else + { + ret = -1; + } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ostimer_start_obj, 3, 5, mod_ostimer_start); @@ -96,8 +107,14 @@ STATIC mp_obj_t mod_ostimer_stop(mp_obj_t arg0) int ret = 0; mod_ostimer_obj_t *self = MP_OBJ_TO_PTR(arg0); - - ret = Helios_OSTimer_Stop(self->handle); + if (!(self->deleteFlagh)) + { + ret = Helios_OSTimer_Stop(self->handle); + } + else + { + ret = -1; + } return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_stop_obj, mod_ostimer_stop); @@ -114,6 +131,7 @@ STATIC mp_obj_t mod_ostimer_delete(mp_obj_t arg0) { self->deleteFlagh = 1; Helios_OSTimer_Delete(self->handle); + HELIOS_OSTIMER_LOG("[osTimer] ostimer delete\r\n"); } return mp_obj_new_int(ret); @@ -123,6 +141,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ostimer_delete_obj, mod_ostimer_delete); STATIC const mp_rom_map_elem_t mod_ostimer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_osTimer) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_ostimer_delete_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_ostimer_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_ostimer_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_delete_timer), MP_ROM_PTR(&mod_ostimer_delete_obj) }, diff --git a/ports/quectel/core/source/modpoc.c b/ports/quectel/core/source/modpoc.c new file mode 100644 index 0000000..988bc57 --- /dev/null +++ b/ports/quectel/core/source/modpoc.c @@ -0,0 +1,757 @@ +#include +#include +#include "obj.h" +#include "objstr.h" +#include "runtime.h" +#include "binary.h" +#include "objarray.h" + +#include "poc.h" +#include "helios_debug.h" + +#define POC_LOG(msg, ...) custom_log(poc, msg, ##__VA_ARGS__) + + +typedef struct _poc_obj_t +{ + mp_obj_base_t base; + unsigned char in_group; + mp_obj_t init_callback; + mp_obj_t login_callback; + mp_obj_t calluser_callback; + mp_obj_t audio_callback; + mp_obj_t join_group_callback; + mp_obj_t listupdate_callback; + mp_obj_t member_change_callback; + mp_obj_t upgrade_callback; +} poc_obj_t; + +static poc_obj_t poc_obj = {0}; + + +//init +void qpy_poc_isr(int ret) { + + if(poc_obj.init_callback && mp_obj_is_callable(poc_obj.init_callback)){ + mp_sched_schedule(poc_obj.init_callback, MP_OBJ_FROM_PTR(mp_obj_new_int(ret))); + } +} + +int qpy_poc_login_callback(int online) { + if(poc_obj.login_callback && mp_obj_is_callable(poc_obj.login_callback)){ + mp_sched_schedule(poc_obj.login_callback, MP_OBJ_FROM_PTR(mp_obj_new_int(online))); + } + return online; +} + +int qpy_poc_calluser_callback(int ret) { + if(poc_obj.calluser_callback && mp_obj_is_callable(poc_obj.calluser_callback)){ + mp_sched_schedule(poc_obj.calluser_callback, MP_OBJ_FROM_PTR(mp_obj_new_int(ret))); + } + return ret; +} + +void qpy_poc_register_audio_callback(AUDIO_STATE state, uid_t uid, const char* name, int flag) { + mp_obj_t audio_cb[4] = { + mp_obj_new_int(state), + mp_obj_new_int(uid), + mp_obj_new_str(name,strlen(name)), + mp_obj_new_int(flag) + }; + if(poc_obj.audio_callback && mp_obj_is_callable(poc_obj.audio_callback)){ + mp_sched_schedule(poc_obj.audio_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(4, audio_cb))); + } +} + +void qpy_poc_register_join_group_callback(const char* groupname, gid_t gid) { + mp_obj_t audio_cb[2] = { + mp_obj_new_str(groupname,strlen(groupname)), + mp_obj_new_int(gid) + }; + poc_obj.in_group = 1; + if(poc_obj.join_group_callback && mp_obj_is_callable(poc_obj.join_group_callback)){ + mp_sched_schedule(poc_obj.join_group_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(2, audio_cb))); + } +} + +void qpy_poc_register_listupdate_callback(int flag) { + if(poc_obj.listupdate_callback && mp_obj_is_callable(poc_obj.listupdate_callback)){ + mp_sched_schedule(poc_obj.listupdate_callback, MP_OBJ_FROM_PTR(mp_obj_new_int(flag))); + } +} + +void qpy_poc_register_member_change_callback(int flag, int nun, uid_t* uids) { + mp_obj_t member_change[4] = { + mp_obj_new_int(flag), + mp_obj_new_int(nun), + mp_obj_new_str(uids,strlen(uids)), + }; + if(poc_obj.member_change_callback && mp_obj_is_callable(poc_obj.member_change_callback)){ + mp_sched_schedule(poc_obj.member_change_callback, MP_OBJ_FROM_PTR(mp_obj_new_list(4,member_change))); + } +} + +void qpy_poc_egister_upgrade_callback(int ret) { + if(poc_obj.upgrade_callback && mp_obj_is_callable(poc_obj.upgrade_callback)){ + mp_sched_schedule(poc_obj.upgrade_callback, MP_OBJ_FROM_PTR(mp_obj_new_int(ret))); + } +} + + +STATIC mp_obj_t qpy_poc_init(mp_obj_t arg) +{ + poc_ops_t *poc_ops = poc_get_ops(); + + poc_obj.init_callback = arg; + + POC_LOG("poc init\n"); + poc_ops->init(qpy_poc_isr); + + poc_ops->register_audio_cb(qpy_poc_register_audio_callback); + + poc_ops->register_join_group_cb(qpy_poc_register_join_group_callback); + + poc_ops->register_listupdate_cb(qpy_poc_register_listupdate_callback); + + + poc_ops->register_upgrade_cb(qpy_poc_egister_upgrade_callback); + + + poc_ops->register_member_change_cb(qpy_poc_register_member_change_callback); + + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_init_obj, qpy_poc_init); +//init end + + +//free +STATIC mp_obj_t qpy_poc_free() +{ + POC_LOG("poc free\n"); + poc_ops_t *poc_ops = poc_get_ops(); + poc_ops->free(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_free_obj, qpy_poc_free); +//free end + +// log +STATIC mp_obj_t qpy_poc_log(mp_obj_t value) +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int log_enable = mp_obj_get_int(value); + POC_LOG("poc log enable = %d\n",log_enable); + poc_ops->log((boolean)log_enable); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_log_obj, qpy_poc_log); +//log end + + +//login + +STATIC mp_obj_t qpy_poc_login(mp_obj_t args) +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + poc_obj.login_callback = args; + POC_LOG("poc login \n"); + ret = poc_ops->login(qpy_poc_login_callback); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_login_obj, qpy_poc_login); +//login end + +//logout +STATIC mp_obj_t qpy_poc_logout() +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int ret = poc_ops->logout(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_logout_obj, qpy_poc_logout); +//logout end + +//joingroup +STATIC mp_obj_t qpy_poc_joingroup(mp_obj_t args) +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int ret = -1; + poc_obj.in_group = 0; + unsigned int gid = mp_obj_get_int(args); + + POC_LOG("poc joingroup\n"); + ret = poc_ops->joingroup(gid); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_joingroup_obj, qpy_poc_joingroup); +//joingroup end + +//leavegroup +STATIC mp_obj_t qpy_poc_leavegroup() +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->leavegroup(); + if(ret== 0) + poc_obj.in_group = 0; + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_leavegroup_obj, qpy_poc_leavegroup); +//leavegroup end + +//speak +STATIC mp_obj_t qpy_poc_speak(mp_obj_t value) +{ + + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int speak = mp_obj_get_int(value); + ret = poc_ops->speak(speak); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_speak_obj, qpy_poc_speak); +//speak end + +//calluser + +STATIC mp_obj_t qpy_poc_calluser(mp_obj_t poc_uid, mp_obj_t poc_cb) +{ + poc_ops_t *poc_ops = poc_get_ops(); + + int ret = 0; + + int uid = mp_obj_get_int(poc_uid); + POC_LOG("poc call user uid %d",uid); + poc_obj.calluser_callback = poc_cb; + + ret = poc_ops->calluser(uid,qpy_poc_calluser_callback); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_poc_calluser_obj, qpy_poc_calluser); +//calluser end + +//group_getbyindexr +STATIC mp_obj_t qpy_poc_group_getbyindex(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + group_t group_info = {0}; + int index = mp_obj_get_int(value); + ret = poc_ops->group_getbyindex(index, &group_info); + + POC_LOG("qpy_poc_group_getbyindex ret = %d",ret); + if(ret != 0 || group_info.name == NULL) return mp_obj_new_int(-1); + + mp_obj_t group_info_list[4] = { + mp_obj_new_int(group_info.gid), + mp_obj_new_str(group_info.name, strlen(group_info.name)), + mp_obj_new_int(group_info.type), + mp_obj_new_int(group_info.index)}; + + return mp_obj_new_list(4, group_info_list); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_group_getbyindex_obj, qpy_poc_group_getbyindex); +//group_getbyindexr end + +//group_getbyid +STATIC mp_obj_t qpy_poc_group_getbyid(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + group_t group_info = {0}; + int id = mp_obj_get_int(value); + + if(id == 0 && poc_obj.in_group == 0) return mp_obj_new_int(-1); + + ret = poc_ops->group_getbyid(id, &group_info); + POC_LOG("qpy_poc_group_getbyid ret = %d",ret); + if(ret != 0 || group_info.name == NULL) return mp_obj_new_int(-1); + + mp_obj_t group_info_list[4] = { + mp_obj_new_int(group_info.gid), + mp_obj_new_str(group_info.name, strlen(group_info.name)), + mp_obj_new_int(group_info.type), + mp_obj_new_int(group_info.index)}; + + return mp_obj_new_list(4, group_info_list); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_group_getbyid_obj, qpy_poc_group_getbyid); +//group_getbyid end + +//member_getbyid +STATIC mp_obj_t qpy_poc_member_getbyid(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + member_t member_info = {0}; + int uid = mp_obj_get_int(value); + ret = poc_ops->member_getbyid(uid, &member_info); + + POC_LOG("qpy_poc_member_getbyid ret = %d",ret); + if(ret != 0 || member_info.name == NULL) return mp_obj_new_int(-1); + + mp_obj_t member_info_list[4] = { + mp_obj_new_int(member_info.uid), + mp_obj_new_str(member_info.name, strlen(member_info.name)), + mp_obj_new_int(member_info.state), + mp_obj_new_int(member_info.index)}; + + return mp_obj_new_list(4, member_info_list); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_member_getbyid_obj, qpy_poc_member_getbyid); +//member_getbyid end + +//get_loginstate +STATIC mp_obj_t qpy_poc_get_loginstate() +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->get_loginstate(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_get_loginstate_obj, qpy_poc_get_loginstate); +//get_loginstate end + +//get_groupcount +STATIC mp_obj_t qpy_poc_get_groupcount() +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->get_groupcount(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_get_groupcount_obj, qpy_poc_get_groupcount); +//get_groupcount end +//get_grouplist +STATIC mp_obj_t qpy_poc_get_grouplist(mp_obj_t poc_index_begin, mp_obj_t poc_count) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int actual_read_num = 0; + int i = 0; + + int index_begin = mp_obj_get_int(poc_index_begin); + int count = mp_obj_get_int(poc_count); + static group_t *group_list = NULL; + if(group_list != NULL) { + free(group_list); + group_list = NULL; + } + int group_num = poc_ops->get_groupcount(); + group_list = malloc(sizeof(group_t)*group_num); + memset(group_list, 0, sizeof(group_t)*group_num); + + actual_read_num = poc_ops->get_grouplist(group_list, sizeof(group_t)*group_num, index_begin, count); + static mp_obj_t *group_list_py = NULL; + static mp_obj_t *tuple_return = NULL; + if(group_list_py != NULL) { + free(group_list_py); + group_list_py = NULL; + } + if(tuple_return != NULL) { + free(tuple_return); + tuple_return = NULL; + } + + group_list_py = malloc(sizeof(mp_obj_t)*actual_read_num*4); + memset(group_list_py,0,sizeof(mp_obj_t)*actual_read_num*4); + tuple_return = malloc(sizeof(mp_obj_t)*actual_read_num); + memset(tuple_return,0,sizeof(mp_obj_t)*actual_read_num); + if(actual_read_num > 0) { + for(i = 0; i < actual_read_num; i++) { + group_list_py[i*4] = mp_obj_new_int(group_list[i].gid); + group_list_py[i*4+1] = mp_obj_new_str(group_list[i].name, strlen(group_list[i].name)); + group_list_py[i*4+2] = mp_obj_new_int(group_list[i].type); + group_list_py[i*4+3] = mp_obj_new_int(group_list[i].index); + tuple_return[i] = mp_obj_new_list(4, group_list_py+4*i); + } + return mp_obj_new_tuple(actual_read_num, tuple_return); + }else { + return mp_obj_new_int(-1); + } + + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_poc_get_grouplist_obj, qpy_poc_get_grouplist); +//get_grouplist end + +//get_membercount +STATIC mp_obj_t qpy_poc_get_membercount(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int gid = mp_obj_get_int(value); + ret = poc_ops->get_membercount(gid); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_get_membercount_obj, qpy_poc_get_membercount); +//get_membercount end + +//get_memberlist +STATIC mp_obj_t qpy_poc_get_memberlist(mp_obj_t poc_gid, mp_obj_t poc_index_begin, mp_obj_t poc_count) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int actual_read_num = 0; + int i = 0; + + int gid = mp_obj_get_int(poc_gid); + int index_begin = mp_obj_get_int(poc_index_begin); + int count = mp_obj_get_int(poc_count); + + static member_t *member_list = NULL; + if(member_list != NULL) { + free(member_list); + member_list = NULL; + } + int member_num = poc_ops->get_membercount(gid); + member_list = malloc(sizeof(member_t)*member_num); + memset(member_list, 0, sizeof(member_t)*member_num); + + actual_read_num = poc_ops->get_memberlist(gid, member_list, (sizeof(member_t)*member_num), index_begin, count); + static mp_obj_t *member_list_py = NULL; + static mp_obj_t *tuple_return = NULL; + if(member_list_py != NULL) { + free(member_list_py); + member_list_py = NULL; + } + if(tuple_return != NULL) { + free(tuple_return); + tuple_return = NULL; + } + + member_list_py = malloc(sizeof(mp_obj_t)*actual_read_num*5); + tuple_return = malloc(sizeof(mp_obj_t)*actual_read_num); + memset(member_list_py,0,sizeof(mp_obj_t)*actual_read_num*5); + memset(tuple_return,0,sizeof(mp_obj_t)*actual_read_num); + if(actual_read_num > 0) { + for(i = 0; i < actual_read_num; i++) { + member_list_py[i*5] = mp_obj_new_int(member_list[i].uid); + member_list_py[i*5+1] = mp_obj_new_str(member_list[i].name, strlen(member_list[i].name)); + member_list_py[i*5+2] = mp_obj_new_int(member_list[i].state); + member_list_py[i*5+3] = mp_obj_new_int(member_list[i].prior); + member_list_py[i*5+4] = mp_obj_new_int(member_list[i].index); + tuple_return[i] = mp_obj_new_list(5, member_list_py+5*i); + } + return mp_obj_new_tuple(actual_read_num, tuple_return); + }else { + return mp_obj_new_int(-1); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_poc_get_memberlist_obj, qpy_poc_get_memberlist); +//get_memberlist end + +//get_audiostate +STATIC mp_obj_t qpy_poc_get_audiostate() +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->get_audiostate(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_get_audiostate_obj, qpy_poc_get_audiostate); +//get_audiostate end + +//play_tts +STATIC mp_obj_t qpy_poc_play_tts(mp_obj_t poc_tts, mp_obj_t poc_interrupt) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + + char *path = (char*)mp_obj_str_get_str(poc_tts); + int interrupt = mp_obj_get_int(poc_interrupt); + ret = poc_ops->play_tts(path, interrupt); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_poc_play_tts_obj, qpy_poc_play_tts); +//play_tts end + +//send_ping +STATIC mp_obj_t qpy_poc_send_ping() +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->send_ping(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_send_ping_obj, qpy_poc_send_ping); +//send_ping end + +//get_version +STATIC mp_obj_t qpy_poc_get_version() +{ + poc_ops_t *poc_ops = poc_get_ops(); + char version[64] = {0}; + poc_ops->get_version(version); + return mp_obj_new_str(version, strlen(version)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_get_version_obj, qpy_poc_get_version); +//get_version end + +//set_tts_enable +STATIC mp_obj_t qpy_poc_set_tts_enable(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int enable = mp_obj_get_int(value); + ret = poc_ops->set_tts_enable(enable); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_tts_enable_obj, qpy_poc_set_tts_enable); +//set_tts_enable end + +//register_audio_cb + +STATIC mp_obj_t qpy_poc_register_audio_cb(mp_obj_t args) +{ + poc_ops_t *poc_ops = poc_get_ops(); + poc_obj.audio_callback = args; + + POC_LOG("poc register audio cb\n"); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_register_audio_cb_obj, qpy_poc_register_audio_cb); +//register_audio_cb end + +//register_join_group_cb + +STATIC mp_obj_t qpy_poc_register_join_group_cb(mp_obj_t args) +{ + poc_ops_t *poc_ops = poc_get_ops(); + poc_obj.join_group_callback = args; + POC_LOG("poc register join ggroup cb\n"); + + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_register_join_group_cb_obj, qpy_poc_register_join_group_cb); +//register_join_group_cb end + +//register_listupdate_cb + +STATIC mp_obj_t qpy_poc_register_listupdate_cb(mp_obj_t args) +{ + poc_ops_t *poc_ops = poc_get_ops(); + poc_obj.listupdate_callback = args; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_register_listupdate_cb_obj, qpy_poc_register_listupdate_cb); +//register_listupdate_cb end + +//register_member_change_cb + +STATIC mp_obj_t qpy_poc_register_member_change_cb(mp_obj_t args) +{ + poc_ops_t *poc_ops = poc_get_ops(); + poc_obj.member_change_callback = args; + + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_register_member_change_cb_obj, qpy_poc_register_member_change_cb); +//register_member_change_cb end + +//set_call_end_timeptr +STATIC mp_obj_t qpy_poc_set_call_end_timeptr(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int timeptr = mp_obj_get_int(value); + POC_LOG("poc set call end timeptr = %d\n",timeptr); + ret = poc_ops->set_call_end_timeptr(timeptr); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_call_end_timeptr_obj, qpy_poc_set_call_end_timeptr); +//set_call_end_timeptr end + +//set_call_auto_leave_temp_group +STATIC mp_obj_t qpy_poc_set_call_auto_leave_temp_group(mp_obj_t args) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int flag = mp_obj_get_int(args); + ret = poc_ops->set_call_auto_leave_temp_group(flag); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_call_auto_leave_temp_group_obj, qpy_poc_set_call_auto_leave_temp_group); +//set_call_auto_leave_temp_group end + +//register_upgrade_cb + +STATIC mp_obj_t qpy_poc_register_upgrade_cb(const mp_obj_t args) +{ + poc_obj.upgrade_callback = args; + POC_LOG("poc register upgrade_cb\n"); + + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_register_upgrade_cb_obj, qpy_poc_register_upgrade_cb); +//register_upgrade_cb end + +//set_notify_mode +STATIC mp_obj_t qpy_poc_set_notify_mode(mp_obj_t value) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + int flags = mp_obj_get_int(value); + + POC_LOG("qpy_poc_set_notify_mode flag = %d\n",flags); + poc_ops->set_notify_mode(flags); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_notify_mode_obj, qpy_poc_set_notify_mode); +//set_notify_mode end + +//set_solution +STATIC mp_obj_t qpy_poc_set_solution(const mp_obj_t arg) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + char *solution = mp_obj_str_get_str(arg); + POC_LOG("qpy_poc_set_solution solution = %s\n",solution); + ret = poc_ops->set_solution(solution); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_solution_obj, qpy_poc_set_solution); +//set_solution end + +//set_solution_version +STATIC mp_obj_t qpy_poc_set_solution_version(const mp_obj_t arg) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + char *version = mp_obj_str_get_str(arg); + POC_LOG("poc version = %s\n",version); + ret = poc_ops->set_solution_version(version); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_solution_version_obj, qpy_poc_set_solution_version); +//set_solution_version end + +//set_productInfo +STATIC mp_obj_t qpy_poc_set_productInfo(const mp_obj_t arg) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + char *productInfo = mp_obj_str_get_str(arg); + POC_LOG("poc productinfo = %s\n", productInfo); + ret = poc_ops->set_productInfo(productInfo); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_productInfo_obj, qpy_poc_set_productInfo); +//set_productInfo end + +//set_manufacturer +STATIC mp_obj_t qpy_poc_set_manufacturer(const mp_obj_t arg) +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + char *manufacturer = mp_obj_str_get_str(arg); + POC_LOG("poc manufacturer = %s\n",manufacturer); + ret = poc_ops->set_manufacturer(manufacturer); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_poc_set_manufacturer_obj, qpy_poc_set_manufacturer); +//set_manufacturer end + +//get_init_status +STATIC mp_obj_t qpy_poc_get_init_status() +{ + poc_ops_t *poc_ops = poc_get_ops(); + int ret = 0; + ret = poc_ops->get_init_status(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_poc_get_init_status_obj, qpy_poc_get_init_status); +//get_init_status end + + +STATIC const mp_rom_map_elem_t mp_module_poc_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_poc) }, + + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&qpy_poc_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&qpy_poc_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_log), MP_ROM_PTR(&qpy_poc_log_obj) }, +#if 1 + { MP_ROM_QSTR(MP_QSTR_login), MP_ROM_PTR(&qpy_poc_login_obj) }, + { MP_ROM_QSTR(MP_QSTR_logout), MP_ROM_PTR(&qpy_poc_logout_obj) }, + { MP_ROM_QSTR(MP_QSTR_joingroup), MP_ROM_PTR(&qpy_poc_joingroup_obj) }, + { MP_ROM_QSTR(MP_QSTR_leavegroup), MP_ROM_PTR(&qpy_poc_leavegroup_obj) }, + { MP_ROM_QSTR(MP_QSTR_speak), MP_ROM_PTR(&qpy_poc_speak_obj) }, + { MP_ROM_QSTR(MP_QSTR_calluser), MP_ROM_PTR(&qpy_poc_calluser_obj) }, + { MP_ROM_QSTR(MP_QSTR_group_getbyindex), MP_ROM_PTR(&qpy_poc_group_getbyindex_obj) }, + { MP_ROM_QSTR(MP_QSTR_group_getbyid), MP_ROM_PTR(&qpy_poc_group_getbyid_obj) }, + { MP_ROM_QSTR(MP_QSTR_member_getbyid), MP_ROM_PTR(&qpy_poc_member_getbyid_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_loginstate), MP_ROM_PTR(&qpy_poc_get_loginstate_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_groupcount), MP_ROM_PTR(&qpy_poc_get_groupcount_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_grouplist), MP_ROM_PTR(&qpy_poc_get_grouplist_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_membercount), MP_ROM_PTR(&qpy_poc_get_membercount_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_memberlist), MP_ROM_PTR(&qpy_poc_get_memberlist_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_audiostate), MP_ROM_PTR(&qpy_poc_get_audiostate_obj) }, + { MP_ROM_QSTR(MP_QSTR_play_tts), MP_ROM_PTR(&qpy_poc_play_tts_obj) }, + { MP_ROM_QSTR(MP_QSTR_send_ping), MP_ROM_PTR(&qpy_poc_send_ping_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_send_gpsinfo), MP_ROM_PTR(&qpy_poc_send_gpsinfo_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_version), MP_ROM_PTR(&qpy_poc_get_version_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_current_zone_time), MP_ROM_PTR(&qpy_poc_current_zone_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_tts_enable), MP_ROM_PTR(&qpy_poc_set_tts_enable_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_set_vol), MP_ROM_PTR(&qpy_poc_set_vol_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_get_vol), MP_ROM_PTR(&qpy_poc_get_vol_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_get_account_day), MP_ROM_PTR(&qpy_poc_get_account_day_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_set_rec_audio_mode), MP_ROM_PTR(&qpy_poc_set_rec_audio_mode_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_get_rec_audio_coun), MP_ROM_PTR(&qpy_poc_get_rec_audio_coun_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_get_rec_audio_info), MP_ROM_PTR(&qpy_poc_get_rec_audio_info_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_play_rec_audio), MP_ROM_PTR(&qpy_poc_play_rec_audio_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_stop_play_rec_audio), MP_ROM_PTR(&qpy_poc_stop_play_rec_audio_obj) }, + + { MP_ROM_QSTR(MP_QSTR_register_audio_cb), MP_ROM_PTR(&qpy_poc_register_audio_cb_obj) }, + { MP_ROM_QSTR(MP_QSTR_register_join_group_cb), MP_ROM_PTR(&qpy_poc_register_join_group_cb_obj) }, + { MP_ROM_QSTR(MP_QSTR_register_listupdate_cb), MP_ROM_PTR(&qpy_poc_register_listupdate_cb_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_call_auto_leave_temp_group), MP_ROM_PTR(&qpy_poc_set_call_auto_leave_temp_group_obj) }, + //... + { MP_ROM_QSTR(MP_QSTR_set_call_end_timeptr), MP_ROM_PTR(&qpy_poc_set_call_end_timeptr_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_set_call_end_timeptr), MP_ROM_PTR(&qpy_poc_set_call_end_timeptr_obj) }, + //... + { MP_ROM_QSTR(MP_QSTR_register_upgrade_cb), MP_ROM_PTR(&qpy_poc_register_upgrade_cb_obj) }, + //... + { MP_ROM_QSTR(MP_QSTR_set_notify_mode), MP_ROM_PTR(&qpy_poc_set_notify_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_solution), MP_ROM_PTR(&qpy_poc_set_solution_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_solution_version), MP_ROM_PTR(&qpy_poc_set_solution_version_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_productInfo), MP_ROM_PTR(&qpy_poc_set_productInfo_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_manufacturer), MP_ROM_PTR(&qpy_poc_set_manufacturer_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_init_status), MP_ROM_PTR(&qpy_poc_get_init_status_obj) }, + #endif +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_poc_globals, mp_module_poc_globals_table); + + +const mp_obj_module_t mp_module_poc = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_poc_globals, +}; + + + + diff --git a/ports/quectel/core/source/modqrcode.c b/ports/quectel/core/source/modqrcode.c new file mode 100644 index 0000000..11ed7d3 --- /dev/null +++ b/ports/quectel/core/source/modqrcode.c @@ -0,0 +1,166 @@ +/* + * 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 modqrcode.c + * @author felix.ye + * @version V1.0.0 + * @date 2021/11/4 + * @brief xxx + ****************************************************************************** + */ +#include +#include + +#include "runtime.h" +#include "gc.h" +#include "mphal.h" +#include "mperrno.h" + +#include "helios_os.h" +#include "helios_lcd.h" +#include "QR_Encode.h" + + + +unsigned short *qrcode_data = NULL; +static Helios_Mutex_t qrcode_MutexRef = 0; +static int first_show = 1; + + +static int qrcode_amplification(unsigned int qrcode_size, unsigned int magnification, + unsigned short Background_color, unsigned short Foreground_color) { + + unsigned int i = 0, j = 0, k = 0, l = 0; + + //unsigned short * qrcode = NULL; + if(qrcode_data != NULL) { + free(qrcode_data); + qrcode_data = NULL; + } + + qrcode_data = calloc(qrcode_size*qrcode_size*magnification*magnification,sizeof(unsigned short)); + if(qrcode_data == NULL) return -1; + + for(i = 0; i < qrcode_size; i++) { + for(j = 0; j < qrcode_size ; j++) { + if(m_byModuleData[i][j] == 1) { + for(k = 0; k < magnification; k++) { + for(l = 0; l < magnification; l++) { + qrcode_data[(magnification * i+k)*qrcode_size * magnification + (magnification * j+l)] = Foreground_color; + } + } + } + else { + for(k = 0; k < magnification; k++) { + for(l = 0; l < magnification; l++) { + qrcode_data[(magnification * i+k)*qrcode_size * magnification + (magnification * j+l)] = Background_color; + } + } + } + + } + } + + return 0; + +} + + +int qpy_qrcode_show(char *qrcode_str, unsigned int magnification, + unsigned int start_x, unsigned start_y,unsigned short Background_color, unsigned short Foreground_color) { + + int ret = 0; + + if(first_show == 1) { + qrcode_MutexRef = Helios_Mutex_Create(); + first_show = 0; + } + + int ret1 = Helios_Mutex_Lock(qrcode_MutexRef, HELIOS_WAIT_FOREVER); + memset(m_byModuleData,0,sizeof(m_byModuleData)); + + int qrcode_size = EncodeData(qrcode_str); + + if(qrcode_size < 0) { + ret = -1; + goto lopo; + } + + if(qrcode_amplification(qrcode_size, magnification,Background_color,Foreground_color) < 0) { + ret = -2; + goto lopo; + } + if(Helios_LCD_Write((unsigned char*)qrcode_data, start_x, start_y, start_x+qrcode_size*magnification-1, start_y+qrcode_size*magnification-1) != 0) { + ret = -3; + goto lopo; + } + + +lopo: + if(qrcode_data != NULL) { + free(qrcode_data); + qrcode_data = NULL; + } + if(!ret1) + Helios_Mutex_Unlock(qrcode_MutexRef); + return ret; +} + + + +STATIC mp_obj_t qrcode_show(size_t n_args, const mp_obj_t *args) +{ + int ret = 0; + const char* qrcode_str = mp_obj_str_get_str(args[0]); + if(strlen(qrcode_str) > 192) mp_raise_ValueError("String length cannot exceed 192"); + + int magnification = mp_obj_get_int(args[1]); + if(magnification < 1 || magnification > 6) mp_raise_ValueError("Wrong magnification"); + + unsigned int start_x = mp_obj_get_int(args[2]); + unsigned int start_y = mp_obj_get_int(args[3]); + + unsigned short Background_color = 0xffff; + unsigned short Foreground_color = 0x0000; + + + if(n_args == 6) { + Background_color = (unsigned short)mp_obj_get_int(args[4]); + Foreground_color = (unsigned short)mp_obj_get_int(args[5]); + } + + + ret = qpy_qrcode_show((char*)qrcode_str, magnification, start_x,start_y,Background_color,Foreground_color); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qrcode_show_obj, 4, 6, qrcode_show); + + +STATIC const mp_rom_map_elem_t mp_module_qrcode_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sim) }, + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&qrcode_show_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_qrcode_globals, mp_module_qrcode_globals_table); + + +const mp_obj_module_t mp_module_qrcode = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_qrcode_globals, +}; + + diff --git a/ports/quectel/core/source/modquecIot.c b/ports/quectel/core/source/modquecIot.c index fe957c2..cc9f1f9 100644 --- a/ports/quectel/core/source/modquecIot.c +++ b/ports/quectel/core/source/modquecIot.c @@ -841,7 +841,7 @@ static qbool ttlv_dict_handle(const void *ttlv_head, quint32_t count, mp_obj_t n ** @param : ** @retval: ***************************************************************************/ -static mp_obj_t g_event_urc_cb = NULL; +static c_callback_t *g_event_urc_cb = NULL; static void FUNCTION_ATTR_ROM Ql_iotEventCB(quint32_t event, qint32_t errcode, const void *valueT, quint32_t valLen) { printf("\r\n******* event:%d,%d,%p *******\r\n", event, errcode, valueT); @@ -855,7 +855,7 @@ static void FUNCTION_ATTR_ROM Ql_iotEventCB(quint32_t event, qint32_t errcode, c { mp_obj_new_int_from_uint(event), mp_obj_new_int_from_uint(errcode)}; - mp_sched_schedule(g_event_urc_cb, mp_obj_new_tuple(2, tuple)); + mp_sched_schedule_ex(g_event_urc_cb, mp_obj_new_tuple(2, tuple)); } else if (QIOT_ATEVENT_TYPE_RECV == event && QIOT_RECV_SUCC_PHYMODEL_RECV == errcode) { @@ -868,7 +868,7 @@ static void FUNCTION_ATTR_ROM Ql_iotEventCB(quint32_t event, qint32_t errcode, c mp_obj_new_int_from_uint(event), mp_obj_new_int_from_uint(errcode), node_dict}; - mp_sched_schedule(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); } } else if(QIOT_ATEVENT_TYPE_RECV == event && QIOT_RECV_SUCC_PHYMODEL_REQ == errcode) @@ -889,7 +889,7 @@ static void FUNCTION_ATTR_ROM Ql_iotEventCB(quint32_t event, qint32_t errcode, c mp_obj_new_int_from_uint(event), mp_obj_new_int_from_uint(errcode), req_list}; - mp_sched_schedule(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); } else { @@ -898,7 +898,7 @@ static void FUNCTION_ATTR_ROM Ql_iotEventCB(quint32_t event, qint32_t errcode, c mp_obj_new_int_from_uint(event), mp_obj_new_int_from_uint(errcode), mp_obj_new_bytes(valueT, valLen)}; - mp_sched_schedule(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_event_urc_cb, mp_obj_new_tuple(3, tuple)); } } /************************************************************************** @@ -912,7 +912,11 @@ STATIC mp_obj_t qpy_Ql_iotConfigSetEventCB(mp_obj_t event_urc_cb) { return mp_obj_new_bool(FALSE); } - g_event_urc_cb = event_urc_cb; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_event_urc_cb = &cb; + mp_sched_schedule_callback_register(g_event_urc_cb, event_urc_cb); + Ql_iotConfigSetEventCB(Ql_iotEventCB); return mp_obj_new_bool(TRUE); } @@ -1083,8 +1087,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_Ql_iotCmdBusLocReport_obj, qpy_Ql_iotCmdBus ** @param : ** @retval: ***************************************************************************/ +STATIC mp_obj_t qpy_module_quecIot_deinit(void) +{ + g_event_urc_cb = NULL; + Ql_iotConfigSetConnmode(0); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_quecIot_deinit_obj, qpy_module_quecIot_deinit); + + STATIC const mp_rom_map_elem_t mp_module_quecIot_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_quecIot)}, + {MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_quecIot_deinit_obj) }, {MP_ROM_QSTR(MP_QSTR_passTransSend), MP_ROM_PTR(&qpy_Ql_iotCmdBusPassTransSend_obj)}, {MP_ROM_QSTR(MP_QSTR_phymodelReport), MP_ROM_PTR(&qpy_Ql_iotCmdBusPhymodelReport_obj)}, {MP_ROM_QSTR(MP_QSTR_phymodelAck), MP_ROM_PTR(&qpy_Ql_iotCmdBusPhymodelAck_obj)}, diff --git a/ports/quectel/core/source/modsecuredata.c b/ports/quectel/core/source/modsecuredata.c index 25c7b71..054ac17 100644 --- a/ports/quectel/core/source/modsecuredata.c +++ b/ports/quectel/core/source/modsecuredata.c @@ -104,12 +104,13 @@ STATIC mp_obj_t qpy_securedata_store(size_t n_args, const mp_obj_t *pos_args, mp Helios_SecureData_t sec_data = {0}; sec_data.index = index; sec_data.len = length; - sec_data.pBuffer = (uint8_t *)malloc(sizeof(uint8_t)*length); + sec_data.pBuffer = (uint8_t *)malloc(sizeof(uint8_t)*length + 1); if (sec_data.pBuffer == NULL) { m_malloc_fail(length); } - strncpy((char *)sec_data.pBuffer, (char *)bufinfo.buf, strlen((char *)bufinfo.buf)); + memcpy((char *)sec_data.pBuffer, (char *)bufinfo.buf, length); + sec_data.pBuffer[length] = 0; int ret = Helios_Securedata_Store(&sec_data); if (sec_data.pBuffer) diff --git a/ports/quectel/core/source/modsim.c b/ports/quectel/core/source/modsim.c index 4f56499..c3d4a11 100644 --- a/ports/quectel/core/source/modsim.c +++ b/ports/quectel/core/source/modsim.c @@ -111,8 +111,9 @@ STATIC mp_obj_t qpy_sim_get_phonenumber(void) return mp_obj_new_int(-1); } +#if !defined (PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_phonenumber_obj, qpy_sim_get_phonenumber); - +#endif /*=============================================================================*/ /* FUNCTION: qpy_sim_enable_pin */ @@ -496,7 +497,10 @@ STATIC mp_obj_t qpy_sim_set_simdet(const mp_obj_t obj_detenable, const mp_obj_t return mp_obj_new_int(-1); } + +#if !defined (PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_sim_set_simdet_obj, qpy_sim_set_simdet); +#endif STATIC mp_obj_t qpy_sim_get_simdet(void) { @@ -517,34 +521,87 @@ STATIC mp_obj_t qpy_sim_get_simdet(void) return mp_obj_new_int(-1); } +#if !defined (PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_sim_get_simdet_obj, qpy_sim_get_simdet); - -static mp_obj_t g_sim_user_callback; +#endif +static c_callback_t *g_sim_user_callback; static void qpy_sim_event_handler(uint8_t sim_id, unsigned int event_id, void *ctx) { if(g_sim_user_callback) { QPY_MODSIM_LOG("[SIM] callback start.\r\n"); - mp_sched_schedule(g_sim_user_callback, mp_obj_new_int(event_id)); + mp_sched_schedule_ex(g_sim_user_callback, mp_obj_new_int(event_id)); QPY_MODSIM_LOG("[SIM] callback end.\r\n"); } } STATIC mp_obj_t qpy_sim_add_event_handler(mp_obj_t handler) { - g_sim_user_callback = handler; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_sim_user_callback = &cb; + mp_sched_schedule_callback_register(g_sim_user_callback, handler); + Helios_SIM_Add_Event_Handler(qpy_sim_event_handler); return mp_obj_new_int(0); } +#if !defined (PLAT_RDA) STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_sim_add_event_handler_obj, qpy_sim_add_event_handler); +#endif + +STATIC mp_obj_t qpy_module_sim_deinit(void) +{ + g_sim_user_callback = NULL; + Helios_SIM_Add_Event_Handler(NULL); + return mp_obj_new_int(0); +} +#if !defined (PLAT_RDA) +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_sim_deinit_obj, qpy_module_sim_deinit); +#endif + +#if defined (PLAT_ASR) +STATIC mp_obj_t qpy_sim_genericaccess(const mp_obj_t sim_id, const mp_obj_t cmd) +{ + Helios_SIMGenericAccesStruct info = {0}; + int simid = mp_obj_get_int(sim_id); + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(cmd, &bufinfo, MP_BUFFER_READ); + + if (bufinfo.len <= 0) + { + mp_raise_ValueError("invalid value, the length of cmd should be more than 0 bytes."); + } + + if (simid > 1 || simid < 0) + { + mp_raise_ValueError("invalid value, simid should be 0 or 1."); + } + + strncpy((char *)info.cmd, (const char *)bufinfo.buf, bufinfo.len); + info.len = bufinfo.len; + int ret = Helios_SIM_GenericAccess(simid, &info); + if (ret == 0) + { + mp_obj_t tuple[2] = + { + mp_obj_new_int(strlen(info.resp)), + mp_obj_new_str(info.resp, strlen(info.resp)), + }; + return mp_obj_new_tuple(2, tuple); + //return mp_obj_new_str(info.resp, strlen(info.resp)); + } + return mp_obj_new_int(-1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_sim_genericaccess_obj, qpy_sim_genericaccess); +#endif STATIC const mp_rom_map_elem_t mp_module_sim_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sim) }, { MP_ROM_QSTR(MP_QSTR_getImsi), MP_ROM_PTR(&qpy_sim_get_imsi_obj) }, { MP_ROM_QSTR(MP_QSTR_getIccid), MP_ROM_PTR(&qpy_sim_get_iccid_obj) }, - { MP_ROM_QSTR(MP_QSTR_getPhoneNumber), MP_ROM_PTR(&qpy_sim_get_phonenumber_obj)}, + { MP_ROM_QSTR(MP_QSTR_verifyPin), MP_ROM_PTR(&qpy_sim_verify_pin_obj) }, { MP_ROM_QSTR(MP_QSTR_changePin), MP_ROM_PTR(&qpy_sim_change_pin_obj) }, { MP_ROM_QSTR(MP_QSTR_unblockPin), MP_ROM_PTR(&qpy_sim_unblock_pin_obj) }, @@ -552,12 +609,17 @@ STATIC const mp_rom_map_elem_t mp_module_sim_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_disablePin), MP_ROM_PTR(&qpy_sim_disable_pin_obj) }, { MP_ROM_QSTR(MP_QSTR_getStatus), MP_ROM_PTR(&qpy_sim_get_card_status_obj)}, #if defined (PLAT_ASR) - { MP_ROM_QSTR(MP_QSTR_readPhonebook), MP_ROM_PTR(&qpy_sim_read_phonebook_record_obj) }, - { MP_ROM_QSTR(MP_QSTR_writePhonebook), MP_ROM_PTR(&qpy_sim_write_phonebook_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_readPhonebook), MP_ROM_PTR(&qpy_sim_read_phonebook_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_writePhonebook), MP_ROM_PTR(&qpy_sim_write_phonebook_record_obj) }, + { MP_ROM_QSTR(MP_QSTR_genericAccess), MP_ROM_PTR(&qpy_sim_genericaccess_obj) }, +#endif +#if !defined (PLAT_RDA) + { MP_ROM_QSTR(MP_QSTR_setSimDet), MP_ROM_PTR(&qpy_sim_set_simdet_obj) }, + { MP_ROM_QSTR(MP_QSTR_getSimDet), MP_ROM_PTR(&qpy_sim_get_simdet_obj) }, + { MP_ROM_QSTR(MP_QSTR_getPhoneNumber), MP_ROM_PTR(&qpy_sim_get_phonenumber_obj)}, + { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_sim_add_event_handler_obj) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_sim_deinit_obj) }, #endif - { MP_ROM_QSTR(MP_QSTR_setSimDet), MP_ROM_PTR(&qpy_sim_set_simdet_obj) }, - { MP_ROM_QSTR(MP_QSTR_getSimDet), MP_ROM_PTR(&qpy_sim_get_simdet_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCallback), MP_ROM_PTR(&qpy_sim_add_event_handler_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_sim_globals, mp_module_sim_globals_table); diff --git a/ports/quectel/core/source/modslipif.c b/ports/quectel/core/source/modslipif.c new file mode 100644 index 0000000..fba242b --- /dev/null +++ b/ports/quectel/core/source/modslipif.c @@ -0,0 +1,196 @@ +/* + * 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 "string.h" + +#include "helios_audio.h" +#include "helios_debug.h" + +#include "slipif.h" +#include "netif.h" +#include "ip4.h" + +#include "obj.h" +#include "runtime.h" +#include "mphalport.h" +#include "helios_debug.h" + + + +extern const mp_obj_type_t slipif_type; + +#define sl_name "slip" +struct netif sl_netif; +static Helios_UARTNum global_dev; + + +unsigned long user_inet_addr(const char *str) +{ + unsigned long lHost = 0; + int i = 1, j = 1; + const char *pstr[4] = { NULL }; + pstr[0] = strchr(str, '.'); + pstr[1] = strchr(pstr[0] + 1, '.'); + pstr[2] = strchr(pstr[1] + 1, '.'); + pstr[3] = strchr(str, '\0'); + + for (j = 0; j < 4; j++) + { + i = 1; + if (j == 0) + { + while (str != pstr[0]) + { + lHost += (*--pstr[j] - '0') * i; + i *= 10; + } + } + else + { + while (*--pstr[j] != '.') + { + lHost += (*pstr[j] - '0') * i << 8 * j; + i *= 10; + } + } + } + return lHost; +} + + +static int _netif_init(char *ip_str, char *netmask_str, char *gw_str) +{ + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gw; + int ret = 1; + //char ip4_addr_str[16] = {0}; + //slip_log("user_netif_init start! port = %d\n", port); + + struct netif *temp; + memset(&sl_netif, 0x00, sizeof(sl_netif)); + ipaddr.addr = user_inet_addr(ip_str); + netmask.addr = user_inet_addr(netmask_str); + gw.addr = user_inet_addr(gw_str); + + temp = netif_add(&sl_netif, &ipaddr, &netmask, &gw, &global_dev, slipif_init, ip_input); + if( temp == NULL ) { + // slip_log("fail to netif init---------------\n"); + return -1; + } + sl_netif.hostname = sl_name; + netif_set_up(&sl_netif); + netif_set_link_up(&sl_netif); + return ret; +} + + +STATIC mp_obj_t qpy_slipif_construct(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + int ret = 0; + enum { ARG_port = 0, ARG_ip, ARG_netmask, ARG_gw}; + static const mp_arg_t allowed_args[] = + { + { MP_QSTR_port, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_slipIp, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_slipNetmask, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_slipGW, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + + int new_port = 0; + new_port = vals[ARG_port].u_int; + char *ip_str = (char *)mp_obj_str_get_str(vals[ARG_ip].u_obj); + char *netmask_str = (char *)mp_obj_str_get_str(vals[ARG_netmask].u_obj); + char *gw_str = (char *)mp_obj_str_get_str(vals[ARG_gw].u_obj); + + global_dev = (Helios_UARTNum)new_port; + + ret = _netif_init(ip_str, netmask_str, gw_str); + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(qpy_slipif_construct_obj, 1, qpy_slipif_construct); + +STATIC mp_obj_t qpy_slipif_netif_set_default(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + static const mp_arg_t allowed_args[] = + { + { MP_QSTR_slipExternalIp, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + + char *ip_str = (char *)mp_obj_str_get_str(vals[0].u_obj); + ip_addr_t ipaddr; + ipaddr.addr = user_inet_addr(ip_str); + int ret = slipif_netif_set_default(ipaddr.addr); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(qpy_slipif_netif_set_default_obj, 1, qpy_slipif_netif_set_default); + + +STATIC mp_obj_t qpy_slipif_set_mtu(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + static const mp_arg_t allowed_args[] = + { + { MP_QSTR_slipIp, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + + unsigned int mtu = vals[0].u_int; + if( mtu > 1500 ) return mp_obj_new_int(-1); + sl_netif.mtu = mtu; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(qpy_slipif_set_mtu_obj, 1, qpy_slipif_set_mtu); + +STATIC mp_obj_t qpy_slipif_destroy(mp_obj_t self_in) +{ + (void)self_in; + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_slipif_destroy_obj, qpy_slipif_destroy); + +STATIC const mp_rom_map_elem_t slipif_module_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_construct), MP_ROM_PTR(&qpy_slipif_construct_obj) }, + { MP_ROM_QSTR(MP_QSTR_netif_set_default), MP_ROM_PTR(&qpy_slipif_netif_set_default_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_smtu), MP_ROM_PTR(&qpy_slipif_set_mtu_obj) }, + { MP_ROM_QSTR(MP_QSTR_destroy), MP_ROM_PTR(&qpy_slipif_destroy_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(slipif_module_dict, slipif_module_dict_table); +#if 0 +const mp_obj_type_t slipif_type = { + { &mp_type_type }, + // .name = MP_QSTR_SLIPIF, + .locals_dict = (mp_obj_dict_t *)&slipif_locals_dict, +}; +#endif +const mp_obj_module_t module_slip = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&slipif_module_dict, +}; + + + + +// 1. 构建(串口,ip,netmask,gw) +// 2. 设置默认网卡 +// 3. 设置mtu +// 4. 关闭 + diff --git a/ports/quectel/core/source/modsms.c b/ports/quectel/core/source/modsms.c index 296fc45..c4eef8b 100644 --- a/ports/quectel/core/source/modsms.c +++ b/ports/quectel/core/source/modsms.c @@ -23,7 +23,7 @@ #define QPY_MODSMS_LOG(msg, ...) custom_log("SMS", msg, ##__VA_ARGS__) -static mp_obj_t g_sms_user_callback; +static c_callback_t *g_sms_user_callback = NULL; STATIC mp_obj_t qpy_sms_pdu_decode(mp_obj_t data, mp_obj_t datalen) { @@ -243,10 +243,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_sms_get_center_address_obj, qpy_sms_get_cen STATIC mp_obj_t qpy_sms_set_center_address(mp_obj_t address) { char *addr = (char *)mp_obj_str_get_str(address); - if (strlen(addr) > 30) + + //mia.zhong @20210816 + /*if (strlen(addr) > 30) { mp_raise_ValueError("invalid value, the length of center addr should be no more than 30 bytes."); - } + }*/ int ret = Helios_SMS_SetCenterAddress(0, (void *)addr); return mp_obj_new_int(ret); @@ -489,7 +491,7 @@ static void qpy_sms_event_handler(uint8_t sim_id, int32_t event_id, void *ctx) if (g_sms_user_callback) { QPY_MODSMS_LOG("[SMS] callback start.\r\n"); - mp_sched_schedule(g_sms_user_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_sms_user_callback, mp_obj_new_tuple(3, tuple)); QPY_MODSMS_LOG("[SMS] callback end.\r\n"); } } @@ -511,17 +513,30 @@ STATIC mp_obj_t qpy_sms_add_event_handler(mp_obj_t handler) Helios_SMSInitStruct info = {0}; info.user_cb = qpy_sms_event_handler; - g_sms_user_callback = handler; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_sms_user_callback = &cb; + mp_sched_schedule_callback_register(g_sms_user_callback, handler); + Helios_SMS_Init(&info); return mp_obj_new_int(0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_sms_add_event_handler_obj, qpy_sms_add_event_handler); - +STATIC mp_obj_t qpy_module_sms_deinit(void) +{ + g_sms_user_callback = NULL; + Helios_SMSInitStruct info = {0}; + info.user_cb = NULL; + Helios_SMS_Init(&info); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_sms_deinit_obj, qpy_module_sms_deinit); STATIC const mp_rom_map_elem_t mp_module_sms_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sms) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_sms_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_decodePdu), MP_ROM_PTR(&qpy_sms_pdu_decode_obj) }, { MP_ROM_QSTR(MP_QSTR_sendTextMsg), MP_ROM_PTR(&qpy_sms_send_text_msg_obj) }, { MP_ROM_QSTR(MP_QSTR_sendPduMsg), MP_ROM_PTR(&qpy_sms_send_pdu_msg_obj) }, diff --git a/ports/quectel/core/source/modsocket.c b/ports/quectel/core/source/modsocket.c index bb4d996..2528bc5 100644 --- a/ports/quectel/core/source/modsocket.c +++ b/ports/quectel/core/source/modsocket.c @@ -31,11 +31,13 @@ //#include "mdns.h" //#include "modnetwork.h" +#if !defined(PLAT_Qualcomm) #include "sockets.h" #include "netdb.h" #include "ip4.h" #include "igmp.h" #include "netif.h" +#endif #include "helios_debug.h" #if !defined(PLAT_RDA) #include "helios_datacall.h" @@ -52,6 +54,10 @@ //#define lwip_close lwip_close_r //#endif +#if defined(PLAT_Qualcomm) +#define TCP_KEEPALIVE 0x02 +#endif + #define QPY_SOCKET_LOG(msg, ...) custom_log(modsocket, msg, ##__VA_ARGS__) #define SOCKET_POLL_US (100000) @@ -68,6 +74,7 @@ typedef struct _socket_obj_t { uint8_t proto; bool peer_closed; unsigned int retries; + unsigned int timeout; #if MICROPY_PY_USOCKET_EVENTS mp_obj_t events_callback; struct _socket_obj_t *events_next; @@ -91,7 +98,7 @@ void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms); STATIC uint8_t usocket_events_divisor; STATIC socket_obj_t *usocket_events_head; -STATIC uint32_t usocket_timeout = 0; +//STATIC uint32_t usocket_timeout = 0; void usocket_events_deinit(void) { usocket_events_head = NULL; @@ -166,25 +173,36 @@ static inline void check_for_exceptions(void) { // This function mimics lwip_getaddrinfo, with added support for mDNS queries static int _socket_getaddrinfo3(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { +#if defined(PLAT_ASR) + if (netif_get_default_nw()) { + return getaddrinfo(nodename, servname, hints, res); + } else { +#endif + // Normal query + //uart_printf("getaddrinfo_with_pcid, nodename %s, servname %s\r\n", nodename, servname); + /* + ** Jayceon 2020/12/03 --part1 begin-- + ** Solve the problem of not being able to connect to the Internet after dialing + ** with a PDP other than the first PDP . + */ + #if defined(PLAT_RDA) || defined(PLAT_Qualcomm) + int pdp = 1; + #else + int pdp = Helios_DataCall_GetCurrentPDP(); + #endif - // Normal query - //uart_printf("getaddrinfo_with_pcid, nodename %s, servname %s\r\n", nodename, servname); - /* - ** Jayceon 2020/12/03 --part1 begin-- - ** Solve the problem of not being able to connect to the Internet after dialing - ** with a PDP other than the first PDP . - */ -#if defined(PLAT_RDA) - int pdp = 1; -#else - int pdp = Helios_DataCall_GetCurrentPDP(); + return getaddrinfo_with_pcid(nodename, servname, hints, res, pdp); + /* Jayceon 2020/12/03 --part1 end-- */ +#if defined(PLAT_ASR) + } #endif - return getaddrinfo_with_pcid(nodename, servname, hints, res, pdp); - /* Jayceon 2020/12/03 --part1 end-- */ } static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { const struct addrinfo hints = { +#if defined(PLAT_Qualcomm) + .ai_flags = AI_CANONNAME, +#endif .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, }; @@ -244,85 +262,101 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz sock->fd = lwip_socket(sock->domain, sock->type, sock->proto); if (sock->fd < 0) { QPY_SOCKET_LOG("lwip_socket: create socket failed!\r\n"); +#if defined(PLAT_Qualcomm) + exception_from_errno(errno(sock->fd)); +#else exception_from_errno(errno); +#endif } - /* - ** Jayceon 2020/12/03 --part2 begin-- - ** Solve the problem of not being able to connect to the Internet after dialing - ** with a PDP other than the first PDP . - */ -#if defined(PLAT_RDA) - int pdp = 1; - struct netif* netif_cfg = netif_get_by_cid(pdp); + +#if defined(PLAT_Qualcomm) + _socket_settimeout(sock, UINT64_MAX); + return MP_OBJ_FROM_PTR(sock); #else - int pdp = Helios_DataCall_GetCurrentPDP(); -#if defined (PLAT_Unisoc) - struct netif* netif_cfg = netif_get_by_cid(pdp); -#elif defined (PLAT_ASR) - struct netif* netif_cfg = netif_get_by_cid(pdp - 1); -#endif +#if defined(PLAT_ASR) + if (!netif_get_default_nw()) { #endif + /* + ** Jayceon 2020/12/03 --part2 begin-- + ** Solve the problem of not being able to connect to the Internet after dialing + ** with a PDP other than the first PDP . + */ + #if defined(PLAT_RDA) + int pdp = 1; + struct netif* netif_cfg = netif_get_by_cid(pdp); + #else + int pdp = Helios_DataCall_GetCurrentPDP(); + #if defined (PLAT_Unisoc) + struct netif* netif_cfg = netif_get_by_cid(pdp); + #elif defined (PLAT_ASR) + struct netif* netif_cfg = netif_get_by_cid(pdp - 1); + #endif + #endif - /* Jayceon 2020/12/03 --part2 end-- */ - if(netif_cfg) - { - if (sock->domain == AF_INET) + /* Jayceon 2020/12/03 --part2 end-- */ + if(netif_cfg) { - struct sockaddr_in local_v4; - local_v4.sin_family = AF_INET; - local_v4.sin_port = 0; -#if defined (PLAT_Unisoc) || defined(PLAT_RDA) - local_v4.sin_addr.s_addr = netif_cfg->ip_addr.u_addr.ip4.addr; -#elif defined (PLAT_ASR) - local_v4.sin_addr.s_addr = netif_cfg->ip_addr.addr; -#endif - if(lwip_bind(sock->fd,(struct sockaddr *)&local_v4,sizeof(struct sockaddr))) + if (sock->domain == AF_INET) { - //bind failed. - QPY_SOCKET_LOG("[socket]bind IPV4 failed.\r\n"); - exception_from_errno(errno); + struct sockaddr_in local_v4; + local_v4.sin_family = AF_INET; + local_v4.sin_port = 0; + #if defined (PLAT_Unisoc) || defined(PLAT_RDA) + local_v4.sin_addr.s_addr = netif_cfg->ip_addr.u_addr.ip4.addr; + #elif defined (PLAT_ASR) + local_v4.sin_addr.s_addr = netif_cfg->ip_addr.addr; + #endif + if(lwip_bind(sock->fd,(struct sockaddr *)&local_v4,sizeof(struct sockaddr))) + { + //bind failed. + QPY_SOCKET_LOG("[socket]bind IPV4 failed.\r\n"); + exception_from_errno(errno); + } + else + { + QPY_SOCKET_LOG("[socket]bind IPV4 success.\r\n"); + } } - else + else if (sock->domain == AF_INET6) { - QPY_SOCKET_LOG("[socket]bind IPV4 success.\r\n"); + struct sockaddr_in6 local_v6; + + #if defined (PLAT_Unisoc) + const ip6_addr_t * ip6_addr_ptr = NULL; + ip6_addr_ptr = netif_ip6_addr(netif_cfg, 1); + memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); + #elif defined (PLAT_ASR) + ip6_addr_t * ip6_addr_ptr = NULL; + ip6_addr_ptr = netif_get_global_ip6addr(netif_cfg); + memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); + #endif + local_v6.sin6_family = AF_INET6; + local_v6.sin6_port = 0; + if(lwip_bind(sock->fd,(struct sockaddr *)&local_v6,sizeof(struct sockaddr_in6))) + { + //bind failed. + QPY_SOCKET_LOG("[socket]bind IPV6 failed.\r\n"); + exception_from_errno(errno); + } + else + { + QPY_SOCKET_LOG("[socket]bind IPV6 success.\r\n"); + } } } - else if (sock->domain == AF_INET6) + else { - struct sockaddr_in6 local_v6; - -#if defined (PLAT_Unisoc) - const ip6_addr_t * ip6_addr_ptr = NULL; - ip6_addr_ptr = netif_ip6_addr(netif_cfg, 1); - memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); -#elif defined (PLAT_ASR) - ip6_addr_t * ip6_addr_ptr = NULL; - ip6_addr_ptr = netif_get_global_ip6addr(netif_cfg); - memcpy(&local_v6.sin6_addr, ip6_addr_ptr, sizeof(ip6_addr_t)); -#endif - local_v6.sin6_family = AF_INET6; - local_v6.sin6_port = 0; - if(lwip_bind(sock->fd,(struct sockaddr *)&local_v6,sizeof(struct sockaddr_in6))) - { - //bind failed. - QPY_SOCKET_LOG("[socket]bind IPV6 failed.\r\n"); - exception_from_errno(errno); - } - else - { - QPY_SOCKET_LOG("[socket]bind IPV6 success.\r\n"); - } + QPY_SOCKET_LOG("[socket]find netif cfg failed..\r\n"); } - } - else - { - QPY_SOCKET_LOG("[socket]find netif cfg failed..\r\n"); - } - //end + //end +#if defined(PLAT_ASR) + } +#endif _socket_settimeout(sock, UINT64_MAX); return MP_OBJ_FROM_PTR(sock); +#endif } STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { @@ -332,7 +366,11 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { int r = lwip_bind(self->fd, res->ai_addr, res->ai_addrlen); lwip_freeaddrinfo(res); if (r < 0) { +#if defined(PLAT_Qualcomm) + exception_from_errno(errno(self->fd)); +#else exception_from_errno(errno); +#endif } return mp_const_none; } @@ -343,7 +381,11 @@ STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) { int backlog = mp_obj_get_int(arg1); int r = lwip_listen(self->fd, backlog); if (r < 0) { +#if defined(PLAT_Qualcomm) + exception_from_errno(errno(self->fd)); +#else exception_from_errno(errno); +#endif } return mp_const_none; } @@ -363,9 +405,16 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { if (new_fd >= 0) { break; } +#if defined(PLAT_Qualcomm) + int socket_error = errno(self->fd); + if (socket_error != 11) { + exception_from_errno(socket_error); + } +#else if (errno != EAGAIN) { exception_from_errno(errno); } +#endif check_for_exceptions(); } if (new_fd < 0) { @@ -397,15 +446,40 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); +#if defined(PLAT_Qualcomm) +#define _htons(x) \ + ((unsigned short)((((unsigned short)(x) & 0x00ff) << 8) | \ + (((unsigned short)(x) & 0xff00) >> 8))) +#endif + STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - struct addrinfo *res; int r; +#if defined(PLAT_Qualcomm) + MP_THREAD_GIL_EXIT(); + + mp_obj_t *elem; + mp_obj_get_array_fixed_n(arg1, 2, &elem); + const char *host_str = mp_obj_str_get_str(elem[0]); + + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = _htons(mp_obj_get_int(elem[1])); + server_addr.sin_addr.s_addr = inet_addr(host_str); + + r = lwip_connect(self->fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); + MP_THREAD_GIL_ENTER(); + if (r != 0) + { + exception_from_errno(errno(self->fd)); + } +#else + struct addrinfo *res; _socket_getaddrinfo(arg1, &res); MP_THREAD_GIL_EXIT(); - if (usocket_timeout > 0 && usocket_timeout < 25) + if (self->timeout > 0 && self->timeout < 25) { - QPY_SOCKET_LOG("socket_connect usocket_timeout = %d \r\n", usocket_timeout); + QPY_SOCKET_LOG("socket_connect usocket timeout = %d \r\n", self->timeout); int sock_nbio = 1; struct timeval t; fd_set read_fds, write_fds; @@ -415,7 +489,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { FD_SET(self->fd, &read_fds); FD_SET(self->fd, &write_fds); - t.tv_sec = usocket_timeout; + t.tv_sec = self->timeout; t.tv_usec = 0; lwip_ioctl(self->fd, FIONBIO, &sock_nbio); @@ -453,6 +527,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { MP_THREAD_GIL_ENTER(); lwip_freeaddrinfo(res); +#endif return mp_const_none; } @@ -470,7 +545,11 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { int val = mp_obj_get_int(args[3]); int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); if (ret != 0) { +#if defined(PLAT_Qualcomm) + exception_from_errno(errno(self->fd)); +#else exception_from_errno(errno); +#endif } break; } @@ -492,7 +571,11 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { optval = 3; ret = lwip_setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(int)); if (ret != 0) { +#if defined(PLAT_Qualcomm) + exception_from_errno(errno(self->fd)); +#else exception_from_errno(errno); +#endif } } break; @@ -548,7 +631,7 @@ void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { // if timeout_ms == UINT64_MAX, wait forever. sock->retries = (timeout_ms == UINT64_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US; - usocket_timeout = timeout_ms/1000; + sock->timeout = timeout_ms/1000; struct timeval timeout = { .tv_sec = 0, @@ -605,17 +688,50 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, return MP_STREAM_ERROR; } + unsigned int retries = 0; + if (sock->timeout > 5) + { + retries = ((sock->timeout/5) - 1); + } + else + { + retries = sock->retries; + } // XXX Would be nicer to use RTC to handle timeouts - for (unsigned int i = 0; i <= sock->retries; ++i) { + for (unsigned int i = 0; i <= retries; ++i) { + if (sock->timeout > 5) + { + unsigned int retries_i = 0; + retries_i = sock->timeout/5; + if (!((retries_i - 1) == retries)) + { + retries = retries_i; + } + } + else + { + retries = sock->retries; + } // Poll the socket to see if it has waiting data and only release the GIL if it doesn't. // This ensures higher performance in the case of many small reads, eg for readline. bool release_gil; { fd_set rfds; + int r = 0; FD_ZERO(&rfds); FD_SET(sock->fd, &rfds); - struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; - int r = lwip_select(sock->fd + 1, &rfds, NULL, NULL, &timeout); + MP_THREAD_GIL_EXIT(); + if (sock->timeout > 5) + { + struct timeval timeout = { .tv_sec = 5, .tv_usec = 0 }; + r = lwip_select(sock->fd + 1, &rfds, NULL, NULL, &timeout); + } + else + { + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + r = lwip_select(sock->fd + 1, &rfds, NULL, NULL, &timeout); + } + MP_THREAD_GIL_ENTER(); release_gil = r != 1; } if (release_gil) { @@ -625,9 +741,16 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, if (release_gil) { MP_THREAD_GIL_ENTER(); } +#if defined(PLAT_Qualcomm) + int socket_error = errno(sock->fd); +#endif if (r == 0) { sock->peer_closed = true; +#if defined(PLAT_Qualcomm) + if (socket_error == ENOTCONN)//recv FIN +#else if (errno == ENOTCONN)//recv FIN +#endif { *errcode = ENOTCONN; QPY_SOCKET_LOG("_socket_read_data recv FIN \n"); @@ -637,14 +760,21 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, if (r >= 0) { return r; } +#if defined(PLAT_Qualcomm) + if (socket_error != 6) { + *errcode = socket_error; + return MP_STREAM_ERROR; + } +#else if (errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } check_for_exceptions(); +#endif } - *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; + *errcode = retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; return MP_STREAM_ERROR; } @@ -690,9 +820,17 @@ int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { MP_THREAD_GIL_EXIT(); int r = lwip_write(sock->fd, data + sentlen, datalen - sentlen); MP_THREAD_GIL_ENTER(); +#if defined(PLAT_Qualcomm) + int socket_error = errno(sock->fd); + if (r < 0 && socket_error != 11) { + exception_from_errno(socket_error); + } +#else if (r < 0 && errno != EWOULDBLOCK) { exception_from_errno(errno); } +#endif + if (r > 0) { sentlen += r; } @@ -736,7 +874,9 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ // create the destination address struct sockaddr_in to; +#if !defined(PLAT_Qualcomm) to.sin_len = sizeof(to); +#endif to.sin_family = AF_INET; to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t *)&to.sin_addr, NETUTILS_BIG)); @@ -748,9 +888,16 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ if (ret > 0) { return mp_obj_new_int_from_uint(ret); } +#if defined(PLAT_Qualcomm) + int socket_error = errno(self->fd); + if (ret == -1 && socket_error != 11) { + exception_from_errno(socket_error); + } +#else if (ret == -1 && errno != EWOULDBLOCK) { exception_from_errno(errno); } +#endif check_for_exceptions(); } mp_raise_OSError(MP_ETIMEDOUT); @@ -794,10 +941,18 @@ STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_ if (r > 0) { return r; } +#if defined(PLAT_Qualcomm) + int socket_error = errno(sock->fd); + if (r < 0 && socket_error != 11) { + *errcode = socket_error; + return MP_STREAM_ERROR; + } +#else if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } +#endif check_for_exceptions(); } *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; @@ -852,7 +1007,11 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt #endif int ret = lwip_close(socket->fd); if (ret != 0) { +#if defined(PLAT_Qualcomm) + *errcode = errno(socket->fd); +#else *errcode = errno; +#endif return MP_STREAM_ERROR; } socket->fd = -1; @@ -969,14 +1128,19 @@ STATIC mp_obj_t socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { ip_addr_t ip4_addr = { .addr = addr->sin_addr.s_addr }; #endif char buf[16]; +#if defined (PLAT_Qualcomm) + //struct ipv4_info ip4_addr = { .addr = addr->sin_addr.s_addr }; + inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)); +#else ipaddr_ntoa_r(&ip4_addr, buf, sizeof(buf)); +#endif mp_obj_t inaddr_objs[2] = { mp_obj_new_str(buf, strlen(buf)), mp_obj_new_int(ntohs(addr->sin_port)) }; addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); } - +#if !defined (PLAT_Qualcomm) if (resi->ai_family == AF_INET6) { char ip6_addr_buf[128] = {0}; struct sockaddr_in6 *addr = (struct sockaddr_in6 *)resi->ai_addr; @@ -987,6 +1151,7 @@ STATIC mp_obj_t socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { }; addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); } +#endif mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs)); } diff --git a/ports/quectel/core/source/moduos.c b/ports/quectel/core/source/moduos.c index 93749d2..046ec82 100644 --- a/ports/quectel/core/source/moduos.c +++ b/ports/quectel/core/source/moduos.c @@ -27,6 +27,7 @@ #include "extmod/vfs_lfs.h" #include "mpversion.h" #include "helios_dev.h" +#include "extmod/vfs_efs.h" static char sysname[20] = {0}; @@ -147,7 +148,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, - { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, { MP_ROM_QSTR(MP_QSTR_uname2), MP_ROM_PTR(&os_uname2_obj) }, { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #if MICROPY_PY_OS_DUPTERM @@ -170,12 +171,17 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif +#if !defined(PLAT_Qualcomm) #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, #endif #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif +#endif + #if defined(PLAT_Qualcomm) + { MP_ROM_QSTR(MP_QSTR_VfsEfs), MP_ROM_PTR(&mp_type_vfs_efs) }, + #endif #endif }; diff --git a/ports/quectel/core/source/modutime.c b/ports/quectel/core/source/modutime.c index 9942893..e42f505 100644 --- a/ports/quectel/core/source/modutime.c +++ b/ports/quectel/core/source/modutime.c @@ -19,13 +19,14 @@ #include "runtime.h" #include "timeutils.h" #include "utime_mphal.h" +#if !defined(PLAT_Qualcomm) #include "sockets.h" +#endif #include "helios_debug.h" #include "helios_rtc.h" #define QPY_UTIME_LOG(msg, ...) custom_log(Utime, msg, ##__VA_ARGS__) - STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { timeutils_struct_time_t tm; mp_int_t seconds; @@ -179,13 +180,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_get_timezone_obj, time_get_timezone); STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, - { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, diff --git a/ports/quectel/core/source/modvoicecall.c b/ports/quectel/core/source/modvoicecall.c index f7c203a..9a9afb8 100644 --- a/ports/quectel/core/source/modvoicecall.c +++ b/ports/quectel/core/source/modvoicecall.c @@ -38,7 +38,7 @@ WHEN WHO WHAT,WHERE,WHY #include "helios_voicecall.h" -#define QPY_MODSMS_LOG(msg, ...) custom_log("VOICECALL", msg, ##__VA_ARGS__) +#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) @@ -115,7 +115,85 @@ STATIC mp_obj_t qpy_voicecall_fw_set(mp_obj_t mp_obj_reason, mp_obj_t mp_obj_fwm } STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_voice_call_fw_set_obj, qpy_voicecall_fw_set); -static mp_obj_t g_voice_call_callback; +#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) { @@ -139,7 +217,7 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c }; if (g_voice_call_callback) { - mp_sched_schedule(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); } } } @@ -161,7 +239,7 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c }; if (g_voice_call_callback) { - mp_sched_schedule(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); } } } @@ -180,7 +258,7 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c }; if (g_voice_call_callback) { - mp_sched_schedule(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(3, tuple)); } } } @@ -203,7 +281,58 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c }; if (g_voice_call_callback) { - mp_sched_schedule(g_voice_call_callback, mp_obj_new_tuple(5, tuple)); + 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)); } } } @@ -213,6 +342,9 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c 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) @@ -233,7 +365,7 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c }; if (g_voice_call_callback) { - mp_sched_schedule(g_voice_call_callback, mp_obj_new_tuple(9, tuple)); + mp_sched_schedule_ex(g_voice_call_callback, mp_obj_new_tuple(9, tuple)); } } } @@ -247,24 +379,45 @@ static void ql_voice_call_EventHandler(uint8_t sim_id, int32_t event_id, void *c 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 = 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) +{ + g_voice_call_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_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___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); diff --git a/ports/quectel/core/source/modwifiscan.c b/ports/quectel/core/source/modwifiscan.c index fce1256..84c6c5c 100644 --- a/ports/quectel/core/source/modwifiscan.c +++ b/ports/quectel/core/source/modwifiscan.c @@ -24,7 +24,7 @@ #define MOD_WIFISCAN_LOG(msg, ...) custom_log(wifiscan, msg, ##__VA_ARGS__) -static mp_obj_t g_wifiscan_callback = NULL; +static c_callback_t *g_wifiscan_callback = NULL; /*=============================================================================*/ @@ -328,7 +328,7 @@ static void qpy_wifiscan_callback(uint8_t msg_id, void *ctx) if (g_wifiscan_callback) { MOD_WIFISCAN_LOG("[wifi-scan] callback start.\r\n"); - mp_sched_schedule(g_wifiscan_callback, mp_obj_new_tuple(2, tuple)); + mp_sched_schedule_ex(g_wifiscan_callback, mp_obj_new_tuple(2, tuple)); MOD_WIFISCAN_LOG("[wifi-scan] callback end.\r\n"); } } @@ -347,7 +347,11 @@ static void qpy_wifiscan_callback(uint8_t msg_id, void *ctx) /*=============================================================================*/ STATIC mp_obj_t qpy_wifiscan_register_usr_cb(mp_obj_t callback) { - g_wifiscan_callback = callback; + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + g_wifiscan_callback = &cb; + mp_sched_schedule_callback_register(g_wifiscan_callback, callback); + Helios_WifiScanInitStruct info = {0}; info.user_cb = qpy_wifiscan_callback; Helios_WifiScan_Init(&info); @@ -355,9 +359,18 @@ STATIC mp_obj_t qpy_wifiscan_register_usr_cb(mp_obj_t callback) } STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_wifiscan_register_usr_cb_obj, qpy_wifiscan_register_usr_cb); +STATIC mp_obj_t qpy_module_wifiscan_deinit(void) +{ + MOD_WIFISCAN_LOG("module wifiScan deinit.\r\n"); + g_wifiscan_callback = NULL; + Helios_WifiScan_Deinit(); + return mp_obj_new_int(0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_module_wifiscan_deinit_obj, qpy_module_wifiscan_deinit); STATIC const mp_rom_map_elem_t mp_module_wifiscan_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wifiScan) }, + { MP_ROM_QSTR(MP_QSTR___qpy_module_deinit__), MP_ROM_PTR(&qpy_module_wifiscan_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_support), MP_ROM_PTR(&qpy_wifiscan_support_obj) }, { MP_ROM_QSTR(MP_QSTR_control), MP_ROM_PTR(&qpy_wifiscan_control_obj) }, { MP_ROM_QSTR(MP_QSTR_getState), MP_ROM_PTR(&qpy_wifiscan_get_state_obj) }, diff --git a/ports/quectel/core/source/mpconfigport.h b/ports/quectel/core/source/mpconfigport.h index 6351609..73ce854 100644 --- a/ports/quectel/core/source/mpconfigport.h +++ b/ports/quectel/core/source/mpconfigport.h @@ -41,7 +41,7 @@ #define MICROPY_STACK_CHECK (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (0) -#define MICROPY_PY_BUILTINS_MEMORYVIEW (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) #define MICROPY_PY_BUILTINS_SET (1) @@ -94,10 +94,14 @@ #endif #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_BUILTINS_INPUT (1) - +// jaxsen 2021-09-11 +#define MICROPY_PY_UASYNCIO (1) +#define MICROPY_PY_USELECT (1) +#define MICROPY_PY_UERRNO (1) +// 2021-09-11 #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) //decimal numbers support +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) //decimal numbers support #define MICROPY_USE_INTERNAL_PRINTF (0) #define MICROPY_REPL_AUTO_INDENT (1) //baron 2020/04/17 @@ -115,7 +119,7 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_PY_USOCKET_EVENTS (1) #define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_SCHEDULER_DEPTH (32) +#define MICROPY_SCHEDULER_DEPTH (64)//8 #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool @@ -134,9 +138,12 @@ #define MICROPY_PY_THREAD_GIL (1) #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) +#if CONFIG_MBEDTLS +#define MICROPY_PY_USSL (1) // (1) for original, modified by Chavis for compilation on 1/7/2021 +#define MICROPY_SSL_MBEDTLS (1) // (1) for original, modified by Chavis for compilation on 1/7/2021 +#endif + #if defined(PLAT_RDA) -#define MICROPY_PY_USSL (0) // (1) for original, modified by Chavis for compilation on 1/7/2021 -#define MICROPY_SSL_MBEDTLS (0) // (1) for original, modified by Chavis for compilation on 1/7/2021 #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_UHASHLIB_SHA256 (0) @@ -146,12 +153,13 @@ #define MICROPY_PY_UCRYPTOLIB (0) #define MICROPY_PY_UCRYPTOLIB_CTR (0) #define MICROPY_PY_UCRYPTOLIB_CONSTS (0) +#define MICROPY_PY_NB (1) +#define MICROPY_PY_NB_OC (1) +#define MICROPY_PY_NB_AEP (1) +#define MICROPY_PY_NB_ONENET (1) #else -#define MICROPY_PY_USSL (1) // (1) for original, modified by Chavis for compilation on 1/7/2021 -#define MICROPY_SSL_MBEDTLS (1) // (1) for original, modified by Chavis for compilation on 1/7/2021 - #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_SHA256 (1) #define MICROPY_PY_UHASHLIB_SHA1 (1) @@ -179,7 +187,11 @@ #define MICROPY_NLR_SETJMP (1) // optimisations +#if !defined(PLAT_Qualcomm) #define MICROPY_OPT_COMPUTED_GOTO (1) +#else +#define MICROPY_OPT_COMPUTED_GOTO (0)//forrest.liu@20210926 add for dump when python use "param = xxx" +#endif #define MICROPY_OPT_MPZ_BITWISE (1) // emitters @@ -205,10 +217,14 @@ typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; #if MICROPY_PY_USOCKET_EVENTS +#if !defined(PLAT_Qualcomm) #define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler(); #else #define MICROPY_PY_USOCKET_EVENTS_HANDLER #endif +#else +#define MICROPY_PY_USOCKET_EVENTS_HANDLER +#endif #define mp_type_fileio mp_type_vfs_lfs1_fileio @@ -221,6 +237,7 @@ extern const struct _mp_obj_module_t mp_module_hmacSha1; extern const struct _mp_obj_module_t mp_module_utils; extern const struct _mp_obj_type_t mp_ostimer_type; extern const struct _mp_obj_module_t mp_module_machine; +extern const struct _mp_obj_module_t mp_module_nb; extern const struct _mp_obj_module_t utime_module; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_net; @@ -228,6 +245,7 @@ extern const struct _mp_obj_module_t mp_module_dial; extern const struct _mp_obj_module_t mp_module_misc; extern const struct _mp_obj_module_t mp_module_quecgnss; extern const struct _mp_obj_module_t mp_module_sim; +extern const struct _mp_obj_module_t mp_module_pm; #if !defined(PLAT_RDA) //extern const struct _mp_obj_module_t mp_module_machine; @@ -245,7 +263,7 @@ extern const struct _mp_obj_module_t mp_module_audio; //extern const struct _mp_obj_module_t mp_module_misc; //extern const struct _mp_obj_module_t mp_module_net; //extern const struct _mp_obj_module_t mp_module_hmacSha1; -extern const struct _mp_obj_module_t mp_module_pm; +//extern const struct _mp_obj_module_t mp_module_pm; // end //extern const struct _mp_obj_type_t mp_ostimer_type; extern const struct _mp_obj_module_t mp_module_sms; @@ -255,9 +273,17 @@ extern const struct _mp_obj_module_t mp_module_wifiscan; //#define MICROPY_PORT_BUILTIN_MODULES extern const struct _mp_obj_module_t mp_module_bma250; + +#endif + +#if defined(PLAT_ASR) +extern const struct _mp_obj_module_t mp_module_ethernet; +#define MICROPY_PORT_BUILTIN_MODULES_ETHERNET { MP_OBJ_NEW_QSTR(MP_QSTR_ethernet), (mp_obj_t)&mp_module_ethernet }, +#else +#define MICROPY_PORT_BUILTIN_MODULES_ETHERNET #endif -#if defined(PLAT_ASR) || defined(PLAT_Unisoc) +#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}, #else @@ -271,7 +297,7 @@ extern const struct _mp_obj_module_t mp_module_lvgl; #define MICROPY_PORT_BUILTIN_MODULES_LVGL #endif -#ifdef CONFIG_QUECTHING +#if defined(CONFIG_QUECTHING) && (defined(PLAT_ASR) || defined(PLAT_Unisoc)) extern const struct _mp_obj_module_t mp_module_quecIot; #define MICROPY_PORT_BUILTIN_MODULES_QUECTHING { MP_OBJ_NEW_QSTR(MP_QSTR_quecIot), (mp_obj_t)&mp_module_quecIot}, #else @@ -285,7 +311,7 @@ extern const struct _mp_obj_module_t mp_module_camera; #define MICROPY_PORT_BUILTIN_MODULES_CAMERA #endif -#if defined(PLAT_Unisoc) +#if defined(CONFIG_BT) extern const struct _mp_obj_module_t mp_module_ble; #define MICROPY_PORT_BUILTIN_MODULES_BLE { MP_OBJ_NEW_QSTR(MP_QSTR_ble), (mp_obj_t)&mp_module_ble}, #else @@ -313,7 +339,10 @@ extern const struct _mp_obj_module_t mp_module_rtmp; #define MICROPY_PORT_BUILTIN_MODULES_RTMP #endif -#if defined(BOARD_EC600SCN_LA_VOLTE) || defined(BOARD_EC600NCN_LC_VOLTE) || defined(EC200UCN_AA) || defined(EC200UCN_AB) +//mia.zhong @20210901 +//#if defined(BOARD_EC600SCN_LA_VOLTE) || defined(BOARD_EC600NCN_LC_VOLTE) || defined(BOARD_EC200UCN_AA) || defined(BOARD_EC200UCN_AB) +//#if defined(PLAT_ASR) || defined(BOARD_EC600UCN_LB_VOLTE) || defined(BOARD_EC600UEU_AB_VOLTE) +#if defined(CONFIG_VIOCE_CALL) extern const struct _mp_obj_module_t mp_module_voicecall; #define MICROPY_PORT_BUILTIN_MODULES_VOICECALL { MP_OBJ_NEW_QSTR(MP_QSTR_voiceCall), (mp_obj_t)&mp_module_voicecall}, #else @@ -327,6 +356,30 @@ extern const struct _mp_obj_module_t module_SecureData; #define MICROPY_PORT_BUILTIN_MODULES_SECUREDATA #endif +#if defined(PLAT_ASR) +extern const struct _mp_obj_module_t module_slip; +#define MICROPY_PORT_BUILTIN_MODULES_SLIP { MP_OBJ_NEW_QSTR(MP_QSTR_slip), (mp_obj_t)&module_slip}, +#else +#define MICROPY_PORT_BUILTIN_MODULES_SLIP +#endif + +#if CONFIG_POC +extern const struct _mp_obj_module_t mp_module_poc; +#define MICROPY_PORT_BUILTIN_MODULES_POC { MP_OBJ_NEW_QSTR(MP_QSTR_poc), (mp_obj_t)&mp_module_poc}, +#else +#define MICROPY_PORT_BUILTIN_MODULES_POC +#endif + +#if CONFIG_QRCODE +extern const struct _mp_obj_module_t mp_module_qrcode; +#define MICROPY_PORT_BUILTIN_MODULES_QRCODE { MP_OBJ_NEW_QSTR(MP_QSTR_qrcode), (mp_obj_t)&mp_module_qrcode}, +#else +#define MICROPY_PORT_BUILTIN_MODULES_QRCODE +#endif + + + + #if defined(PLAT_RDA) #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_modem), (mp_obj_t)&mp_module_modem}, \ @@ -341,8 +394,11 @@ extern const struct _mp_obj_module_t module_SecureData; { MP_OBJ_NEW_QSTR(MP_QSTR_net), (mp_obj_t)&mp_module_net}, \ { MP_OBJ_NEW_QSTR(MP_QSTR_misc), (mp_obj_t)&mp_module_misc}, \ { MP_OBJ_NEW_QSTR(MP_QSTR_sim), (mp_obj_t)&mp_module_sim}, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_dial), (mp_obj_t)&mp_module_dial}, -#else + { MP_OBJ_NEW_QSTR(MP_QSTR_pm), (mp_obj_t)&mp_module_pm}, \ + MICROPY_PORT_BUILTIN_MODULES_FOTA \ + { MP_OBJ_NEW_QSTR(MP_QSTR_dial), (mp_obj_t)&mp_module_dial}, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_nb), (mp_obj_t)&mp_module_nb}, +#elif !defined(PLAT_Qualcomm) #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ @@ -364,14 +420,33 @@ extern const struct _mp_obj_module_t module_SecureData; { MP_OBJ_NEW_QSTR(MP_QSTR_cellLocator), (mp_obj_t)&mp_module_celllocator}, \ { 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_FOTA \ MICROPY_PORT_BUILTIN_MODULES_LVGL \ + MICROPY_PORT_BUILTIN_MODULES_QRCODE \ MICROPY_PORT_BUILTIN_MODULES_CAMERA \ MICROPY_PORT_BUILTIN_MODULES_BLE \ MICROPY_PORT_BUILTIN_MODULES_QUECTHING \ MICROPY_PORT_BUILTIN_MODULES_SENSOR \ MICROPY_PORT_BUILTIN_MODULES_GNSS \ - MICROPY_PORT_BUILTIN_MODULES_RTMP + MICROPY_PORT_BUILTIN_MODULES_RTMP \ + MICROPY_PORT_BUILTIN_MODULES_SLIP \ + MICROPY_PORT_BUILTIN_MODULES_POC +#else +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_example), (mp_obj_t)&example_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_dial), (mp_obj_t)&mp_module_dial },\ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_misc), (mp_obj_t)&mp_module_misc}, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_osTimer), (mp_obj_t)&mp_ostimer_type}, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_sim), (mp_obj_t)&mp_module_sim}, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_net), (mp_obj_t)&mp_module_net}, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_pm), (mp_obj_t)&mp_module_pm}, \ + MICROPY_PORT_BUILTIN_MODULES_FOTA \ + { MP_OBJ_NEW_QSTR(MP_QSTR_modem), (mp_obj_t)&mp_module_modem}, #endif // use vfs's functions for import stat and builtin open @@ -430,16 +505,23 @@ extern const struct _mp_obj_module_t module_SecureData; const char *readline_hist[8]; \ struct _machine_timer_obj_t *machine_timer_obj_head; +#define STRINGIFY_VALUE(s) STRINGIFY(s) +#define STRINGIFY(s) #s -#define MICROPY_HW_BOARD_NAME "EC100Y" +#define MICROPY_HW_BOARD_NAME STRINGIFY_VALUE(BOARD) #define MICROPY_HW_MCU_NAME "QUECTEL" // board specifics -#define MICROPY_PY_SYS_PLATFORM "EC100Y" +#define MICROPY_PY_SYS_PLATFORM STRINGIFY_VALUE(BOARD) +#if !defined(PLAT_Qualcomm) #ifndef SSIZE_MAX #define SSIZE_MAX 0xFFFFFFFF #endif +#else +typedef int intptr_t; +typedef unsigned int uintptr_t; +#endif // We need to provide a declaration/definition of alloca() #include "stdlib.h" diff --git a/ports/quectel/core/source/mphalport.c b/ports/quectel/core/source/mphalport.c index de27b66..538e97e 100644 --- a/ports/quectel/core/source/mphalport.c +++ b/ports/quectel/core/source/mphalport.c @@ -37,28 +37,88 @@ #include "helios_os.h" #include "helios_rtc.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; #if !defined(PLAT_RDA) -#define QUECPYTHON_CALLBACK_MSG_MAX_NUM 50 +#define QUECPYTHON_CALLBACK_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) static Helios_MsgQ_t quecpython_callback_deal_queue = 0; #endif //forrest.liu@20210809 add for quecpython task repl using waiting msg -#define MP_HAL_STDIN_MSG_MAX_NUM 50 +#define MP_HAL_STDIN_MSG_MAX_NUM (2 * MICROPY_SCHEDULER_DEPTH) static Helios_MsgQ_t mp_hal_stdin_msg = 0; void mp_hal_stdin_send_msg_to_rx_chr(void); +static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size); + + + +static uint8_t mp_hal_cdcPort_State = 1; +void mp_hal_port_open(uint8_t state) +{ + mp_hal_cdcPort_State = state; + Helios_UARTConfig UARTConfig = { + HELIOS_UART_BAUD, + HELIOS_UART_DATABIT_8, + HELIOS_UART_STOP_1, + HELIOS_UART_PARITY_NONE, + HELIOS_UART_FC_NONE + }; + Helios_UARTInitStruct UARTInitStruct = {&UARTConfig, mp_hal_stdin_cb}; + + if(state == 1) { + Helios_UART_Deinit(QPY_REPL_UART); + if (Helios_UART_Init(QPY_REPL_UART, &UARTInitStruct)) { + mp_hal_cdcPort_State = 0; + } + } +} + +#define MP_HAL_PORT_CHECK_OPEN (mp_hal_cdcPort_State == 1) +void mp_keyboard_interrupt(void); static void mp_hal_stdin_cb(uint64_t ind_type, Helios_UARTNum port, uint64_t size) { UNUSED(ind_type); - UNUSED(size); UNUSED(port); - - //Helios_Semaphore_Release(mp_hal_stdin_sem); - mp_hal_stdin_send_msg_to_rx_chr();//forrest.liu@20210809 add for quecpython task repl using waiting msg + if(MP_HAL_PORT_CHECK_OPEN) { +#if MICROPY_KBD_EXCEPTION + if(IS_MAINPY_RUNNING_FLAG_TRUE()) + { + uint64_t i = 0; + volatile unsigned char c = 0; + for(i= 0; i < size; i++) + { + if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + if (!IS_REPL_REFUSED() && (c == mp_interrupt_char)) { + // Signal keyboard interrupt to be raised as soon as the VM resumes + mp_keyboard_interrupt(); + break; + } + continue; + } + break; + } + if(i < size) + { + for(; i < size; i++) + { + if(Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + continue; + } + break; + } + } + } + else +#endif + { + //Helios_Semaphore_Release(mp_hal_stdin_sem); + mp_hal_stdin_send_msg_to_rx_chr();//forrest.liu@20210809 add for quecpython task repl using waiting msg + } + } } int mp_hal_stdio_init(void) @@ -95,12 +155,13 @@ int mp_hal_stdin_rx_chr(void) { while(1) { - unsigned char c = 0; + volatile unsigned char c = 0; mp_uint_t msg; - - int ret = (int)Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)); - if(ret > 0) return c; + if(MP_HAL_PORT_CHECK_OPEN && Helios_UART_Read(QPY_REPL_UART, (void *)&c, sizeof(unsigned char)) >0 ) { + return c; + } + //Helios_Semaphore_Acquire(mp_hal_stdin_sem, 10); //forrest.liu@20210809 add for quecpython task repl using waiting msg MP_THREAD_GIL_EXIT(); @@ -113,20 +174,22 @@ int mp_hal_stdin_rx_chr(void) void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (!str|| !len) return; - - Helios_UART_Write(QPY_REPL_UART, (void *)str, len); + if(MP_HAL_PORT_CHECK_OPEN) { + Helios_UART_Write(QPY_REPL_UART, (void *)str, len); + } } -uint32_t mp_hal_ticks_ms(void) { - return (uint32_t)(Helios_RTC_GetTicks()/HAL_TICK1S); +uint32_t mp_hal_ticks_ms(void) +{ + return (uint32_t)Helios_RTC_TicksToMs(); } uint32_t mp_hal_ticks_us(void) { - return (uint32_t)(Helios_RTC_GetTicks()*1000/HAL_TICK1S); + return (uint32_t)Helios_RTC_TicksToUs(); } void mp_hal_delay_ms(uint32_t ms) { -#if !defined(PLAT_RDA) +#if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) mp_uint_t dt = 0; mp_uint_t t0 = 0,t1 = 0; Helios_Thread_t taskid = 0; @@ -187,7 +250,7 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { return ret; } -#if !defined(PLAT_RDA) +#if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) void quecpython_callback_deal_queue_create(void) { quecpython_callback_deal_queue = Helios_MsgQ_Create(QUECPYTHON_CALLBACK_MSG_MAX_NUM, sizeof(mp_uint_t)); diff --git a/ports/quectel/core/source/mphalport.h b/ports/quectel/core/source/mphalport.h index 366c079..cf04aaa 100644 --- a/ports/quectel/core/source/mphalport.h +++ b/ports/quectel/core/source/mphalport.h @@ -29,6 +29,10 @@ #define HAL_TICK1S 16.384 /*Due to low power consumption of BC25 series, the baud rate needs to be set to 57600, please do not modify.*/ #define HELIOS_UART_BAUD HELIOS_UART_BAUD_57600 +#elif defined(PLAT_Qualcomm) +#define HAL_TICK1S 32.768 +#define QPY_REPL_UART HELIOS_UART0 +#define HELIOS_UART_BAUD HELIOS_UART_BAUD_115200 #else #define HAL_TICK1S 32.768 #define QPY_REPL_UART HELIOS_UART3 @@ -39,8 +43,10 @@ extern ringbuf_t stdin_ringbuf; int mp_hal_stdio_init(void); uint32_t mp_hal_ticks_ms(void); -#if !defined(PLAT_RDA) +#if !defined(PLAT_RDA) && !defined(PLAT_Qualcomm) void quecpython_send_msg_to_sleep_func(void); mp_uint_t quecpython_sleep_deal_fun(mp_uint_t ms); #endif +void mp_hal_port_open(uint8_t state); + #endif //__MP_HAL_PORT_H__ diff --git a/ports/quectel/core/source/mpthreadport.c b/ports/quectel/core/source/mpthreadport.c index b552d6e..8a184e1 100644 --- a/ports/quectel/core/source/mpthreadport.c +++ b/ports/quectel/core/source/mpthreadport.c @@ -21,7 +21,9 @@ #include "mpthread.h" #include "mphal.h" #include "mpthreadport.h" +#if !defined(PLAT_Qualcomm) #include "arch.h" +#endif #include "helios_os.h" #if MICROPY_PY_THREAD @@ -228,6 +230,11 @@ void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { Helios_Mutex_Unlock(*mutex); } +//Added by Freddy @20210818 delete a lock +void mp_thread_mutex_del(mp_thread_mutex_t *mutex) { + Helios_Mutex_Delete(*mutex); +} + void mp_thread_deinit(void) { for (;;) { // Find a task to delete diff --git a/ports/quectel/core/source/mpthreadport.h b/ports/quectel/core/source/mpthreadport.h index 6236e58..18c7dba 100644 --- a/ports/quectel/core/source/mpthreadport.h +++ b/ports/quectel/core/source/mpthreadport.h @@ -35,5 +35,10 @@ void mp_thread_deinit(void); unsigned int mp_get_available_memory_size(void); bool mp_is_python_thread(void); +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); + #endif // MICROPY_INCLUDED_MPTHREADPORT_H diff --git a/ports/quectel/core/source/nb_aep.c b/ports/quectel/core/source/nb_aep.c new file mode 100644 index 0000000..d3df42f --- /dev/null +++ b/ports/quectel/core/source/nb_aep.c @@ -0,0 +1,171 @@ +/* + * 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 "stream.h" +#include "mperrno.h" +#include "modnb.h" +#include "helios_ril_aep.h" + +#if MICROPY_PY_NB_AEP + +typedef struct _nb_aep_obj_t { + mp_obj_base_t base; + Helios_NB_AEP_Info nb_aep_info; +} nb_aep_obj_t; + +STATIC mp_obj_t nb_aep_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); + + +STATIC void nb_aep_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + // nb_aep_obj_t *self = MP_OBJ_TO_PTR(self_in); +} + +STATIC mp_obj_t nb_aep_connect(mp_obj_t self_in){ + nb_aep_obj_t * self = MP_OBJ_TO_PTR(self_in); + int ret = Helios_AEP_Connect(self->nb_aep_info.ip,self->nb_aep_info.port); + if ( ret != -1 ){ + return mp_obj_new_int(ret); + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nb_aep_connect_obj, nb_aep_connect); + +STATIC mp_obj_t nb_aep_close(mp_obj_t self_in){ + mp_uint_t ret = 0; + ret = Helios_AEP_DisConnect(); + if ( !ret ){ + return mp_const_true; + }else{ + return mp_const_false; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nb_aep_close_obj, nb_aep_close); + +STATIC mp_obj_t nb_aep_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + mp_uint_t ret = 0; + + enum { ARG_data_len,ARG_data_buf, ARG_type}; + + + const mp_arg_t allowed_args[] = { + { MP_QSTR_data_len , MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_data_buf , MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, + { MP_QSTR_type , MP_ARG_REQUIRED | 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); + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t data_len = args[ARG_data_len].u_int; + mp_int_t type = args[ARG_type].u_int; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data_buf].u_obj, &bufinfo, MP_BUFFER_READ); + data_len = (data_len < (mp_int_t)bufinfo.len ? data_len : (mp_int_t)bufinfo.len ); + ret = Helios_AEP_SendData(( uint32_t )data_len,(uint8_t *)bufinfo.buf,type); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nb_aep_send_obj, 2, nb_aep_send); + +STATIC mp_obj_t nb_aep_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + + enum { ARG_data_len,ARG_data_buf }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_data_len , MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_data_buf , MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } } + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data_buf].u_obj, &bufinfo, MP_BUFFER_READ); + mp_int_t data_len = args[ARG_data_len].u_int; + data_len = (int32_t)(data_len) > (int32_t)bufinfo.len ? (int32_t)bufinfo.len : (int32_t)(data_len); + if ( data_len < 0 ){ + mp_raise_OSError(MP_EINVAL); + }else if ( data_len == 0 ){ + data_len = (int32_t)bufinfo.len; + } + + Helios_NB_AEP_databuffer data_buffer; + data_buffer.buffer = (uint8_t *)malloc(data_len+1); + if ( data_buffer.buffer == NULL ) + { + mp_raise_OSError(MP_ENOMEM); + } + data_buffer.capacity = data_len; + memset(data_buffer.buffer,0x00,data_len+1); + mp_uint_t ret = Helios_AEP_RecvData(&data_buffer); + + if ( ret != 0 ) + { + free(data_buffer.buffer); + return mp_obj_new_int(ret); + } + strncpy((char *)bufinfo.buf, (char *)data_buffer.buffer,data_len); + + free(data_buffer.buffer); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nb_aep_recv_obj, 1, nb_aep_recv); + +STATIC const mp_rom_map_elem_t nb_aep_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&nb_aep_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&nb_aep_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&nb_aep_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&nb_aep_send_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nb_aep_locals_dict, nb_aep_locals_dict_table); + +const mp_obj_type_t nb_aep_type = { + { &mp_type_type }, + .name = MP_QSTR_AEP, + .print = nb_aep_print, + .make_new = nb_aep_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .locals_dict = (mp_obj_dict_t *)&nb_aep_locals_dict, +}; + +STATIC mp_obj_t nb_aep_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, 2, MP_OBJ_FUN_ARGS_MAX, true); + // create instance + nb_aep_obj_t *self = m_new_obj(nb_aep_obj_t); + if ( self == NULL ){ + mp_raise_OSError(MP_ENOMEM); + } + + memset((void *)&self->nb_aep_info,0x00,sizeof(self->nb_aep_info)); + self->base.type = &nb_aep_type; + const char * ip = mp_obj_str_get_str(args[0]); + const char * port = mp_obj_str_get_str(args[1]); + memcpy(self->nb_aep_info.ip ,ip ,strlen(ip )); + memcpy(self->nb_aep_info.port ,port ,strlen(port )); + return MP_OBJ_FROM_PTR(self); +} +#endif /*end MICROPY_PY_NB_AEP*/ \ No newline at end of file diff --git a/ports/quectel/core/source/nb_oc.c b/ports/quectel/core/source/nb_oc.c new file mode 100644 index 0000000..0e5a1e1 --- /dev/null +++ b/ports/quectel/core/source/nb_oc.c @@ -0,0 +1,186 @@ +/* + * 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 "helios_debug.h" +#include "runtime.h" +#include "stream.h" +#include "mperrno.h" +#include "modnb.h" +#include "helios_ril_lot.h" + +#if MICROPY_PY_NB_OC + +typedef struct _nb_oc_obj_t { + mp_obj_base_t base; + Helios_NB_OC_Info nb_oc_info; +} nb_oc_obj_t; + +STATIC mp_obj_t nb_oc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); + + +STATIC void nb_oc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + // nb_oc_obj_t *self = MP_OBJ_TO_PTR(self_in); +} + +STATIC mp_obj_t nb_oc_connect(mp_obj_t self_in){ + int ret = 0; + nb_oc_obj_t * self = MP_OBJ_TO_PTR(self_in); + if ( strlen((const char*)self->nb_oc_info.psk) != 0 ) + { + ret = Helios_OC_Connect(self->nb_oc_info.ip,self->nb_oc_info.port,self->nb_oc_info.psk,NULL); + }else{ + ret = Helios_OC_Connect(self->nb_oc_info.ip,self->nb_oc_info.port,NULL,NULL); + } + if ( ret != -1 ){ + return mp_obj_new_int(ret); + } + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nb_oc_connect_obj, nb_oc_connect); + +STATIC mp_obj_t nb_oc_close(mp_obj_t self_in){ + nb_oc_obj_t * self = MP_OBJ_TO_PTR(self_in); + mp_uint_t ret = 0; + ret = Helios_OC_DisConnect(); + if ( !ret ){ + return mp_const_true; + }else{ + return mp_const_false; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nb_oc_close_obj, nb_oc_close); + +STATIC mp_obj_t nb_oc_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + mp_uint_t ret = 0; + + enum { ARG_data_len,ARG_data_buf, ARG_type}; + + + const mp_arg_t allowed_args[] = { + { MP_QSTR_data_len , MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_data_buf , MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, + { MP_QSTR_type , MP_ARG_REQUIRED | 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); + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t data_len = args[ARG_data_len].u_int; + mp_int_t type = args[ARG_type].u_int; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data_buf].u_obj, &bufinfo, MP_BUFFER_READ); + data_len = (data_len < (mp_int_t)bufinfo.len ? data_len : (mp_int_t)bufinfo.len ); + ret = Helios_OC_SendData( ( uint32_t )data_len,(uint8_t *)bufinfo.buf,type); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nb_oc_send_obj, 2, nb_oc_send); + +STATIC mp_obj_t nb_oc_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + + enum { ARG_data_len,ARG_data_buf }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_data_len , MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_data_buf , MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } } + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data_buf].u_obj, &bufinfo, MP_BUFFER_READ); + mp_int_t data_len = args[ARG_data_len].u_int; + data_len = (int32_t)(data_len) > (int32_t)bufinfo.len ? (int32_t)bufinfo.len : (int32_t)(data_len); + if ( data_len < 0 ){ + mp_raise_OSError(MP_EINVAL); + }else if ( data_len == 0 ){ + data_len = (int32_t)bufinfo.len; + } + + Helios_NB_OC_databuffer data_buffer; + data_buffer.buffer = (uint8_t *)malloc(data_len+1); + if ( data_buffer.buffer == NULL ) + { + mp_raise_OSError(MP_ENOMEM); + } + data_buffer.capacity = data_len; + memset(data_buffer.buffer,0x00,data_len+1); + mp_uint_t ret = Helios_OC_RecvData(&data_buffer); + + if ( ret != 0 ) + { + free(data_buffer.buffer); + return mp_obj_new_int(ret); + } + strncpy((char *)bufinfo.buf, (char *)data_buffer.buffer,data_len); + + free(data_buffer.buffer); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nb_oc_recv_obj, 1, nb_oc_recv); + +STATIC const mp_rom_map_elem_t nb_oc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&nb_oc_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&nb_oc_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&nb_oc_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&nb_oc_send_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nb_oc_locals_dict, nb_oc_locals_dict_table); + +const mp_obj_type_t nb_oc_type = { + { &mp_type_type }, + .name = MP_QSTR_OC, + .print = nb_oc_print, + .make_new = nb_oc_make_new, + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .locals_dict = (mp_obj_dict_t *)&nb_oc_locals_dict, +}; + +STATIC mp_obj_t nb_oc_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, 2, MP_OBJ_FUN_ARGS_MAX, true); + // create instance + nb_oc_obj_t *self = m_new_obj(nb_oc_obj_t); + if ( self == NULL ){ + mp_raise_OSError(MP_ENOMEM); + } + memset((void *)&self->nb_oc_info,0x00,sizeof(self->nb_oc_info)); + self->base.type = &nb_oc_type; + const char * ip = mp_obj_str_get_str(args[0]); + const char * port = mp_obj_str_get_str(args[1]); + const char * psk = NULL; + if ( n_args >= 3 ){ + psk = mp_obj_str_get_str(args[2]); + if ( strlen( psk ) > 0 ) + { + memcpy(self->nb_oc_info.psk ,psk ,strlen(psk )); + } + } + memcpy(self->nb_oc_info.ip ,ip ,strlen(ip )); + memcpy(self->nb_oc_info.port ,port ,strlen(port )); + return MP_OBJ_FROM_PTR(self); +} +#endif /*end MICROPY_PY_NB_OC*/ \ No newline at end of file diff --git a/ports/quectel/core/source/nb_onenet.c b/ports/quectel/core/source/nb_onenet.c new file mode 100644 index 0000000..b77a755 --- /dev/null +++ b/ports/quectel/core/source/nb_onenet.c @@ -0,0 +1,707 @@ + +#include +#include +#include + +#include "runtime.h" +#include "gc.h" +#include "mphal.h" +#include "mperrno.h" + +#include "mphalport.h" +#include "helios_ril_onenet.h" +#if MICROPY_PY_NB_ONENET + + +#define ONENET_ADD_OBJECT_CNT 6 +#define ONENET_OBSERVER_RESP_LIST 3 +#define ONENET_CONFIG_LIST 7 +#define ONENET_DISCOVER_RESP_LIST 6 +#define ONENET_WRITE_RESP_LIST 3 +#define ONENET_READ_RESP_LIST 11 +#define ONENET_NOTIFY_LIST 10 + +static c_callback_t *onenet_callback_cur = NULL; + +//s32 Helios_ONENET_Create(void); +STATIC mp_obj_t qpy_ONENET_Create() +{ + int ret = -1; + ret = Helios_ONENET_Create(); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(qpy_ONENET_Create_obj, qpy_ONENET_Create); + +//typedef struct{ +// u32 ref; // Instance ID of OneNET communication suite.. +// u32 obj_id; //Object identifier. If the object ID is not existed, the module will return error.. +// u32 ins_count; //Length of data sent. +// u8* insbitmap; //Instance bitmap. A string which should be marked with double quotation marks For example, +// //if =4, and the ="1101", it means the instance ID 0, 1, 3 will be registered, and the instance ID 2 will not be registered. +// u32 attrcount; //Attribute count, which indicate the count of readable and/or writeable resources. +// u32 actcount; //Action count, which indicate the count of executable resources. +//}Helios_ONENET_Obj_Param_t; +static s32 resolve_ONENET_Addobj_list(mp_obj_t mp_data, Helios_ONENET_Obj_Param_t *onenet_obj_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_ADD_OBJECT_CNT ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_obj_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_obj_param->obj_id = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_obj_param->ins_count = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_str(value) ) return -1; + mp_buffer_info_t data = {0}; + mp_get_buffer_raise(value, &data, MP_BUFFER_READ); + onenet_obj_param->insbitmap = data.buf; + break; + case 4: + if ( !mp_obj_is_int(value) ) return -1; + onenet_obj_param->attrcount = mp_obj_get_int_truncated(value); + break; + case 5: + if ( !mp_obj_is_int(value) ) return -1; + onenet_obj_param->actcount = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Addobj(Helios_ONENET_Obj_Param_t *onenet_obj_param_t); +STATIC mp_obj_t qpy_ONENET_Addobj(mp_obj_t mp_data) +{ + int ret = -1; + Helios_ONENET_Obj_Param_t onenet_obj_param; + memset(&onenet_obj_param, 0x00, sizeof(onenet_obj_param)); + ret = resolve_ONENET_Addobj_list(mp_data, &onenet_obj_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Addobj(&onenet_obj_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Addobj_obj, qpy_ONENET_Addobj); + + +//s32 Helios_ONENET_Delobj(u32 ref,u32 obj_id); +STATIC mp_obj_t qpy_ONENET_Delobj(mp_obj_t mp_ref, mp_obj_t mp_obj_id) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_ref) || !mp_obj_is_int(mp_obj_id) ) return mp_obj_new_int(ret); + + u32 ref = mp_obj_get_int_truncated(mp_ref); + u32 obj_id = mp_obj_get_int_truncated(mp_obj_id); + + ret = Helios_ONENET_Delobj(ref, obj_id); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_ONENET_Delobj_obj, qpy_ONENET_Delobj); + +static void qpy_callback_onenet_req(u8* buffer,u32 length) +{ + if(onenet_callback_cur == NULL) { + return; + } + + mp_sched_schedule_ex(onenet_callback_cur, MP_OBJ_FROM_PTR(mp_obj_new_str((char *)buffer, length))); +} +//s32 Helios_ONENET_Open(u32 ref, u32 lifetime, void (*callback_onenet_req)(u8* buffer,u32 length) ); +STATIC mp_obj_t qpy_ONENET_Open(mp_obj_t mp_ref, mp_obj_t mp_lifetime, mp_obj_t mp_callback) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_ref) || !mp_obj_is_int(mp_lifetime) ) return mp_obj_new_int(ret); + u32 ref = mp_obj_get_int_truncated(mp_ref); + u32 lifetime = mp_obj_get_int_truncated(mp_lifetime); + + static c_callback_t cb = {0}; + memset(&cb, 0, sizeof(c_callback_t)); + onenet_callback_cur = &cb; + mp_sched_schedule_callback_register(onenet_callback_cur, mp_callback); + + ret = Helios_ONENET_Open(ref, lifetime, qpy_callback_onenet_req); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(qpy_ONENET_Open_obj, qpy_ONENET_Open); + +//typedef struct{ +//u32 ref; //Instance ID of OneNET communication suite. +//u32 msgid; //The message identifier, which comes from the URC "+ MIPLOBSERVE:". +//Helios_Enum_ONENET_Observe_Result obderve_result;// The result of observe. +//u8 raimode; +//}Helios_ONENET_Observe_Param_t; +static s32 resolve_ONENET_Observer_Rsp_list(mp_obj_t mp_data, Helios_ONENET_Observe_Param_t *onenet_observe_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_OBSERVER_RESP_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_observe_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_observe_param->msgid = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_observe_param->obderve_result = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_observe_param->raimode = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Observer_Rsp(Helios_ONENET_Observe_Param_t* onenet_observe_param_t); +STATIC mp_obj_t qpy_ONENET_Observer_Rsp(mp_obj_t mp_data) +{ + int ret = -1; + Helios_ONENET_Observe_Param_t onenet_observe_param; + memset(&onenet_observe_param, 0x00, sizeof(onenet_observe_param)); + ret = resolve_ONENET_Observer_Rsp_list(mp_data, &onenet_observe_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Observer_Rsp(&onenet_observe_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Observer_Rsp_obj, qpy_ONENET_Observer_Rsp); + +//typedef struct{ +// Helios_Enum_ONENET_Bs_Mode onenet_bs_mode; +// u8* ip; +// u32 port; +// u8 ack_timeout; +// bool obs_autoack; +// bool auto_update; +// bool save_state; +//}Helios_ONENET_Config_Param_t; +static s32 resolve_ONENET_Config_list(mp_obj_t mp_data, Helios_ONENET_Config_Param_t* onenet_config_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_CONFIG_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->onenet_bs_mode = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_str(value) ) return -1; + mp_buffer_info_t data = {0}; + mp_get_buffer_raise(value, &data, MP_BUFFER_READ); + onenet_config_param->ip = data.buf; + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->port = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->ack_timeout = mp_obj_get_int_truncated(value); + break; + case 4: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->obs_autoack = mp_obj_get_int_truncated(value); + break; + case 5: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->auto_update = mp_obj_get_int_truncated(value); + break; + case 6: + if ( !mp_obj_is_int(value) ) return -1; + onenet_config_param->save_state = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Config(Helios_ONENET_Config_Param_t* onenet_config_param_t,Helios_Enum_ONENET_Conf_Flag config_flag); +STATIC mp_obj_t qpy_ONENET_Config(mp_obj_t mp_data, mp_obj_t mp_config_flag) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_config_flag) ) return mp_obj_new_int(ret); + s32 config_flag = mp_obj_get_int(mp_config_flag); + + Helios_ONENET_Config_Param_t onenet_config_param; + memset(&onenet_config_param, 0x00, sizeof(onenet_config_param)); + ret = resolve_ONENET_Config_list(mp_data, &onenet_config_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Config(&onenet_config_param, config_flag); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_ONENET_Config_obj, qpy_ONENET_Config); + +//typedef struct{ +// u32 ref; // Instance ID of OneNET communication suite.. +// u32 msgid; //The message identifier, which comes from the URC "+ MIPLDISCOVER:" +// u32 result; //The result of discover operate, +// u32 length; //The length of . +// u8* value_string; //A string which includes the attributes of the object and should be marked with double quotation marks. +// Helios_Enum_ONENET_Rai_Mode raimode; +//}Helios_ONENET_Discover_Rsp_Param_t; +static s32 resolve_ONENET_Discover_Rsp_list(mp_obj_t mp_data, Helios_ONENET_Discover_Rsp_Param_t* onenet_discover_rsp_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_DISCOVER_RESP_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_discover_rsp_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_discover_rsp_param->msgid = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_discover_rsp_param->result = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_discover_rsp_param->length = mp_obj_get_int_truncated(value); + break; + case 4: + if ( !mp_obj_is_str(value) ) return -1; + mp_buffer_info_t data = {0}; + mp_get_buffer_raise(value, &data, MP_BUFFER_READ); + onenet_discover_rsp_param->value_string = data.buf; + break; + case 5: + if ( !mp_obj_is_int(value) ) return -1; + onenet_discover_rsp_param->raimode = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Discover_Rsp(Helios_ONENET_Discover_Rsp_Param_t *onenet_discover_rsp_param_t); +STATIC mp_obj_t qpy_ONENET_Discover_Rsp(mp_obj_t mp_data) +{ + int ret = -1; + + Helios_ONENET_Discover_Rsp_Param_t onenet_discover_rsp_param; + memset(&onenet_discover_rsp_param, 0x00, sizeof(onenet_discover_rsp_param)); + ret = resolve_ONENET_Discover_Rsp_list(mp_data, &onenet_discover_rsp_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Discover_Rsp(&onenet_discover_rsp_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Discover_Rsp_obj, qpy_ONENET_Discover_Rsp); + +//typedef struct{ +//u32 ref; //Instance ID of OneNET communication suite. +//u32 msgid; //The message identifier, which comes from the URC "+MIPLWRITE:". +//Helios_Enum_ONENET_Observe_Result result;// The result of response. +//Helios_Enum_ONENET_Rai_Mode raimode; +//}Helios_ONENET_Write_Rsp_Param_t; +static s32 resolve_ONENET_Write_Rsp_list(mp_obj_t mp_data, Helios_ONENET_Write_Rsp_Param_t *onenet_write_rsp_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_WRITE_RESP_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_write_rsp_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_write_rsp_param->msgid = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_write_rsp_param->result = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_write_rsp_param->raimode = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Write_Rsp(Helios_ONENET_Write_Rsp_Param_t* onenet_write_rsp_param_t); +STATIC mp_obj_t qpy_ONENET_Write_Rsp(mp_obj_t mp_data) +{ + int ret = -1; + + Helios_ONENET_Write_Rsp_Param_t onenet_write_rsp_param; + memset(&onenet_write_rsp_param, 0x00, sizeof(onenet_write_rsp_param)); + ret = resolve_ONENET_Write_Rsp_list(mp_data, &onenet_write_rsp_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Write_Rsp(&onenet_write_rsp_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Write_Rsp_obj, qpy_ONENET_Write_Rsp); + +//typedef struct{ +// u32 ref; // Instance ID of OneNET communication suite.. +// u32 msgid; //The message identifier, which comes from the URC "+MIPLREAD:" +// Helios_Enum_ONENET_Observe_Result result;// The result of response. +// u32 objid; //Object identifier. +// u32 insid; //The instance identifier, which comes from the URC "+MIPLOBSERVE :" +// u32 resid; //The resource identifier, which comes from the URC "+MIPLOBSERVE :". +// Helios_Enum_ONENET_Value_Type value_type; //The value type. +// u32 len; //The value length. +// u8* value; +// u32 index; //The index number of the data. +// u32 flag; //The message indication. The range is 0-2. +// Helios_Enum_ONENET_Rai_Mode raimode; //Integer type. Just for raimode +//}Helios_ONENET_Read_Rsp_Param_t; +static s32 resolve_ONENET_Read_Rsp_list(mp_obj_t mp_data, Helios_ONENET_Read_Rsp_Param_t* onenet_read_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_READ_RESP_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->msgid = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->result = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->objid = mp_obj_get_int_truncated(value); + break; + case 4: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->insid = mp_obj_get_int_truncated(value); + break; + case 5: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->resid = mp_obj_get_int_truncated(value); + break; + case 6: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->value_type = mp_obj_get_int_truncated(value); + break; + case 7: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->len = mp_obj_get_int_truncated(value); + break; + case 8: + if ( !mp_obj_is_str(value) ) return -1; + mp_buffer_info_t data = {0}; + mp_get_buffer_raise(value, &data, MP_BUFFER_READ); + onenet_read_param->value = data.buf; + break; + case 9: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->index = mp_obj_get_int_truncated(value); + break; + case 10: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->flag = mp_obj_get_int_truncated(value); + break; + case 11: + if ( !mp_obj_is_int(value) ) return -1; + onenet_read_param->raimode = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Read_Rsp(Helios_ONENET_Read_Rsp_Param_t* onenet_read_param_t); +STATIC mp_obj_t qpy_ONENET_Read_Rsp(mp_obj_t mp_data) +{ + int ret = -1; + + Helios_ONENET_Read_Rsp_Param_t onenet_read_param; + memset(&onenet_read_param, 0x00, sizeof(onenet_read_param)); + ret = resolve_ONENET_Read_Rsp_list(mp_data, &onenet_read_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Read_Rsp(&onenet_read_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Read_Rsp_obj, qpy_ONENET_Read_Rsp); + + +//s32 Helios_ONENET_Execute_Rsp(Helios_ONENET_Write_Rsp_Param_t* onenet_write_rsp_param_t); +STATIC mp_obj_t qpy_ONENET_Execute_Rsp(mp_obj_t mp_data) +{ + int ret = -1; + + Helios_ONENET_Write_Rsp_Param_t onenet_write_rsp_param; + memset(&onenet_write_rsp_param, 0x00, sizeof(onenet_write_rsp_param)); + ret = resolve_ONENET_Write_Rsp_list(mp_data, &onenet_write_rsp_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Execute_Rsp(&onenet_write_rsp_param); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_Execute_Rsp_obj, qpy_ONENET_Execute_Rsp); + +//typedef struct{ +// u32 ref; // Instance ID of OneNET communication suite.. +// u32 msgid; //The message identifier, which comes from the URC "+MIPLDISCOVER:" +// u32 objid; //Object identifier. +// u32 insid; //The instance identifier, which comes from the URC "+MIPLOBSERVE :" +// u32 resid; //The resource identifier, which comes from the URC "+MIPLOBSERVE :". +// Helios_Enum_ONENET_Value_Type value_type; //The value type. +// u32 len; //The value length. +// u8* value; +// u32 index; //The index number of the data. +// u32 flag; //The message indication. The range is 0-2. +// u32 ackid; //Integer type, range: 0-65535 +// u32 result; //Integer type. Just for Read Response +// Helios_Enum_ONENET_Rai_Mode raimode; //Integer type. Just for raimode +//}Helios_ONENET_Notify_Param_t; +static s32 resolve_ONENET_Notify_list(mp_obj_t mp_data, Helios_ONENET_Notify_Param_t* onenet_notify_param) +{ + size_t len = 0; + mp_obj_t *items = NULL; + mp_obj_list_get(mp_data, &len, &items); + if (len < ONENET_CONFIG_LIST ) + { + return -1; + } + for (u32 i = 0; i < len; i++) + { + mp_obj_t value = items[i]; + switch ( i ) { + case 0: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->ref = mp_obj_get_int_truncated(value); + break; + case 1: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->msgid = mp_obj_get_int_truncated(value); + break; + case 2: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->objid = mp_obj_get_int_truncated(value); + break; + case 3: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->insid = mp_obj_get_int_truncated(value); + break; + case 4: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->resid = mp_obj_get_int_truncated(value); + break; + case 5: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->value_type = mp_obj_get_int_truncated(value); + break; + case 6: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->len = mp_obj_get_int_truncated(value); + break; + case 7: + if ( !mp_obj_is_str(value) ) return -1; + mp_buffer_info_t data = {0}; + mp_get_buffer_raise(value, &data, MP_BUFFER_READ); + onenet_notify_param->value = data.buf; + break; + case 8: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->index = mp_obj_get_int_truncated(value); + break; + case 9: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->flag = mp_obj_get_int_truncated(value); + break; + case 10: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->ackid = mp_obj_get_int_truncated(value); + break; + case 11: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->result = mp_obj_get_int_truncated(value); + break; + case 12: + if ( !mp_obj_is_int(value) ) return -1; + onenet_notify_param->raimode = mp_obj_get_int_truncated(value); + break; + default: + return -1; + } + } + return 0; +} +//s32 Helios_ONENET_Notify(Helios_ONENET_Notify_Param_t* onenet_notify_param_t,bool ack_flag); +STATIC mp_obj_t qpy_ONENET_Notify(mp_obj_t mp_data, mp_obj_t mp_ack_flag) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_ack_flag) ) return mp_obj_new_int(ret); + s32 ack_flag = mp_obj_get_int(mp_ack_flag); + + Helios_ONENET_Notify_Param_t onenet_notify_param; + memset(&onenet_notify_param, 0x00, sizeof(onenet_notify_param)); + ret = resolve_ONENET_Notify_list(mp_data, &onenet_notify_param); + if( ret != 0 ) { + return mp_obj_new_int(ret); + } + + ret = Helios_ONENET_Notify(&onenet_notify_param, ack_flag); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(qpy_ONENET_Notify_obj, qpy_ONENET_Notify); + + +//s32 Helios_ONENET_Update(u32 ref,u32 lifetime,Helios_Enum_ONENET_Obj_Flag obj_flag,Helios_Enum_ONENET_Rai_Mode raimode); +STATIC mp_obj_t qpy_ONENET_Update(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + int ret = 0; + static const mp_arg_t allowed_args[] = + { + { MP_QSTR_ref, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_lifetime, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_obj_flag, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_raimode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + + u32 ref = vals[0].u_int; + u32 lifetime = vals[1].u_int; + u32 obj_flag = vals[2].u_int; + u32 raimode = vals[3].u_int; + + ret = Helios_ONENET_Update(ref, lifetime, obj_flag, raimode); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(qpy_ONENET_Update_obj, 2, qpy_ONENET_Update); + + +//s32 Helios_ONENET_CLOSE(u32 ref); +STATIC mp_obj_t qpy_ONENET_CLOSE(mp_obj_t mp_data) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_data) ) return mp_obj_new_int(ret); + + s32 ref = mp_obj_get_int(mp_data); + ret = Helios_ONENET_CLOSE(ref); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_CLOSE_obj, qpy_ONENET_CLOSE); + + +//s32 Helios_ONENET_DELETE(u32 ref); +STATIC mp_obj_t qpy_ONENET_DELETE(mp_obj_t mp_data) +{ + int ret = -1; + if ( !mp_obj_is_int(mp_data) ) return mp_obj_new_int(ret); + + s32 ref = mp_obj_get_int(mp_data); + ret = Helios_ONENET_DELETE(ref); + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(qpy_ONENET_DELETE_obj, qpy_ONENET_DELETE); + +STATIC const mp_rom_map_elem_t onenet_module_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_create), MP_ROM_PTR(&qpy_ONENET_Create_obj) }, + { MP_ROM_QSTR(MP_QSTR_add_object), MP_ROM_PTR(&qpy_ONENET_Addobj_obj) }, + { MP_ROM_QSTR(MP_QSTR_delete_object), MP_ROM_PTR(&qpy_ONENET_Delobj_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&qpy_ONENET_Open_obj) }, + { MP_ROM_QSTR(MP_QSTR_observer_resp), MP_ROM_PTR(&qpy_ONENET_Observer_Rsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&qpy_ONENET_Config_obj) }, + { MP_ROM_QSTR(MP_QSTR_discover_resp), MP_ROM_PTR(&qpy_ONENET_Discover_Rsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_resp), MP_ROM_PTR(&qpy_ONENET_Write_Rsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_resp), MP_ROM_PTR(&qpy_ONENET_Read_Rsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_execute_resp), MP_ROM_PTR(&qpy_ONENET_Execute_Rsp_obj) }, + { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&qpy_ONENET_Notify_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&qpy_ONENET_Update_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&qpy_ONENET_CLOSE_obj) }, + { MP_ROM_QSTR(MP_QSTR_destroy), MP_ROM_PTR(&qpy_ONENET_DELETE_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(onenet_module_dict, onenet_module_dict_table); + +const mp_obj_module_t module_onenet = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&onenet_module_dict, +}; + +#endif /*MICROPY_PY_NB_ONENET*/ \ No newline at end of file diff --git a/ports/quectel/core/source/quecpython.c b/ports/quectel/core/source/quecpython.c index 74d2369..9c63bde 100644 --- a/ports/quectel/core/source/quecpython.c +++ b/ports/quectel/core/source/quecpython.c @@ -33,6 +33,7 @@ #include "mphal.h" #include "readline.h" #include "mpprint.h" +#include "objmodule.h" #if !defined(PLAT_RDA) #if CONFIG_MBEDTLS @@ -105,17 +106,26 @@ void _start(void) {main(0, NULL);} */ static char *stack_top; #if MICROPY_ENABLE_GC +#if defined(PLAT_Qualcomm) +static char heap[650 * 1024]; +#else static char heap[1024 * 512]; #endif +#endif extern pyexec_mode_kind_t pyexec_mode_kind; +extern void machine_timer_deinit_all(void); + +MAINPY_RUNNING_FLAG_DEF +MAINPY_INTERRUPT_BY_KBD_FLAG_DEF + void quecpython_task(void *arg) { Helios_Thread_t id = 0; void *stack_ptr = NULL; int stack_dummy; -#if !defined(PLAT_RDA) - //Added by Freddy @20210520 在线程sleep时,通过wait queue的方式超时代替实际的sleep, +#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(); @@ -134,9 +144,9 @@ void quecpython_task(void *arg) mp_thread_init(stack_ptr, MP_TASK_STACK_LEN); //uart_printf("===========id: 0x%4X, stack_ptr: 0x%08X==========\r\n", id, stack_ptr); #endif - + if(mp_hal_stdio_init()) return; - + /* ** Jayceon-2020/09/23: ** Resolve all sorts of weird bugs that occur using the quecpython.py tool. @@ -159,32 +169,53 @@ 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(); - + // run boot-up scripts #if defined(PLAT_RDA) pyexec_frozen_module("_boot_RDA.py"); +#elif defined(PLAT_Qualcomm) + pyexec_frozen_module("_boot_Qualcomm.py"); #else pyexec_frozen_module("_boot.py"); #endif - if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { - pyexec_file_if_exists("/usr/main.py"); + if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE()) { + 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(); + } } - for (;;) { - if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { - if (pyexec_raw_repl() != 0) { - break; - } - } else { - if (pyexec_friendly_repl() != 0) { - break; + else + { + MAINPY_INTERRUPT_BY_KBD_FLAG_CLEAR(); + } + + if(MAINPY_INTERRUPT_BY_KBD_FLAG_FALSE()) + { + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } } } } - //machine_timer_deinit_all(); + + machine_timer_deinit_all(); + #if MICROPY_PY_THREAD //uart_printf("mp_thread_deinit in quecpython task.\r\n"); mp_thread_deinit(); #endif + + mp_module_deinit_all(); + gc_sweep_all(); mp_hal_stdout_tx_str("MPY: soft reboot\r\n"); diff --git a/ports/quectel/core/source/sensor_sn95500.c b/ports/quectel/core/source/sensor_sn95500.c index 8d65fed..9b094b2 100644 --- a/ports/quectel/core/source/sensor_sn95500.c +++ b/ports/quectel/core/source/sensor_sn95500.c @@ -561,25 +561,7 @@ STATIC const mp_rom_map_elem_t sensor_sn95500_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_exitSuspendMode), MP_ROM_PTR(&qpy_exit_suspend_mode_obj) }, //{ MP_ROM_QSTR(MP_QSTR_readSdioPin), MP_ROM_PTR(&qpy_read_sdio_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_INT(HELIOS_GPIO1) }, - { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_INT(HELIOS_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_INT(HELIOS_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_INT(HELIOS_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_INT(HELIOS_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_INT(HELIOS_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_INT(HELIOS_GPIO7) }, - { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_INT(HELIOS_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_INT(HELIOS_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_INT(HELIOS_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_INT(HELIOS_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_GPIO12), MP_ROM_INT(HELIOS_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_GPIO13), MP_ROM_INT(HELIOS_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_GPIO14), MP_ROM_INT(HELIOS_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_GPIO15), MP_ROM_INT(HELIOS_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_GPIO16), MP_ROM_INT(HELIOS_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_GPIO17), MP_ROM_INT(HELIOS_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_GPIO18), MP_ROM_INT(HELIOS_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_GPIO19), MP_ROM_INT(HELIOS_GPIO19) }, + PLAT_GPIO_DEF(PLAT_GPIO_NUM), }; STATIC MP_DEFINE_CONST_DICT(sensor_sn95500_locals_dict, sensor_sn95500_locals_dict_table); diff --git a/ports/quectel/core/source/utf8togbk.c b/ports/quectel/core/source/utf8togbk.c deleted file mode 100644 index 4fab16b..0000000 --- a/ports/quectel/core/source/utf8togbk.c +++ /dev/null @@ -1,1375 +0,0 @@ -/* - * 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 "utf8togbk.h" -#include -extern const unsigned short mb_uni2gb_table[]; - -const unsigned short mb_uni2gb_table[20902] = -{ -0xd2bb,0xb6a1,0x8140,0xc6df,0x8141,0x8142,0x8143,0xcdf2,0xd5c9,0xc8fd,0xc9cf,0xcfc2,0xd8a2,0xb2bb,0xd3eb,0x8144, -0xd8a4,0xb3f3,0x8145,0xd7a8,0xc7d2,0xd8a7,0xcac0,0x8146,0xc7f0,0xb1fb,0xd2b5,0xb4d4,0xb6ab,0xcbbf,0xd8a9,0x8147, -0x8148,0x8149,0xb6aa,0x814a,0xc1bd,0xd1cf,0x814b,0xc9a5,0xd8ad,0x814c,0xb8f6,0xd1be,0xe3dc,0xd6d0,0x814d,0x814e, -0xb7e1,0x814f,0xb4ae,0x8150,0xc1d9,0x8151,0xd8bc,0x8152,0xcde8,0xb5a4,0xceaa,0xd6f7,0x8153,0xc0f6,0xbed9,0xd8af, -0x8154,0x8155,0x8156,0xc4cb,0x8157,0xbec3,0x8158,0xd8b1,0xc3b4,0xd2e5,0x8159,0xd6ae,0xceda,0xd5a7,0xbaf5,0xb7a6, -0xc0d6,0x815a,0xc6b9,0xc5d2,0xc7c7,0x815b,0xb9d4,0x815c,0xb3cb,0xd2d2,0x815d,0x815e,0xd8bf,0xbec5,0xc6f2,0xd2b2, -0xcfb0,0xcfe7,0x815f,0x8160,0x8161,0x8162,0xcae9,0x8163,0x8164,0xd8c0,0x8165,0x8166,0x8167,0x8168,0x8169,0x816a, -0xc2f2,0xc2d2,0x816b,0xc8e9,0x816c,0x816d,0x816e,0x816f,0x8170,0x8171,0x8172,0x8173,0x8174,0x8175,0xc7ac,0x8176, -0x8177,0x8178,0x8179,0x817a,0x817b,0x817c,0xc1cb,0x817d,0xd3e8,0xd5f9,0x817e,0xcac2,0xb6fe,0xd8a1,0xd3da,0xbff7, -0x8180,0xd4c6,0xbba5,0xd8c1,0xcee5,0xbeae,0x8181,0x8182,0xd8a8,0x8183,0xd1c7,0xd0a9,0x8184,0x8185,0x8186,0xd8bd, -0xd9ef,0xcdf6,0xbfba,0x8187,0xbdbb,0xbaa5,0xd2e0,0xb2fa,0xbae0,0xc4b6,0x8188,0xcfed,0xbea9,0xcda4,0xc1c1,0x8189, -0x818a,0x818b,0xc7d7,0xd9f1,0x818c,0xd9f4,0x818d,0x818e,0x818f,0x8190,0xc8cb,0xd8e9,0x8191,0x8192,0x8193,0xd2da, -0xcab2,0xc8ca,0xd8ec,0xd8ea,0xd8c6,0xbdf6,0xc6cd,0xb3f0,0x8194,0xd8eb,0xbdf1,0xbde9,0x8195,0xc8d4,0xb4d3,0x8196, -0x8197,0xc2d8,0x8198,0xb2d6,0xd7d0,0xcacb,0xcbfb,0xd5cc,0xb8b6,0xcfc9,0x8199,0x819a,0x819b,0xd9da,0xd8f0,0xc7aa, -0x819c,0xd8ee,0x819d,0xb4fa,0xc1ee,0xd2d4,0x819e,0x819f,0xd8ed,0x81a0,0xd2c7,0xd8ef,0xc3c7,0x81a1,0x81a2,0x81a3, -0xd1f6,0x81a4,0xd6d9,0xd8f2,0x81a5,0xd8f5,0xbcfe,0xbcdb,0x81a6,0x81a7,0x81a8,0xc8ce,0x81a9,0xb7dd,0x81aa,0xb7c2, -0x81ab,0xc6f3,0x81ac,0x81ad,0x81ae,0x81af,0x81b0,0x81b1,0x81b2,0xd8f8,0xd2c1,0x81b3,0x81b4,0xcee9,0xbcbf,0xb7fc, -0xb7a5,0xd0dd,0x81b5,0x81b6,0x81b7,0x81b8,0x81b9,0xd6da,0xd3c5,0xbbef,0xbbe1,0xd8f1,0x81ba,0x81bb,0xc9a1,0xceb0, -0xb4ab,0x81bc,0xd8f3,0x81bd,0xc9cb,0xd8f6,0xc2d7,0xd8f7,0x81be,0x81bf,0xceb1,0xd8f9,0x81c0,0x81c1,0x81c2,0xb2ae, -0xb9c0,0x81c3,0xd9a3,0x81c4,0xb0e9,0x81c5,0xc1e6,0x81c6,0xc9ec,0x81c7,0xcbc5,0x81c8,0xcbc6,0xd9a4,0x81c9,0x81ca, -0x81cb,0x81cc,0x81cd,0xb5e8,0x81ce,0x81cf,0xb5ab,0x81d0,0x81d1,0x81d2,0x81d3,0x81d4,0x81d5,0xcebb,0xb5cd,0xd7a1, -0xd7f4,0xd3d3,0x81d6,0xcce5,0x81d7,0xbace,0x81d8,0xd9a2,0xd9dc,0xd3e0,0xd8fd,0xb7f0,0xd7f7,0xd8fe,0xd8fa,0xd9a1, -0xc4e3,0x81d9,0x81da,0xd3b6,0xd8f4,0xd9dd,0x81db,0xd8fb,0x81dc,0xc5e5,0x81dd,0x81de,0xc0d0,0x81df,0x81e0,0xd1f0, -0xb0db,0x81e1,0x81e2,0xbcd1,0xd9a6,0x81e3,0xd9a5,0x81e4,0x81e5,0x81e6,0x81e7,0xd9ac,0xd9ae,0x81e8,0xd9ab,0xcab9, -0x81e9,0x81ea,0x81eb,0xd9a9,0xd6b6,0x81ec,0x81ed,0x81ee,0xb3de,0xd9a8,0x81ef,0xc0fd,0x81f0,0xcacc,0x81f1,0xd9aa, -0x81f2,0xd9a7,0x81f3,0x81f4,0xd9b0,0x81f5,0x81f6,0xb6b1,0x81f7,0x81f8,0x81f9,0xb9a9,0x81fa,0xd2c0,0x81fb,0x81fc, -0xcfc0,0x81fd,0x81fe,0xc2c2,0x8240,0xbdc4,0xd5ec,0xb2e0,0xc7c8,0xbfeb,0xd9ad,0x8241,0xd9af,0x8242,0xceea,0xbaee, -0x8243,0x8244,0x8245,0x8246,0x8247,0xc7d6,0x8248,0x8249,0x824a,0x824b,0x824c,0x824d,0x824e,0x824f,0x8250,0xb1e3, -0x8251,0x8252,0x8253,0xb4d9,0xb6ed,0xd9b4,0x8254,0x8255,0x8256,0x8257,0xbfa1,0x8258,0x8259,0x825a,0xd9de,0xc7ce, -0xc0fe,0xd9b8,0x825b,0x825c,0x825d,0x825e,0x825f,0xcbd7,0xb7fd,0x8260,0xd9b5,0x8261,0xd9b7,0xb1a3,0xd3e1,0xd9b9, -0x8262,0xd0c5,0x8263,0xd9b6,0x8264,0x8265,0xd9b1,0x8266,0xd9b2,0xc1a9,0xd9b3,0x8267,0x8268,0xbcf3,0xd0de,0xb8a9, -0x8269,0xbee3,0x826a,0xd9bd,0x826b,0x826c,0x826d,0x826e,0xd9ba,0x826f,0xb0b3,0x8270,0x8271,0x8272,0xd9c2,0x8273, -0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x827a,0x827b,0x827c,0x827d,0x827e,0x8280,0xd9c4,0xb1b6,0x8281,0xd9bf, -0x8282,0x8283,0xb5b9,0x8284,0xbef3,0x8285,0x8286,0x8287,0xccc8,0xbaf2,0xd2d0,0x8288,0xd9c3,0x8289,0x828a,0xbde8, -0x828b,0xb3ab,0x828c,0x828d,0x828e,0xd9c5,0xbeeb,0x828f,0xd9c6,0xd9bb,0xc4df,0x8290,0xd9be,0xd9c1,0xd9c0,0x8291, -0x8292,0x8293,0x8294,0x8295,0x8296,0x8297,0x8298,0x8299,0x829a,0x829b,0xd5ae,0x829c,0xd6b5,0x829d,0xc7e3,0x829e, -0x829f,0x82a0,0x82a1,0xd9c8,0x82a2,0x82a3,0x82a4,0xbcd9,0xd9ca,0x82a5,0x82a6,0x82a7,0xd9bc,0x82a8,0xd9cb,0xc6ab, -0x82a9,0x82aa,0x82ab,0x82ac,0x82ad,0xd9c9,0x82ae,0x82af,0x82b0,0x82b1,0xd7f6,0x82b2,0xcda3,0x82b3,0x82b4,0x82b5, -0x82b6,0x82b7,0x82b8,0x82b9,0x82ba,0xbda1,0x82bb,0x82bc,0x82bd,0x82be,0x82bf,0x82c0,0xd9cc,0x82c1,0x82c2,0x82c3, -0x82c4,0x82c5,0x82c6,0x82c7,0x82c8,0x82c9,0xc5bc,0xcdb5,0x82ca,0x82cb,0x82cc,0xd9cd,0x82cd,0x82ce,0xd9c7,0xb3a5, -0xbffe,0x82cf,0x82d0,0x82d1,0x82d2,0xb8b5,0x82d3,0x82d4,0xc0fc,0x82d5,0x82d6,0x82d7,0x82d8,0xb0f8,0x82d9,0x82da, -0x82db,0x82dc,0x82dd,0x82de,0x82df,0x82e0,0x82e1,0x82e2,0x82e3,0x82e4,0x82e5,0x82e6,0x82e7,0x82e8,0x82e9,0x82ea, -0x82eb,0x82ec,0x82ed,0xb4f6,0x82ee,0xd9ce,0x82ef,0xd9cf,0xb4a2,0xd9d0,0x82f0,0x82f1,0xb4df,0x82f2,0x82f3,0x82f4, -0x82f5,0x82f6,0xb0c1,0x82f7,0x82f8,0x82f9,0x82fa,0x82fb,0x82fc,0x82fd,0xd9d1,0xc9b5,0x82fe,0x8340,0x8341,0x8342, -0x8343,0x8344,0x8345,0x8346,0x8347,0x8348,0x8349,0x834a,0x834b,0x834c,0x834d,0x834e,0x834f,0x8350,0x8351,0xcff1, -0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0xd9d2,0x8358,0x8359,0x835a,0xc1c5,0x835b,0x835c,0x835d,0x835e,0x835f, -0x8360,0x8361,0x8362,0x8363,0x8364,0x8365,0xd9d6,0xc9ae,0x8366,0x8367,0x8368,0x8369,0xd9d5,0xd9d4,0xd9d7,0x836a, -0x836b,0x836c,0x836d,0xcbdb,0x836e,0xbda9,0x836f,0x8370,0x8371,0x8372,0x8373,0xc6a7,0x8374,0x8375,0x8376,0x8377, -0x8378,0x8379,0x837a,0x837b,0x837c,0x837d,0xd9d3,0xd9d8,0x837e,0x8380,0x8381,0xd9d9,0x8382,0x8383,0x8384,0x8385, -0x8386,0x8387,0xc8e5,0x8388,0x8389,0x838a,0x838b,0x838c,0x838d,0x838e,0x838f,0x8390,0x8391,0x8392,0x8393,0x8394, -0x8395,0xc0dc,0x8396,0x8397,0x8398,0x8399,0x839a,0x839b,0x839c,0x839d,0x839e,0x839f,0x83a0,0x83a1,0x83a2,0x83a3, -0x83a4,0x83a5,0x83a6,0x83a7,0x83a8,0x83a9,0x83aa,0x83ab,0x83ac,0x83ad,0x83ae,0x83af,0x83b0,0x83b1,0x83b2,0xb6f9, -0xd8a3,0xd4ca,0x83b3,0xd4aa,0xd0d6,0xb3e4,0xd5d7,0x83b4,0xcfc8,0xb9e2,0x83b5,0xbfcb,0x83b6,0xc3e2,0x83b7,0x83b8, -0x83b9,0xb6d2,0x83ba,0x83bb,0xcdc3,0xd9ee,0xd9f0,0x83bc,0x83bd,0x83be,0xb5b3,0x83bf,0xb6b5,0x83c0,0x83c1,0x83c2, -0x83c3,0x83c4,0xbea4,0x83c5,0x83c6,0xc8eb,0x83c7,0x83c8,0xc8ab,0x83c9,0x83ca,0xb0cb,0xb9ab,0xc1f9,0xd9e2,0x83cb, -0xc0bc,0xb9b2,0x83cc,0xb9d8,0xd0cb,0xb1f8,0xc6e4,0xbedf,0xb5e4,0xd7c8,0x83cd,0xd1f8,0xbce6,0xcade,0x83ce,0x83cf, -0xbcbd,0xd9e6,0xd8e7,0x83d0,0x83d1,0xc4da,0x83d2,0x83d3,0xb8d4,0xc8bd,0x83d4,0x83d5,0xb2e1,0xd4d9,0x83d6,0x83d7, -0x83d8,0x83d9,0xc3b0,0x83da,0x83db,0xc3e1,0xdaa2,0xc8df,0x83dc,0xd0b4,0x83dd,0xbefc,0xc5a9,0x83de,0x83df,0x83e0, -0xb9da,0x83e1,0xdaa3,0x83e2,0xd4a9,0xdaa4,0x83e3,0x83e4,0x83e5,0x83e6,0x83e7,0xd9fb,0xb6ac,0x83e8,0x83e9,0xb7eb, -0xb1f9,0xd9fc,0xb3e5,0xbef6,0x83ea,0xbff6,0xd2b1,0xc0e4,0x83eb,0x83ec,0x83ed,0xb6b3,0xd9fe,0xd9fd,0x83ee,0x83ef, -0xbebb,0x83f0,0x83f1,0x83f2,0xc6e0,0x83f3,0xd7bc,0xdaa1,0x83f4,0xc1b9,0x83f5,0xb5f2,0xc1e8,0x83f6,0x83f7,0xbcf5, -0x83f8,0xb4d5,0x83f9,0x83fa,0x83fb,0x83fc,0x83fd,0x83fe,0x8440,0x8441,0x8442,0xc1dd,0x8443,0xc4fd,0x8444,0x8445, -0xbcb8,0xb7b2,0x8446,0x8447,0xb7ef,0x8448,0x8449,0x844a,0x844b,0x844c,0x844d,0xd9ec,0x844e,0xc6be,0x844f,0xbfad, -0xbbcb,0x8450,0x8451,0xb5ca,0x8452,0xdbc9,0xd0d7,0x8453,0xcdb9,0xb0bc,0xb3f6,0xbbf7,0xdbca,0xbaaf,0x8454,0xd4e4, -0xb5b6,0xb5f3,0xd8d6,0xc8d0,0x8455,0x8456,0xb7d6,0xc7d0,0xd8d7,0x8457,0xbfaf,0x8458,0x8459,0xdbbb,0xd8d8,0x845a, -0x845b,0xd0cc,0xbbae,0x845c,0x845d,0x845e,0xebbe,0xc1d0,0xc1f5,0xd4f2,0xb8d5,0xb4b4,0x845f,0xb3f5,0x8460,0x8461, -0xc9be,0x8462,0x8463,0x8464,0xc5d0,0x8465,0x8466,0x8467,0xc5d9,0xc0fb,0x8468,0xb1f0,0x8469,0xd8d9,0xb9ce,0x846a, -0xb5bd,0x846b,0x846c,0xd8da,0x846d,0x846e,0xd6c6,0xcba2,0xc8af,0xc9b2,0xb4cc,0xbfcc,0x846f,0xb9f4,0x8470,0xd8db, -0xd8dc,0xb6e7,0xbcc1,0xccea,0x8471,0x8472,0x8473,0x8474,0x8475,0x8476,0xcff7,0x8477,0xd8dd,0xc7b0,0x8478,0x8479, -0xb9d0,0xbda3,0x847a,0x847b,0xccde,0x847c,0xc6ca,0x847d,0x847e,0x8480,0x8481,0x8482,0xd8e0,0x8483,0xd8de,0x8484, -0x8485,0xd8df,0x8486,0x8487,0x8488,0xb0fe,0x8489,0xbee7,0x848a,0xcaa3,0xbcf4,0x848b,0x848c,0x848d,0x848e,0xb8b1, -0x848f,0x8490,0xb8ee,0x8491,0x8492,0x8493,0x8494,0x8495,0x8496,0x8497,0x8498,0x8499,0x849a,0xd8e2,0x849b,0xbdcb, -0x849c,0xd8e4,0xd8e3,0x849d,0x849e,0x849f,0x84a0,0x84a1,0xc5fc,0x84a2,0x84a3,0x84a4,0x84a5,0x84a6,0x84a7,0x84a8, -0xd8e5,0x84a9,0x84aa,0xd8e6,0x84ab,0x84ac,0x84ad,0x84ae,0x84af,0x84b0,0x84b1,0xc1a6,0x84b2,0xc8b0,0xb0ec,0xb9a6, -0xbcd3,0xcef1,0xdbbd,0xc1d3,0x84b3,0x84b4,0x84b5,0x84b6,0xb6af,0xd6fa,0xc5ac,0xbdd9,0xdbbe,0xdbbf,0x84b7,0x84b8, -0x84b9,0xc0f8,0xbea2,0xc0cd,0x84ba,0x84bb,0x84bc,0x84bd,0x84be,0x84bf,0x84c0,0x84c1,0x84c2,0x84c3,0xdbc0,0xcac6, -0x84c4,0x84c5,0x84c6,0xb2aa,0x84c7,0x84c8,0x84c9,0xd3c2,0x84ca,0xc3e3,0x84cb,0xd1ab,0x84cc,0x84cd,0x84ce,0x84cf, -0xdbc2,0x84d0,0xc0d5,0x84d1,0x84d2,0x84d3,0xdbc3,0x84d4,0xbfb1,0x84d5,0x84d6,0x84d7,0x84d8,0x84d9,0x84da,0xc4bc, -0x84db,0x84dc,0x84dd,0x84de,0xc7da,0x84df,0x84e0,0x84e1,0x84e2,0x84e3,0x84e4,0x84e5,0x84e6,0x84e7,0x84e8,0x84e9, -0xdbc4,0x84ea,0x84eb,0x84ec,0x84ed,0x84ee,0x84ef,0x84f0,0x84f1,0xd9e8,0xc9d7,0x84f2,0x84f3,0x84f4,0xb9b4,0xcef0, -0xd4c8,0x84f5,0x84f6,0x84f7,0x84f8,0xb0fc,0xb4d2,0x84f9,0xd0d9,0x84fa,0x84fb,0x84fc,0x84fd,0xd9e9,0x84fe,0xdecb, -0xd9eb,0x8540,0x8541,0x8542,0x8543,0xd8b0,0xbbaf,0xb1b1,0x8544,0xb3d7,0xd8ce,0x8545,0x8546,0xd4d1,0x8547,0x8548, -0xbdb3,0xbfef,0x8549,0xcfbb,0x854a,0x854b,0xd8d0,0x854c,0x854d,0x854e,0xb7cb,0x854f,0x8550,0x8551,0xd8d1,0x8552, -0x8553,0x8554,0x8555,0x8556,0x8557,0x8558,0x8559,0x855a,0x855b,0xc6a5,0xc7f8,0xd2bd,0x855c,0x855d,0xd8d2,0xc4e4, -0x855e,0xcaae,0x855f,0xc7a7,0x8560,0xd8a6,0x8561,0xc9fd,0xcee7,0xbbdc,0xb0eb,0x8562,0x8563,0x8564,0xbbaa,0xd0ad, -0x8565,0xb1b0,0xd7e4,0xd7bf,0x8566,0xb5a5,0xc2f4,0xc4cf,0x8567,0x8568,0xb2a9,0x8569,0xb2b7,0x856a,0xb1e5,0xdfb2, -0xd5bc,0xbfa8,0xc2ac,0xd8d5,0xc2b1,0x856b,0xd8d4,0xced4,0x856c,0xdae0,0x856d,0xcec0,0x856e,0x856f,0xd8b4,0xc3ae, -0xd3a1,0xcea3,0x8570,0xbcb4,0xc8b4,0xc2d1,0x8571,0xbeed,0xd0b6,0x8572,0xdae1,0x8573,0x8574,0x8575,0x8576,0xc7e4, -0x8577,0x8578,0xb3a7,0x8579,0xb6f2,0xccfc,0xc0fa,0x857a,0x857b,0xc0f7,0x857c,0xd1b9,0xd1e1,0xd8c7,0x857d,0x857e, -0x8580,0x8581,0x8582,0x8583,0x8584,0xb2de,0x8585,0x8586,0xc0e5,0x8587,0xbaf1,0x8588,0x8589,0xd8c8,0x858a,0xd4ad, -0x858b,0x858c,0xcfe1,0xd8c9,0x858d,0xd8ca,0xcfc3,0x858e,0xb3f8,0xbec7,0x858f,0x8590,0x8591,0x8592,0xd8cb,0x8593, -0x8594,0x8595,0x8596,0x8597,0x8598,0x8599,0xdbcc,0x859a,0x859b,0x859c,0x859d,0xc8a5,0x859e,0x859f,0x85a0,0xcfd8, -0x85a1,0xc8fe,0xb2ce,0x85a2,0x85a3,0x85a4,0x85a5,0x85a6,0xd3d6,0xb2e6,0xbcb0,0xd3d1,0xcbab,0xb7b4,0x85a7,0x85a8, -0x85a9,0xb7a2,0x85aa,0x85ab,0xcae5,0x85ac,0xc8a1,0xcadc,0xb1e4,0xd0f0,0x85ad,0xc5d1,0x85ae,0x85af,0x85b0,0xdbc5, -0xb5fe,0x85b1,0x85b2,0xbfda,0xb9c5,0xbee4,0xc1ed,0x85b3,0xdfb6,0xdfb5,0xd6bb,0xbdd0,0xd5d9,0xb0c8,0xb6a3,0xbfc9, -0xcca8,0xdfb3,0xcab7,0xd3d2,0x85b4,0xd8cf,0xd2b6,0xbac5,0xcbbe,0xccbe,0x85b5,0xdfb7,0xb5f0,0xdfb4,0x85b6,0x85b7, -0x85b8,0xd3f5,0x85b9,0xb3d4,0xb8f7,0x85ba,0xdfba,0x85bb,0xbacf,0xbcaa,0xb5f5,0x85bc,0xcdac,0xc3fb,0xbaf3,0xc0f4, -0xcdc2,0xcff2,0xdfb8,0xcfc5,0x85bd,0xc2c0,0xdfb9,0xc2f0,0x85be,0x85bf,0x85c0,0xbefd,0x85c1,0xc1df,0xcdcc,0xd2f7, -0xb7cd,0xdfc1,0x85c2,0xdfc4,0x85c3,0x85c4,0xb7f1,0xb0c9,0xb6d6,0xb7d4,0x85c5,0xbaac,0xccfd,0xbfd4,0xcbb1,0xc6f4, -0x85c6,0xd6a8,0xdfc5,0x85c7,0xcee2,0xb3b3,0x85c8,0x85c9,0xcefc,0xb4b5,0x85ca,0xcec7,0xbaf0,0x85cb,0xcee1,0x85cc, -0xd1bd,0x85cd,0x85ce,0xdfc0,0x85cf,0x85d0,0xb4f4,0x85d1,0xb3ca,0x85d2,0xb8e6,0xdfbb,0x85d3,0x85d4,0x85d5,0x85d6, -0xc4c5,0x85d7,0xdfbc,0xdfbd,0xdfbe,0xc5bb,0xdfbf,0xdfc2,0xd4b1,0xdfc3,0x85d8,0xc7ba,0xced8,0x85d9,0x85da,0x85db, -0x85dc,0x85dd,0xc4d8,0x85de,0xdfca,0x85df,0xdfcf,0x85e0,0xd6dc,0x85e1,0x85e2,0x85e3,0x85e4,0x85e5,0x85e6,0x85e7, -0x85e8,0xdfc9,0xdfda,0xceb6,0x85e9,0xbac7,0xdfce,0xdfc8,0xc5de,0x85ea,0x85eb,0xc9eb,0xbaf4,0xc3fc,0x85ec,0x85ed, -0xbed7,0x85ee,0xdfc6,0x85ef,0xdfcd,0x85f0,0xc5d8,0x85f1,0x85f2,0x85f3,0x85f4,0xd5a6,0xbacd,0x85f5,0xbecc,0xd3bd, -0xb8c0,0x85f6,0xd6e4,0x85f7,0xdfc7,0xb9be,0xbfa7,0x85f8,0x85f9,0xc1fc,0xdfcb,0xdfcc,0x85fa,0xdfd0,0x85fb,0x85fc, -0x85fd,0x85fe,0x8640,0xdfdb,0xdfe5,0x8641,0xdfd7,0xdfd6,0xd7c9,0xdfe3,0xdfe4,0xe5eb,0xd2a7,0xdfd2,0x8642,0xbfa9, -0x8643,0xd4db,0x8644,0xbfc8,0xdfd4,0x8645,0x8646,0x8647,0xcfcc,0x8648,0x8649,0xdfdd,0x864a,0xd1ca,0x864b,0xdfde, -0xb0a7,0xc6b7,0xdfd3,0x864c,0xbae5,0x864d,0xb6df,0xcddb,0xb9fe,0xd4d5,0x864e,0x864f,0xdfdf,0xcfec,0xb0a5,0xdfe7, -0xdfd1,0xd1c6,0xdfd5,0xdfd8,0xdfd9,0xdfdc,0x8650,0xbba9,0x8651,0xdfe0,0xdfe1,0x8652,0xdfe2,0xdfe6,0xdfe8,0xd3b4, -0x8653,0x8654,0x8655,0x8656,0x8657,0xb8e7,0xc5b6,0xdfea,0xc9da,0xc1a8,0xc4c4,0x8658,0x8659,0xbfde,0xcff8,0x865a, -0x865b,0x865c,0xd5dc,0xdfee,0x865d,0x865e,0x865f,0x8660,0x8661,0x8662,0xb2b8,0x8663,0xbadf,0xdfec,0x8664,0xdbc1, -0x8665,0xd1e4,0x8666,0x8667,0x8668,0x8669,0xcbf4,0xb4bd,0x866a,0xb0a6,0x866b,0x866c,0x866d,0x866e,0x866f,0xdff1, -0xccc6,0xdff2,0x8670,0x8671,0xdfed,0x8672,0x8673,0x8674,0x8675,0x8676,0x8677,0xdfe9,0x8678,0x8679,0x867a,0x867b, -0xdfeb,0x867c,0xdfef,0xdff0,0xbbbd,0x867d,0x867e,0xdff3,0x8680,0x8681,0xdff4,0x8682,0xbba3,0x8683,0xcadb,0xcea8, -0xe0a7,0xb3aa,0x8684,0xe0a6,0x8685,0x8686,0x8687,0xe0a1,0x8688,0x8689,0x868a,0x868b,0xdffe,0x868c,0xcdd9,0xdffc, -0x868d,0xdffa,0x868e,0xbfd0,0xd7c4,0x868f,0xc9cc,0x8690,0x8691,0xdff8,0xb0a1,0x8692,0x8693,0x8694,0x8695,0x8696, -0xdffd,0x8697,0x8698,0x8699,0x869a,0xdffb,0xe0a2,0x869b,0x869c,0x869d,0x869e,0x869f,0xe0a8,0x86a0,0x86a1,0x86a2, -0x86a3,0xb7c8,0x86a4,0x86a5,0xc6a1,0xc9b6,0xc0b2,0xdff5,0x86a6,0x86a7,0xc5be,0x86a8,0xd8c4,0xdff9,0xc4f6,0x86a9, -0x86aa,0x86ab,0x86ac,0x86ad,0x86ae,0xe0a3,0xe0a4,0xe0a5,0xd0a5,0x86af,0x86b0,0xe0b4,0xcce4,0x86b1,0xe0b1,0x86b2, -0xbfa6,0xe0af,0xceb9,0xe0ab,0xc9c6,0x86b3,0x86b4,0xc0ae,0xe0ae,0xbaed,0xbab0,0xe0a9,0x86b5,0x86b6,0x86b7,0xdff6, -0x86b8,0xe0b3,0x86b9,0x86ba,0xe0b8,0x86bb,0x86bc,0x86bd,0xb4ad,0xe0b9,0x86be,0x86bf,0xcfb2,0xbac8,0x86c0,0xe0b0, -0x86c1,0x86c2,0x86c3,0x86c4,0x86c5,0x86c6,0x86c7,0xd0fa,0x86c8,0x86c9,0x86ca,0x86cb,0x86cc,0x86cd,0x86ce,0x86cf, -0x86d0,0xe0ac,0x86d1,0xd4fb,0x86d2,0xdff7,0x86d3,0xc5e7,0x86d4,0xe0ad,0x86d5,0xd3f7,0x86d6,0xe0b6,0xe0b7,0x86d7, -0x86d8,0x86d9,0x86da,0x86db,0xe0c4,0xd0e1,0x86dc,0x86dd,0x86de,0xe0bc,0x86df,0x86e0,0xe0c9,0xe0ca,0x86e1,0x86e2, -0x86e3,0xe0be,0xe0aa,0xc9a4,0xe0c1,0x86e4,0xe0b2,0x86e5,0x86e6,0x86e7,0x86e8,0x86e9,0xcac8,0xe0c3,0x86ea,0xe0b5, -0x86eb,0xcecb,0x86ec,0xcbc3,0xe0cd,0xe0c6,0xe0c2,0x86ed,0xe0cb,0x86ee,0xe0ba,0xe0bf,0xe0c0,0x86ef,0x86f0,0xe0c5, -0x86f1,0x86f2,0xe0c7,0xe0c8,0x86f3,0xe0cc,0x86f4,0xe0bb,0x86f5,0x86f6,0x86f7,0x86f8,0x86f9,0xcbd4,0xe0d5,0x86fa, -0xe0d6,0xe0d2,0x86fb,0x86fc,0x86fd,0x86fe,0x8740,0x8741,0xe0d0,0xbcce,0x8742,0x8743,0xe0d1,0x8744,0xb8c2,0xd8c5, -0x8745,0x8746,0x8747,0x8748,0x8749,0x874a,0x874b,0x874c,0xd0ea,0x874d,0x874e,0xc2ef,0x874f,0x8750,0xe0cf,0xe0bd, -0x8751,0x8752,0x8753,0xe0d4,0xe0d3,0x8754,0x8755,0xe0d7,0x8756,0x8757,0x8758,0x8759,0xe0dc,0xe0d8,0x875a,0x875b, -0x875c,0xd6f6,0xb3b0,0x875d,0xd7ec,0x875e,0xcbbb,0x875f,0x8760,0xe0da,0x8761,0xcefb,0x8762,0x8763,0x8764,0xbad9, -0x8765,0x8766,0x8767,0x8768,0x8769,0x876a,0x876b,0x876c,0x876d,0x876e,0x876f,0x8770,0xe0e1,0xe0dd,0xd2ad,0x8771, -0x8772,0x8773,0x8774,0x8775,0xe0e2,0x8776,0x8777,0xe0db,0xe0d9,0xe0df,0x8778,0x8779,0xe0e0,0x877a,0x877b,0x877c, -0x877d,0x877e,0xe0de,0x8780,0xe0e4,0x8781,0x8782,0x8783,0xc6f7,0xd8ac,0xd4eb,0xe0e6,0xcac9,0x8784,0x8785,0x8786, -0x8787,0xe0e5,0x8788,0x8789,0x878a,0x878b,0xb8c1,0x878c,0x878d,0x878e,0x878f,0xe0e7,0xe0e8,0x8790,0x8791,0x8792, -0x8793,0x8794,0x8795,0x8796,0x8797,0xe0e9,0xe0e3,0x8798,0x8799,0x879a,0x879b,0x879c,0x879d,0x879e,0xbabf,0xcce7, -0x879f,0x87a0,0x87a1,0xe0ea,0x87a2,0x87a3,0x87a4,0x87a5,0x87a6,0x87a7,0x87a8,0x87a9,0x87aa,0x87ab,0x87ac,0x87ad, -0x87ae,0x87af,0x87b0,0xcff9,0x87b1,0x87b2,0x87b3,0x87b4,0x87b5,0x87b6,0x87b7,0x87b8,0x87b9,0x87ba,0x87bb,0xe0eb, -0x87bc,0x87bd,0x87be,0x87bf,0x87c0,0x87c1,0x87c2,0xc8c2,0x87c3,0x87c4,0x87c5,0x87c6,0xbdc0,0x87c7,0x87c8,0x87c9, -0x87ca,0x87cb,0x87cc,0x87cd,0x87ce,0x87cf,0x87d0,0x87d1,0x87d2,0x87d3,0xc4d2,0x87d4,0x87d5,0x87d6,0x87d7,0x87d8, -0x87d9,0x87da,0x87db,0x87dc,0xe0ec,0x87dd,0x87de,0xe0ed,0x87df,0x87e0,0xc7f4,0xcbc4,0x87e1,0xe0ee,0xbbd8,0xd8b6, -0xd2f2,0xe0ef,0xcdc5,0x87e2,0xb6da,0x87e3,0x87e4,0x87e5,0x87e6,0x87e7,0x87e8,0xe0f1,0x87e9,0xd4b0,0x87ea,0x87eb, -0xc0a7,0xb4d1,0x87ec,0x87ed,0xcea7,0xe0f0,0x87ee,0x87ef,0x87f0,0xe0f2,0xb9cc,0x87f1,0x87f2,0xb9fa,0xcdbc,0xe0f3, -0x87f3,0x87f4,0x87f5,0xc6d4,0xe0f4,0x87f6,0xd4b2,0x87f7,0xc8a6,0xe0f6,0xe0f5,0x87f8,0x87f9,0x87fa,0x87fb,0x87fc, -0x87fd,0x87fe,0x8840,0x8841,0x8842,0x8843,0x8844,0x8845,0x8846,0x8847,0x8848,0x8849,0xe0f7,0x884a,0x884b,0xcdc1, -0x884c,0x884d,0x884e,0xcaa5,0x884f,0x8850,0x8851,0x8852,0xd4da,0xdbd7,0xdbd9,0x8853,0xdbd8,0xb9e7,0xdbdc,0xdbdd, -0xb5d8,0x8854,0x8855,0xdbda,0x8856,0x8857,0x8858,0x8859,0x885a,0xdbdb,0xb3a1,0xdbdf,0x885b,0x885c,0xbbf8,0x885d, -0xd6b7,0x885e,0xdbe0,0x885f,0x8860,0x8861,0x8862,0xbef9,0x8863,0x8864,0xb7bb,0x8865,0xdbd0,0xccae,0xbfb2,0xbbb5, -0xd7f8,0xbfd3,0x8866,0x8867,0x8868,0x8869,0x886a,0xbfe9,0x886b,0x886c,0xbce1,0xccb3,0xdbde,0xb0d3,0xceeb,0xb7d8, -0xd7b9,0xc6c2,0x886d,0x886e,0xc0a4,0x886f,0xccb9,0x8870,0xdbe7,0xdbe1,0xc6ba,0xdbe3,0x8871,0xdbe8,0x8872,0xc5f7, -0x8873,0x8874,0x8875,0xdbea,0x8876,0x8877,0xdbe9,0xbfc0,0x8878,0x8879,0x887a,0xdbe6,0xdbe5,0x887b,0x887c,0x887d, -0x887e,0x8880,0xb4b9,0xc0ac,0xc2a2,0xdbe2,0xdbe4,0x8881,0x8882,0x8883,0x8884,0xd0cd,0xdbed,0x8885,0x8886,0x8887, -0x8888,0x8889,0xc0dd,0xdbf2,0x888a,0x888b,0x888c,0x888d,0x888e,0x888f,0x8890,0xb6e2,0x8891,0x8892,0x8893,0x8894, -0xdbf3,0xdbd2,0xb9b8,0xd4ab,0xdbec,0x8895,0xbfd1,0xdbf0,0x8896,0xdbd1,0x8897,0xb5e6,0x8898,0xdbeb,0xbfe5,0x8899, -0x889a,0x889b,0xdbee,0x889c,0xdbf1,0x889d,0x889e,0x889f,0xdbf9,0x88a0,0x88a1,0x88a2,0x88a3,0x88a4,0x88a5,0x88a6, -0x88a7,0x88a8,0xb9a1,0xb0a3,0x88a9,0x88aa,0x88ab,0x88ac,0x88ad,0x88ae,0x88af,0xc2f1,0x88b0,0x88b1,0xb3c7,0xdbef, -0x88b2,0x88b3,0xdbf8,0x88b4,0xc6d2,0xdbf4,0x88b5,0x88b6,0xdbf5,0xdbf7,0xdbf6,0x88b7,0x88b8,0xdbfe,0x88b9,0xd3f2, -0xb2ba,0x88ba,0x88bb,0x88bc,0xdbfd,0x88bd,0x88be,0x88bf,0x88c0,0x88c1,0x88c2,0x88c3,0x88c4,0xdca4,0x88c5,0xdbfb, -0x88c6,0x88c7,0x88c8,0x88c9,0xdbfa,0x88ca,0x88cb,0x88cc,0xdbfc,0xc5e0,0xbbf9,0x88cd,0x88ce,0xdca3,0x88cf,0x88d0, -0xdca5,0x88d1,0xccc3,0x88d2,0x88d3,0x88d4,0xb6d1,0xddc0,0x88d5,0x88d6,0x88d7,0xdca1,0x88d8,0xdca2,0x88d9,0x88da, -0x88db,0xc7b5,0x88dc,0x88dd,0x88de,0xb6e9,0x88df,0x88e0,0x88e1,0xdca7,0x88e2,0x88e3,0x88e4,0x88e5,0xdca6,0x88e6, -0xdca9,0xb1a4,0x88e7,0x88e8,0xb5cc,0x88e9,0x88ea,0x88eb,0x88ec,0x88ed,0xbfb0,0x88ee,0x88ef,0x88f0,0x88f1,0x88f2, -0xd1df,0x88f3,0x88f4,0x88f5,0x88f6,0xb6c2,0x88f7,0x88f8,0x88f9,0x88fa,0x88fb,0x88fc,0x88fd,0x88fe,0x8940,0x8941, -0x8942,0x8943,0x8944,0x8945,0xdca8,0x8946,0x8947,0x8948,0x8949,0x894a,0x894b,0x894c,0xcbfa,0xebf3,0x894d,0x894e, -0x894f,0xcbdc,0x8950,0x8951,0xcbfe,0x8952,0x8953,0x8954,0xccc1,0x8955,0x8956,0x8957,0x8958,0x8959,0xc8fb,0x895a, -0x895b,0x895c,0x895d,0x895e,0x895f,0xdcaa,0x8960,0x8961,0x8962,0x8963,0x8964,0xccee,0xdcab,0x8965,0x8966,0x8967, -0x8968,0x8969,0x896a,0x896b,0x896c,0x896d,0x896e,0x896f,0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0xdbd3,0x8976, -0xdcaf,0xdcac,0x8977,0xbeb3,0x8978,0xcafb,0x8979,0x897a,0x897b,0xdcad,0x897c,0x897d,0x897e,0x8980,0x8981,0x8982, -0x8983,0x8984,0xc9ca,0xc4b9,0x8985,0x8986,0x8987,0x8988,0x8989,0xc7bd,0xdcae,0x898a,0x898b,0x898c,0xd4f6,0xd0e6, -0x898d,0x898e,0x898f,0x8990,0x8991,0x8992,0x8993,0x8994,0xc4ab,0xb6d5,0x8995,0x8996,0x8997,0x8998,0x8999,0x899a, -0x899b,0x899c,0x899d,0x899e,0x899f,0x89a0,0x89a1,0x89a2,0x89a3,0x89a4,0x89a5,0x89a6,0xdbd4,0x89a7,0x89a8,0x89a9, -0x89aa,0xb1da,0x89ab,0x89ac,0x89ad,0xdbd5,0x89ae,0x89af,0x89b0,0x89b1,0x89b2,0x89b3,0x89b4,0x89b5,0x89b6,0x89b7, -0x89b8,0xdbd6,0x89b9,0x89ba,0x89bb,0xbabe,0x89bc,0x89bd,0x89be,0x89bf,0x89c0,0x89c1,0x89c2,0x89c3,0x89c4,0x89c5, -0x89c6,0x89c7,0x89c8,0x89c9,0xc8c0,0x89ca,0x89cb,0x89cc,0x89cd,0x89ce,0x89cf,0xcabf,0xc8c9,0x89d0,0xd7b3,0x89d1, -0xc9f9,0x89d2,0x89d3,0xbfc7,0x89d4,0x89d5,0xbaf8,0x89d6,0x89d7,0xd2bc,0x89d8,0x89d9,0x89da,0x89db,0x89dc,0x89dd, -0x89de,0x89df,0xe2ba,0x89e0,0xb4a6,0x89e1,0x89e2,0xb1b8,0x89e3,0x89e4,0x89e5,0x89e6,0x89e7,0xb8b4,0x89e8,0xcfc4, -0x89e9,0x89ea,0x89eb,0x89ec,0xd9e7,0xcfa6,0xcde2,0x89ed,0x89ee,0xd9ed,0xb6e0,0x89ef,0xd2b9,0x89f0,0x89f1,0xb9bb, -0x89f2,0x89f3,0x89f4,0x89f5,0xe2b9,0xe2b7,0x89f6,0xb4f3,0x89f7,0xccec,0xccab,0xb7f2,0x89f8,0xd8b2,0xd1eb,0xbabb, -0x89f9,0xcaa7,0x89fa,0x89fb,0xcdb7,0x89fc,0x89fd,0xd2c4,0xbfe4,0xbcd0,0xb6e1,0x89fe,0xdec5,0x8a40,0x8a41,0x8a42, -0x8a43,0xdec6,0xdbbc,0x8a44,0xd1d9,0x8a45,0x8a46,0xc6e6,0xc4ce,0xb7ee,0x8a47,0xb7dc,0x8a48,0x8a49,0xbffc,0xd7e0, -0x8a4a,0xc6f5,0x8a4b,0x8a4c,0xb1bc,0xdec8,0xbdb1,0xccd7,0xdeca,0x8a4d,0xdec9,0x8a4e,0x8a4f,0x8a50,0x8a51,0x8a52, -0xb5ec,0x8a53,0xc9dd,0x8a54,0x8a55,0xb0c2,0x8a56,0x8a57,0x8a58,0x8a59,0x8a5a,0x8a5b,0x8a5c,0x8a5d,0x8a5e,0x8a5f, -0x8a60,0x8a61,0x8a62,0xc5ae,0xc5ab,0x8a63,0xc4cc,0x8a64,0xbce9,0xcbfd,0x8a65,0x8a66,0x8a67,0xbac3,0x8a68,0x8a69, -0x8a6a,0xe5f9,0xc8e7,0xe5fa,0xcdfd,0x8a6b,0xd7b1,0xb8be,0xc2e8,0x8a6c,0xc8d1,0x8a6d,0x8a6e,0xe5fb,0x8a6f,0x8a70, -0x8a71,0x8a72,0xb6ca,0xbccb,0x8a73,0x8a74,0xd1fd,0xe6a1,0x8a75,0xc3ee,0x8a76,0x8a77,0x8a78,0x8a79,0xe6a4,0x8a7a, -0x8a7b,0x8a7c,0x8a7d,0xe5fe,0xe6a5,0xcdd7,0x8a7e,0x8a80,0xb7c1,0xe5fc,0xe5fd,0xe6a3,0x8a81,0x8a82,0xc4dd,0xe6a8, -0x8a83,0x8a84,0xe6a7,0x8a85,0x8a86,0x8a87,0x8a88,0x8a89,0x8a8a,0xc3c3,0x8a8b,0xc6de,0x8a8c,0x8a8d,0xe6aa,0x8a8e, -0x8a8f,0x8a90,0x8a91,0x8a92,0x8a93,0x8a94,0xc4b7,0x8a95,0x8a96,0x8a97,0xe6a2,0xcabc,0x8a98,0x8a99,0x8a9a,0x8a9b, -0xbde3,0xb9c3,0xe6a6,0xd0d5,0xceaf,0x8a9c,0x8a9d,0xe6a9,0xe6b0,0x8a9e,0xd2a6,0x8a9f,0xbdaa,0xe6ad,0x8aa0,0x8aa1, -0x8aa2,0x8aa3,0x8aa4,0xe6af,0x8aa5,0xc0d1,0x8aa6,0x8aa7,0xd2cc,0x8aa8,0x8aa9,0x8aaa,0xbca7,0x8aab,0x8aac,0x8aad, -0x8aae,0x8aaf,0x8ab0,0x8ab1,0x8ab2,0x8ab3,0x8ab4,0x8ab5,0x8ab6,0xe6b1,0x8ab7,0xd2f6,0x8ab8,0x8ab9,0x8aba,0xd7cb, -0x8abb,0xcdfe,0x8abc,0xcdde,0xc2a6,0xe6ab,0xe6ac,0xbdbf,0xe6ae,0xe6b3,0x8abd,0x8abe,0xe6b2,0x8abf,0x8ac0,0x8ac1, -0x8ac2,0xe6b6,0x8ac3,0xe6b8,0x8ac4,0x8ac5,0x8ac6,0x8ac7,0xc4ef,0x8ac8,0x8ac9,0x8aca,0xc4c8,0x8acb,0x8acc,0xbeea, -0xc9ef,0x8acd,0x8ace,0xe6b7,0x8acf,0xb6f0,0x8ad0,0x8ad1,0x8ad2,0xc3e4,0x8ad3,0x8ad4,0x8ad5,0x8ad6,0x8ad7,0x8ad8, -0x8ad9,0xd3e9,0xe6b4,0x8ada,0xe6b5,0x8adb,0xc8a2,0x8adc,0x8add,0x8ade,0x8adf,0x8ae0,0xe6bd,0x8ae1,0x8ae2,0x8ae3, -0xe6b9,0x8ae4,0x8ae5,0x8ae6,0x8ae7,0x8ae8,0xc6c5,0x8ae9,0x8aea,0xcdf1,0xe6bb,0x8aeb,0x8aec,0x8aed,0x8aee,0x8aef, -0x8af0,0x8af1,0x8af2,0x8af3,0x8af4,0xe6bc,0x8af5,0x8af6,0x8af7,0x8af8,0xbbe9,0x8af9,0x8afa,0x8afb,0x8afc,0x8afd, -0x8afe,0x8b40,0xe6be,0x8b41,0x8b42,0x8b43,0x8b44,0xe6ba,0x8b45,0x8b46,0xc0b7,0x8b47,0x8b48,0x8b49,0x8b4a,0x8b4b, -0x8b4c,0x8b4d,0x8b4e,0x8b4f,0xd3a4,0xe6bf,0xc9f4,0xe6c3,0x8b50,0x8b51,0xe6c4,0x8b52,0x8b53,0x8b54,0x8b55,0xd0f6, -0x8b56,0x8b57,0x8b58,0x8b59,0x8b5a,0x8b5b,0x8b5c,0x8b5d,0x8b5e,0x8b5f,0x8b60,0x8b61,0x8b62,0x8b63,0x8b64,0x8b65, -0x8b66,0x8b67,0xc3bd,0x8b68,0x8b69,0x8b6a,0x8b6b,0x8b6c,0x8b6d,0x8b6e,0xc3c4,0xe6c2,0x8b6f,0x8b70,0x8b71,0x8b72, -0x8b73,0x8b74,0x8b75,0x8b76,0x8b77,0x8b78,0x8b79,0x8b7a,0x8b7b,0x8b7c,0xe6c1,0x8b7d,0x8b7e,0x8b80,0x8b81,0x8b82, -0x8b83,0x8b84,0xe6c7,0xcfb1,0x8b85,0xebf4,0x8b86,0x8b87,0xe6ca,0x8b88,0x8b89,0x8b8a,0x8b8b,0x8b8c,0xe6c5,0x8b8d, -0x8b8e,0xbcde,0xc9a9,0x8b8f,0x8b90,0x8b91,0x8b92,0x8b93,0x8b94,0xbcb5,0x8b95,0x8b96,0xcfd3,0x8b97,0x8b98,0x8b99, -0x8b9a,0x8b9b,0xe6c8,0x8b9c,0xe6c9,0x8b9d,0xe6ce,0x8b9e,0xe6d0,0x8b9f,0x8ba0,0x8ba1,0xe6d1,0x8ba2,0x8ba3,0x8ba4, -0xe6cb,0xb5d5,0x8ba5,0xe6cc,0x8ba6,0x8ba7,0xe6cf,0x8ba8,0x8ba9,0xc4db,0x8baa,0xe6c6,0x8bab,0x8bac,0x8bad,0x8bae, -0x8baf,0xe6cd,0x8bb0,0x8bb1,0x8bb2,0x8bb3,0x8bb4,0x8bb5,0x8bb6,0x8bb7,0x8bb8,0x8bb9,0x8bba,0x8bbb,0x8bbc,0x8bbd, -0x8bbe,0x8bbf,0x8bc0,0x8bc1,0x8bc2,0x8bc3,0x8bc4,0x8bc5,0x8bc6,0xe6d2,0x8bc7,0x8bc8,0x8bc9,0x8bca,0x8bcb,0x8bcc, -0x8bcd,0x8bce,0x8bcf,0x8bd0,0x8bd1,0x8bd2,0xe6d4,0xe6d3,0x8bd3,0x8bd4,0x8bd5,0x8bd6,0x8bd7,0x8bd8,0x8bd9,0x8bda, -0x8bdb,0x8bdc,0x8bdd,0x8bde,0x8bdf,0x8be0,0x8be1,0x8be2,0x8be3,0x8be4,0x8be5,0x8be6,0x8be7,0x8be8,0x8be9,0x8bea, -0x8beb,0x8bec,0xe6d5,0x8bed,0xd9f8,0x8bee,0x8bef,0xe6d6,0x8bf0,0x8bf1,0x8bf2,0x8bf3,0x8bf4,0x8bf5,0x8bf6,0x8bf7, -0xe6d7,0x8bf8,0x8bf9,0x8bfa,0x8bfb,0x8bfc,0x8bfd,0x8bfe,0x8c40,0x8c41,0x8c42,0x8c43,0x8c44,0x8c45,0x8c46,0x8c47, -0xd7d3,0xe6dd,0x8c48,0xe6de,0xbfd7,0xd4d0,0x8c49,0xd7d6,0xb4e6,0xcbef,0xe6da,0xd8c3,0xd7ce,0xd0a2,0x8c4a,0xc3cf, -0x8c4b,0x8c4c,0xe6df,0xbcbe,0xb9c2,0xe6db,0xd1a7,0x8c4d,0x8c4e,0xbaa2,0xc2cf,0x8c4f,0xd8ab,0x8c50,0x8c51,0x8c52, -0xcaeb,0xe5ee,0x8c53,0xe6dc,0x8c54,0xb7f5,0x8c55,0x8c56,0x8c57,0x8c58,0xc8e6,0x8c59,0x8c5a,0xc4f5,0x8c5b,0x8c5c, -0xe5b2,0xc4fe,0x8c5d,0xcbfc,0xe5b3,0xd5ac,0x8c5e,0xd3ee,0xcad8,0xb0b2,0x8c5f,0xcbce,0xcdea,0x8c60,0x8c61,0xbaea, -0x8c62,0x8c63,0x8c64,0xe5b5,0x8c65,0xe5b4,0x8c66,0xd7da,0xb9d9,0xd6e6,0xb6a8,0xcdf0,0xd2cb,0xb1a6,0xcab5,0x8c67, -0xb3e8,0xc9f3,0xbfcd,0xd0fb,0xcad2,0xe5b6,0xbbc2,0x8c68,0x8c69,0x8c6a,0xcfdc,0xb9ac,0x8c6b,0x8c6c,0x8c6d,0x8c6e, -0xd4d7,0x8c6f,0x8c70,0xbaa6,0xd1e7,0xcffc,0xbcd2,0x8c71,0xe5b7,0xc8dd,0x8c72,0x8c73,0x8c74,0xbfed,0xb1f6,0xcbde, -0x8c75,0x8c76,0xbcc5,0x8c77,0xbcc4,0xd2fa,0xc3dc,0xbfdc,0x8c78,0x8c79,0x8c7a,0x8c7b,0xb8bb,0x8c7c,0x8c7d,0x8c7e, -0xc3c2,0x8c80,0xbaae,0xd4a2,0x8c81,0x8c82,0x8c83,0x8c84,0x8c85,0x8c86,0x8c87,0x8c88,0x8c89,0xc7de,0xc4af,0xb2ec, -0x8c8a,0xb9d1,0x8c8b,0x8c8c,0xe5bb,0xc1c8,0x8c8d,0x8c8e,0xd5af,0x8c8f,0x8c90,0x8c91,0x8c92,0x8c93,0xe5bc,0x8c94, -0xe5be,0x8c95,0x8c96,0x8c97,0x8c98,0x8c99,0x8c9a,0x8c9b,0xb4e7,0xb6d4,0xcbc2,0xd1b0,0xb5bc,0x8c9c,0x8c9d,0xcad9, -0x8c9e,0xb7e2,0x8c9f,0x8ca0,0xc9e4,0x8ca1,0xbdab,0x8ca2,0x8ca3,0xcebe,0xd7f0,0x8ca4,0x8ca5,0x8ca6,0x8ca7,0xd0a1, -0x8ca8,0xc9d9,0x8ca9,0x8caa,0xb6fb,0xe6d8,0xbce2,0x8cab,0xb3be,0x8cac,0xc9d0,0x8cad,0xe6d9,0xb3a2,0x8cae,0x8caf, -0x8cb0,0x8cb1,0xdecc,0x8cb2,0xd3c8,0xdecd,0x8cb3,0xd2a2,0x8cb4,0x8cb5,0x8cb6,0x8cb7,0xdece,0x8cb8,0x8cb9,0x8cba, -0x8cbb,0xbecd,0x8cbc,0x8cbd,0xdecf,0x8cbe,0x8cbf,0x8cc0,0xcaac,0xd2fc,0xb3df,0xe5ea,0xc4e1,0xbea1,0xceb2,0xc4f2, -0xbed6,0xc6a8,0xb2e3,0x8cc1,0x8cc2,0xbed3,0x8cc3,0x8cc4,0xc7fc,0xcceb,0xbdec,0xcedd,0x8cc5,0x8cc6,0xcaba,0xc6c1, -0xe5ec,0xd0bc,0x8cc7,0x8cc8,0x8cc9,0xd5b9,0x8cca,0x8ccb,0x8ccc,0xe5ed,0x8ccd,0x8cce,0x8ccf,0x8cd0,0xcaf4,0x8cd1, -0xcdc0,0xc2c5,0x8cd2,0xe5ef,0x8cd3,0xc2c4,0xe5f0,0x8cd4,0x8cd5,0x8cd6,0x8cd7,0x8cd8,0x8cd9,0x8cda,0xe5f8,0xcdcd, -0x8cdb,0xc9bd,0x8cdc,0x8cdd,0x8cde,0x8cdf,0x8ce0,0x8ce1,0x8ce2,0xd2d9,0xe1a8,0x8ce3,0x8ce4,0x8ce5,0x8ce6,0xd3ec, -0x8ce7,0xcbea,0xc6f1,0x8ce8,0x8ce9,0x8cea,0x8ceb,0x8cec,0xe1ac,0x8ced,0x8cee,0x8cef,0xe1a7,0xe1a9,0x8cf0,0x8cf1, -0xe1aa,0xe1af,0x8cf2,0x8cf3,0xb2ed,0x8cf4,0xe1ab,0xb8da,0xe1ad,0xe1ae,0xe1b0,0xb5ba,0xe1b1,0x8cf5,0x8cf6,0x8cf7, -0x8cf8,0x8cf9,0xe1b3,0xe1b8,0x8cfa,0x8cfb,0x8cfc,0x8cfd,0x8cfe,0xd1d2,0x8d40,0xe1b6,0xe1b5,0xc1eb,0x8d41,0x8d42, -0x8d43,0xe1b7,0x8d44,0xd4c0,0x8d45,0xe1b2,0x8d46,0xe1ba,0xb0b6,0x8d47,0x8d48,0x8d49,0x8d4a,0xe1b4,0x8d4b,0xbff9, -0x8d4c,0xe1b9,0x8d4d,0x8d4e,0xe1bb,0x8d4f,0x8d50,0x8d51,0x8d52,0x8d53,0x8d54,0xe1be,0x8d55,0x8d56,0x8d57,0x8d58, -0x8d59,0x8d5a,0xe1bc,0x8d5b,0x8d5c,0x8d5d,0x8d5e,0x8d5f,0x8d60,0xd6c5,0x8d61,0x8d62,0x8d63,0x8d64,0x8d65,0x8d66, -0x8d67,0xcfbf,0x8d68,0x8d69,0xe1bd,0xe1bf,0xc2cd,0x8d6a,0xb6eb,0x8d6b,0xd3f8,0x8d6c,0x8d6d,0xc7cd,0x8d6e,0x8d6f, -0xb7e5,0x8d70,0x8d71,0x8d72,0x8d73,0x8d74,0x8d75,0x8d76,0x8d77,0x8d78,0x8d79,0xbefe,0x8d7a,0x8d7b,0x8d7c,0x8d7d, -0x8d7e,0x8d80,0xe1c0,0xe1c1,0x8d81,0x8d82,0xe1c7,0xb3e7,0x8d83,0x8d84,0x8d85,0x8d86,0x8d87,0x8d88,0xc6e9,0x8d89, -0x8d8a,0x8d8b,0x8d8c,0x8d8d,0xb4de,0x8d8e,0xd1c2,0x8d8f,0x8d90,0x8d91,0x8d92,0xe1c8,0x8d93,0x8d94,0xe1c6,0x8d95, -0x8d96,0x8d97,0x8d98,0x8d99,0xe1c5,0x8d9a,0xe1c3,0xe1c2,0x8d9b,0xb1c0,0x8d9c,0x8d9d,0x8d9e,0xd5b8,0xe1c4,0x8d9f, -0x8da0,0x8da1,0x8da2,0x8da3,0xe1cb,0x8da4,0x8da5,0x8da6,0x8da7,0x8da8,0x8da9,0x8daa,0x8dab,0xe1cc,0xe1ca,0x8dac, -0x8dad,0x8dae,0x8daf,0x8db0,0x8db1,0x8db2,0x8db3,0xeffa,0x8db4,0x8db5,0xe1d3,0xe1d2,0xc7b6,0x8db6,0x8db7,0x8db8, -0x8db9,0x8dba,0x8dbb,0x8dbc,0x8dbd,0x8dbe,0x8dbf,0x8dc0,0xe1c9,0x8dc1,0x8dc2,0xe1ce,0x8dc3,0xe1d0,0x8dc4,0x8dc5, -0x8dc6,0x8dc7,0x8dc8,0x8dc9,0x8dca,0x8dcb,0x8dcc,0x8dcd,0x8dce,0xe1d4,0x8dcf,0xe1d1,0xe1cd,0x8dd0,0x8dd1,0xe1cf, -0x8dd2,0x8dd3,0x8dd4,0x8dd5,0xe1d5,0x8dd6,0x8dd7,0x8dd8,0x8dd9,0x8dda,0x8ddb,0x8ddc,0x8ddd,0x8dde,0x8ddf,0x8de0, -0x8de1,0x8de2,0xe1d6,0x8de3,0x8de4,0x8de5,0x8de6,0x8de7,0x8de8,0x8de9,0x8dea,0x8deb,0x8dec,0x8ded,0x8dee,0x8def, -0x8df0,0x8df1,0x8df2,0x8df3,0x8df4,0x8df5,0x8df6,0x8df7,0x8df8,0xe1d7,0x8df9,0x8dfa,0x8dfb,0xe1d8,0x8dfc,0x8dfd, -0x8dfe,0x8e40,0x8e41,0x8e42,0x8e43,0x8e44,0x8e45,0x8e46,0x8e47,0x8e48,0x8e49,0x8e4a,0x8e4b,0x8e4c,0x8e4d,0x8e4e, -0x8e4f,0x8e50,0x8e51,0x8e52,0x8e53,0x8e54,0x8e55,0xe1da,0x8e56,0x8e57,0x8e58,0x8e59,0x8e5a,0x8e5b,0x8e5c,0x8e5d, -0x8e5e,0x8e5f,0x8e60,0x8e61,0x8e62,0xe1db,0x8e63,0x8e64,0x8e65,0x8e66,0x8e67,0x8e68,0x8e69,0xcea1,0x8e6a,0x8e6b, -0x8e6c,0x8e6d,0x8e6e,0x8e6f,0x8e70,0x8e71,0x8e72,0x8e73,0x8e74,0x8e75,0x8e76,0xe7dd,0x8e77,0xb4a8,0xd6dd,0x8e78, -0x8e79,0xd1b2,0xb3b2,0x8e7a,0x8e7b,0xb9a4,0xd7f3,0xc7c9,0xbede,0xb9ae,0x8e7c,0xced7,0x8e7d,0x8e7e,0xb2ee,0xdbcf, -0x8e80,0xbcba,0xd2d1,0xcbc8,0xb0cd,0x8e81,0x8e82,0xcfef,0x8e83,0x8e84,0x8e85,0x8e86,0x8e87,0xd9e3,0xbded,0x8e88, -0x8e89,0xb1d2,0xcad0,0xb2bc,0x8e8a,0xcba7,0xb7ab,0x8e8b,0xcaa6,0x8e8c,0x8e8d,0x8e8e,0xcfa3,0x8e8f,0x8e90,0xe0f8, -0xd5ca,0xe0fb,0x8e91,0x8e92,0xe0fa,0xc5c1,0xccfb,0x8e93,0xc1b1,0xe0f9,0xd6e3,0xb2af,0xd6c4,0xb5db,0x8e94,0x8e95, -0x8e96,0x8e97,0x8e98,0x8e99,0x8e9a,0x8e9b,0xb4f8,0xd6a1,0x8e9c,0x8e9d,0x8e9e,0x8e9f,0x8ea0,0xcfaf,0xb0ef,0x8ea1, -0x8ea2,0xe0fc,0x8ea3,0x8ea4,0x8ea5,0x8ea6,0x8ea7,0xe1a1,0xb3a3,0x8ea8,0x8ea9,0xe0fd,0xe0fe,0xc3b1,0x8eaa,0x8eab, -0x8eac,0x8ead,0xc3dd,0x8eae,0xe1a2,0xb7f9,0x8eaf,0x8eb0,0x8eb1,0x8eb2,0x8eb3,0x8eb4,0xbbcf,0x8eb5,0x8eb6,0x8eb7, -0x8eb8,0x8eb9,0x8eba,0x8ebb,0xe1a3,0xc4bb,0x8ebc,0x8ebd,0x8ebe,0x8ebf,0x8ec0,0xe1a4,0x8ec1,0x8ec2,0xe1a5,0x8ec3, -0x8ec4,0xe1a6,0xb4b1,0x8ec5,0x8ec6,0x8ec7,0x8ec8,0x8ec9,0x8eca,0x8ecb,0x8ecc,0x8ecd,0x8ece,0x8ecf,0x8ed0,0x8ed1, -0x8ed2,0x8ed3,0xb8c9,0xc6bd,0xc4ea,0x8ed4,0xb2a2,0x8ed5,0xd0d2,0x8ed6,0xe7db,0xbbc3,0xd3d7,0xd3c4,0x8ed7,0xb9e3, -0xe2cf,0x8ed8,0x8ed9,0x8eda,0xd7af,0x8edb,0xc7ec,0xb1d3,0x8edc,0x8edd,0xb4b2,0xe2d1,0x8ede,0x8edf,0x8ee0,0xd0f2, -0xc2ae,0xe2d0,0x8ee1,0xbfe2,0xd3a6,0xb5d7,0xe2d2,0xb5ea,0x8ee2,0xc3ed,0xb8fd,0x8ee3,0xb8ae,0x8ee4,0xc5d3,0xb7cf, -0xe2d4,0x8ee5,0x8ee6,0x8ee7,0x8ee8,0xe2d3,0xb6c8,0xd7f9,0x8ee9,0x8eea,0x8eeb,0x8eec,0x8eed,0xcda5,0x8eee,0x8eef, -0x8ef0,0x8ef1,0x8ef2,0xe2d8,0x8ef3,0xe2d6,0xcafc,0xbfb5,0xd3b9,0xe2d5,0x8ef4,0x8ef5,0x8ef6,0x8ef7,0xe2d7,0x8ef8, -0x8ef9,0x8efa,0x8efb,0x8efc,0x8efd,0x8efe,0x8f40,0x8f41,0x8f42,0xc1ae,0xc0c8,0x8f43,0x8f44,0x8f45,0x8f46,0x8f47, -0x8f48,0xe2db,0xe2da,0xc0aa,0x8f49,0x8f4a,0xc1ce,0x8f4b,0x8f4c,0x8f4d,0x8f4e,0xe2dc,0x8f4f,0x8f50,0x8f51,0x8f52, -0x8f53,0x8f54,0x8f55,0x8f56,0x8f57,0x8f58,0x8f59,0x8f5a,0xe2dd,0x8f5b,0xe2de,0x8f5c,0x8f5d,0x8f5e,0x8f5f,0x8f60, -0x8f61,0x8f62,0x8f63,0x8f64,0xdbc8,0x8f65,0xd1d3,0xcda2,0x8f66,0x8f67,0xbda8,0x8f68,0x8f69,0x8f6a,0xdec3,0xd8a5, -0xbfaa,0xdbcd,0xd2ec,0xc6fa,0xc5aa,0x8f6b,0x8f6c,0x8f6d,0xdec4,0x8f6e,0xb1d7,0xdfae,0x8f6f,0x8f70,0x8f71,0xcabd, -0x8f72,0xdfb1,0x8f73,0xb9ad,0x8f74,0xd2fd,0x8f75,0xb8a5,0xbaeb,0x8f76,0x8f77,0xb3da,0x8f78,0x8f79,0x8f7a,0xb5dc, -0xd5c5,0x8f7b,0x8f7c,0x8f7d,0x8f7e,0xc3d6,0xcfd2,0xbba1,0x8f80,0xe5f3,0xe5f2,0x8f81,0x8f82,0xe5f4,0x8f83,0xcde4, -0x8f84,0xc8f5,0x8f85,0x8f86,0x8f87,0x8f88,0x8f89,0x8f8a,0x8f8b,0xb5af,0xc7bf,0x8f8c,0xe5f6,0x8f8d,0x8f8e,0x8f8f, -0xecb0,0x8f90,0x8f91,0x8f92,0x8f93,0x8f94,0x8f95,0x8f96,0x8f97,0x8f98,0x8f99,0x8f9a,0x8f9b,0x8f9c,0x8f9d,0x8f9e, -0xe5e6,0x8f9f,0xb9e9,0xb5b1,0x8fa0,0xc2bc,0xe5e8,0xe5e7,0xe5e9,0x8fa1,0x8fa2,0x8fa3,0x8fa4,0xd2cd,0x8fa5,0x8fa6, -0x8fa7,0xe1ea,0xd0ce,0x8fa8,0xcdae,0x8fa9,0xd1e5,0x8faa,0x8fab,0xb2ca,0xb1eb,0x8fac,0xb1f2,0xc5ed,0x8fad,0x8fae, -0xd5c3,0xd3b0,0x8faf,0xe1dc,0x8fb0,0x8fb1,0x8fb2,0xe1dd,0x8fb3,0xd2db,0x8fb4,0xb3b9,0xb1cb,0x8fb5,0x8fb6,0x8fb7, -0xcdf9,0xd5f7,0xe1de,0x8fb8,0xbeb6,0xb4fd,0x8fb9,0xe1df,0xbadc,0xe1e0,0xbbb2,0xc2c9,0xe1e1,0x8fba,0x8fbb,0x8fbc, -0xd0ec,0x8fbd,0xcdbd,0x8fbe,0x8fbf,0xe1e2,0x8fc0,0xb5c3,0xc5c7,0xe1e3,0x8fc1,0x8fc2,0xe1e4,0x8fc3,0x8fc4,0x8fc5, -0x8fc6,0xd3f9,0x8fc7,0x8fc8,0x8fc9,0x8fca,0x8fcb,0x8fcc,0xe1e5,0x8fcd,0xd1ad,0x8fce,0x8fcf,0xe1e6,0xcea2,0x8fd0, -0x8fd1,0x8fd2,0x8fd3,0x8fd4,0x8fd5,0xe1e7,0x8fd6,0xb5c2,0x8fd7,0x8fd8,0x8fd9,0x8fda,0xe1e8,0xbbd5,0x8fdb,0x8fdc, -0x8fdd,0x8fde,0x8fdf,0xd0c4,0xe2e0,0xb1d8,0xd2e4,0x8fe0,0x8fe1,0xe2e1,0x8fe2,0x8fe3,0xbcc9,0xc8cc,0x8fe4,0xe2e3, -0xecfe,0xecfd,0xdfaf,0x8fe5,0x8fe6,0x8fe7,0xe2e2,0xd6be,0xcdfc,0xc3a6,0x8fe8,0x8fe9,0x8fea,0xe3c3,0x8feb,0x8fec, -0xd6d2,0xe2e7,0x8fed,0x8fee,0xe2e8,0x8fef,0x8ff0,0xd3c7,0x8ff1,0x8ff2,0xe2ec,0xbfec,0x8ff3,0xe2ed,0xe2e5,0x8ff4, -0x8ff5,0xb3c0,0x8ff6,0x8ff7,0x8ff8,0xc4ee,0x8ff9,0x8ffa,0xe2ee,0x8ffb,0x8ffc,0xd0c3,0x8ffd,0xbaf6,0xe2e9,0xb7de, -0xbbb3,0xccac,0xcbcb,0xe2e4,0xe2e6,0xe2ea,0xe2eb,0x8ffe,0x9040,0x9041,0xe2f7,0x9042,0x9043,0xe2f4,0xd4f5,0xe2f3, -0x9044,0x9045,0xc5ad,0x9046,0xd5fa,0xc5c2,0xb2c0,0x9047,0x9048,0xe2ef,0x9049,0xe2f2,0xc1af,0xcbbc,0x904a,0x904b, -0xb5a1,0xe2f9,0x904c,0x904d,0x904e,0xbcb1,0xe2f1,0xd0d4,0xd4b9,0xe2f5,0xb9d6,0xe2f6,0x904f,0x9050,0x9051,0xc7d3, -0x9052,0x9053,0x9054,0x9055,0x9056,0xe2f0,0x9057,0x9058,0x9059,0x905a,0x905b,0xd7dc,0xeda1,0x905c,0x905d,0xe2f8, -0x905e,0xeda5,0xe2fe,0xcad1,0x905f,0x9060,0x9061,0x9062,0x9063,0x9064,0x9065,0xc1b5,0x9066,0xbbd0,0x9067,0x9068, -0xbfd6,0x9069,0xbae3,0x906a,0x906b,0xcba1,0x906c,0x906d,0x906e,0xeda6,0xeda3,0x906f,0x9070,0xeda2,0x9071,0x9072, -0x9073,0x9074,0xbbd6,0xeda7,0xd0f4,0x9075,0x9076,0xeda4,0xbade,0xb6f7,0xe3a1,0xb6b2,0xccf1,0xb9a7,0x9077,0xcfa2, -0xc7a1,0x9078,0x9079,0xbfd2,0x907a,0x907b,0xb6f1,0x907c,0xe2fa,0xe2fb,0xe2fd,0xe2fc,0xc4d5,0xe3a2,0x907d,0xd3c1, -0x907e,0x9080,0x9081,0xe3a7,0xc7c4,0x9082,0x9083,0x9084,0x9085,0xcfa4,0x9086,0x9087,0xe3a9,0xbab7,0x9088,0x9089, -0x908a,0x908b,0xe3a8,0x908c,0xbbda,0x908d,0xe3a3,0x908e,0x908f,0x9090,0xe3a4,0xe3aa,0x9091,0xe3a6,0x9092,0xcef2, -0xd3c6,0x9093,0x9094,0xbbbc,0x9095,0x9096,0xd4c3,0x9097,0xc4fa,0x9098,0x9099,0xeda8,0xd0fc,0xe3a5,0x909a,0xc3f5, -0x909b,0xe3ad,0xb1af,0x909c,0xe3b2,0x909d,0x909e,0x909f,0xbcc2,0x90a0,0x90a1,0xe3ac,0xb5bf,0x90a2,0x90a3,0x90a4, -0x90a5,0x90a6,0x90a7,0x90a8,0x90a9,0xc7e9,0xe3b0,0x90aa,0x90ab,0x90ac,0xbeaa,0xcdef,0x90ad,0x90ae,0x90af,0x90b0, -0x90b1,0xbbf3,0x90b2,0x90b3,0x90b4,0xcce8,0x90b5,0x90b6,0xe3af,0x90b7,0xe3b1,0x90b8,0xcfa7,0xe3ae,0x90b9,0xcea9, -0xbbdd,0x90ba,0x90bb,0x90bc,0x90bd,0x90be,0xb5eb,0xbee5,0xb2d2,0xb3cd,0x90bf,0xb1b9,0xe3ab,0xb2d1,0xb5ac,0xb9df, -0xb6e8,0x90c0,0x90c1,0xcfeb,0xe3b7,0x90c2,0xbbcc,0x90c3,0x90c4,0xc8c7,0xd0ca,0x90c5,0x90c6,0x90c7,0x90c8,0x90c9, -0xe3b8,0xb3ee,0x90ca,0x90cb,0x90cc,0x90cd,0xeda9,0x90ce,0xd3fa,0xd3e4,0x90cf,0x90d0,0x90d1,0xedaa,0xe3b9,0xd2e2, -0x90d2,0x90d3,0x90d4,0x90d5,0x90d6,0xe3b5,0x90d7,0x90d8,0x90d9,0x90da,0xd3de,0x90db,0x90dc,0x90dd,0x90de,0xb8d0, -0xe3b3,0x90df,0x90e0,0xe3b6,0xb7df,0x90e1,0xe3b4,0xc0a2,0x90e2,0x90e3,0x90e4,0xe3ba,0x90e5,0x90e6,0x90e7,0x90e8, -0x90e9,0x90ea,0x90eb,0x90ec,0x90ed,0x90ee,0x90ef,0x90f0,0x90f1,0x90f2,0x90f3,0x90f4,0x90f5,0x90f6,0x90f7,0xd4b8, -0x90f8,0x90f9,0x90fa,0x90fb,0x90fc,0x90fd,0x90fe,0x9140,0xb4c8,0x9141,0xe3bb,0x9142,0xbbc5,0x9143,0xc9f7,0x9144, -0x9145,0xc9e5,0x9146,0x9147,0x9148,0xc4bd,0x9149,0x914a,0x914b,0x914c,0x914d,0x914e,0x914f,0xedab,0x9150,0x9151, -0x9152,0x9153,0xc2fd,0x9154,0x9155,0x9156,0x9157,0xbbdb,0xbfae,0x9158,0x9159,0x915a,0x915b,0x915c,0x915d,0x915e, -0xcebf,0x915f,0x9160,0x9161,0x9162,0xe3bc,0x9163,0xbfb6,0x9164,0x9165,0x9166,0x9167,0x9168,0x9169,0x916a,0x916b, -0x916c,0x916d,0x916e,0x916f,0x9170,0x9171,0x9172,0x9173,0x9174,0x9175,0x9176,0xb1ef,0x9177,0x9178,0xd4f7,0x9179, -0x917a,0x917b,0x917c,0x917d,0xe3be,0x917e,0x9180,0x9181,0x9182,0x9183,0x9184,0x9185,0x9186,0xedad,0x9187,0x9188, -0x9189,0x918a,0x918b,0x918c,0x918d,0x918e,0x918f,0xe3bf,0xbaa9,0xedac,0x9190,0x9191,0xe3bd,0x9192,0x9193,0x9194, -0x9195,0x9196,0x9197,0x9198,0x9199,0x919a,0x919b,0xe3c0,0x919c,0x919d,0x919e,0x919f,0x91a0,0x91a1,0xbab6,0x91a2, -0x91a3,0x91a4,0xb6ae,0x91a5,0x91a6,0x91a7,0x91a8,0x91a9,0xd0b8,0x91aa,0xb0c3,0xedae,0x91ab,0x91ac,0x91ad,0x91ae, -0x91af,0xedaf,0xc0c1,0x91b0,0xe3c1,0x91b1,0x91b2,0x91b3,0x91b4,0x91b5,0x91b6,0x91b7,0x91b8,0x91b9,0x91ba,0x91bb, -0x91bc,0x91bd,0x91be,0x91bf,0x91c0,0x91c1,0xc5b3,0x91c2,0x91c3,0x91c4,0x91c5,0x91c6,0x91c7,0x91c8,0x91c9,0x91ca, -0x91cb,0x91cc,0x91cd,0x91ce,0x91cf,0xe3c2,0x91d0,0x91d1,0x91d2,0x91d3,0x91d4,0x91d5,0x91d6,0x91d7,0x91d8,0xdcb2, -0x91d9,0x91da,0x91db,0x91dc,0x91dd,0x91de,0xedb0,0x91df,0xb8ea,0x91e0,0xceec,0xeaa7,0xd0e7,0xcaf9,0xc8d6,0xcfb7, -0xb3c9,0xced2,0xbde4,0x91e1,0x91e2,0xe3de,0xbbf2,0xeaa8,0xd5bd,0x91e3,0xc6dd,0xeaa9,0x91e4,0x91e5,0x91e6,0xeaaa, -0x91e7,0xeaac,0xeaab,0x91e8,0xeaae,0xeaad,0x91e9,0x91ea,0x91eb,0x91ec,0xbdd8,0x91ed,0xeaaf,0x91ee,0xc2be,0x91ef, -0x91f0,0x91f1,0x91f2,0xb4c1,0xb4f7,0x91f3,0x91f4,0xbba7,0x91f5,0x91f6,0x91f7,0x91f8,0x91f9,0xece6,0xece5,0xb7bf, -0xcbf9,0xb1e2,0x91fa,0xece7,0x91fb,0x91fc,0x91fd,0xc9c8,0xece8,0xece9,0x91fe,0xcad6,0xded0,0xb2c5,0xd4fa,0x9240, -0x9241,0xc6cb,0xb0c7,0xb4f2,0xc8d3,0x9242,0x9243,0x9244,0xcdd0,0x9245,0x9246,0xbfb8,0x9247,0x9248,0x9249,0x924a, -0x924b,0x924c,0x924d,0xbfdb,0x924e,0x924f,0xc7a4,0xd6b4,0x9250,0xc0a9,0xded1,0xc9a8,0xd1ef,0xc5a4,0xb0e7,0xb3b6, -0xc8c5,0x9251,0x9252,0xb0e2,0x9253,0x9254,0xb7f6,0x9255,0x9256,0xc5fa,0x9257,0x9258,0xb6f3,0x9259,0xd5d2,0xb3d0, -0xbcbc,0x925a,0x925b,0x925c,0xb3ad,0x925d,0x925e,0x925f,0x9260,0xbef1,0xb0d1,0x9261,0x9262,0x9263,0x9264,0x9265, -0x9266,0xd2d6,0xcae3,0xd7a5,0x9267,0xcdb6,0xb6b6,0xbfb9,0xd5db,0x9268,0xb8a7,0xc5d7,0x9269,0x926a,0x926b,0xded2, -0xbfd9,0xc2d5,0xc7c0,0x926c,0xbba4,0xb1a8,0x926d,0x926e,0xc5ea,0x926f,0x9270,0xc5fb,0xcca7,0x9271,0x9272,0x9273, -0x9274,0xb1a7,0x9275,0x9276,0x9277,0xb5d6,0x9278,0x9279,0x927a,0xc4a8,0x927b,0xded3,0xd1ba,0xb3e9,0x927c,0xc3f2, -0x927d,0x927e,0xb7f7,0x9280,0xd6f4,0xb5a3,0xb2f0,0xc4b4,0xc4e9,0xc0ad,0xded4,0x9281,0xb0e8,0xc5c4,0xc1e0,0x9282, -0xb9d5,0x9283,0xbedc,0xcdd8,0xb0ce,0x9284,0xcdcf,0xded6,0xbed0,0xd7be,0xded5,0xd5d0,0xb0dd,0x9285,0x9286,0xc4e2, -0x9287,0x9288,0xc2a3,0xbcf0,0x9289,0xd3b5,0xc0b9,0xc5a1,0xb2a6,0xd4f1,0x928a,0x928b,0xc0a8,0xcac3,0xded7,0xd5fc, -0x928c,0xb9b0,0x928d,0xc8ad,0xcba9,0x928e,0xded9,0xbfbd,0x928f,0x9290,0x9291,0x9292,0xc6b4,0xd7a7,0xcab0,0xc4c3, -0x9293,0xb3d6,0xb9d2,0x9294,0x9295,0x9296,0x9297,0xd6b8,0xeafc,0xb0b4,0x9298,0x9299,0x929a,0x929b,0xbfe6,0x929c, -0x929d,0xccf4,0x929e,0x929f,0x92a0,0x92a1,0xcdda,0x92a2,0x92a3,0x92a4,0xd6bf,0xc2ce,0x92a5,0xcece,0xcca2,0xd0ae, -0xc4d3,0xb5b2,0xded8,0xd5f5,0xbcb7,0xbbd3,0x92a6,0x92a7,0xb0a4,0x92a8,0xc5b2,0xb4ec,0x92a9,0x92aa,0x92ab,0xd5f1, -0x92ac,0x92ad,0xeafd,0x92ae,0x92af,0x92b0,0x92b1,0x92b2,0x92b3,0xdeda,0xcda6,0x92b4,0x92b5,0xcdec,0x92b6,0x92b7, -0x92b8,0x92b9,0xcee6,0xdedc,0x92ba,0xcdb1,0xc0a6,0x92bb,0x92bc,0xd7bd,0x92bd,0xdedb,0xb0c6,0xbab4,0xc9d3,0xc4f3, -0xbee8,0x92be,0x92bf,0x92c0,0x92c1,0xb2b6,0x92c2,0x92c3,0x92c4,0x92c5,0x92c6,0x92c7,0x92c8,0x92c9,0xc0cc,0xcbf0, -0x92ca,0xbcf1,0xbbbb,0xb5b7,0x92cb,0x92cc,0x92cd,0xc5f5,0x92ce,0xdee6,0x92cf,0x92d0,0x92d1,0xdee3,0xbedd,0x92d2, -0x92d3,0xdedf,0x92d4,0x92d5,0x92d6,0x92d7,0xb4b7,0xbddd,0x92d8,0x92d9,0xdee0,0xc4ed,0x92da,0x92db,0x92dc,0x92dd, -0xcfc6,0x92de,0xb5e0,0x92df,0x92e0,0x92e1,0x92e2,0xb6de,0xcada,0xb5f4,0xdee5,0x92e3,0xd5c6,0x92e4,0xdee1,0xcccd, -0xc6fe,0x92e5,0xc5c5,0x92e6,0x92e7,0x92e8,0xd2b4,0x92e9,0xbef2,0x92ea,0x92eb,0x92ec,0x92ed,0x92ee,0x92ef,0x92f0, -0xc2d3,0x92f1,0xccbd,0xb3b8,0x92f2,0xbdd3,0x92f3,0xbfd8,0xcdc6,0xd1da,0xb4eb,0x92f4,0xdee4,0xdedd,0xdee7,0x92f5, -0xeafe,0x92f6,0x92f7,0xc2b0,0xdee2,0x92f8,0x92f9,0xd6c0,0xb5a7,0x92fa,0xb2f4,0x92fb,0xdee8,0x92fc,0xdef2,0x92fd, -0x92fe,0x9340,0x9341,0x9342,0xdeed,0x9343,0xdef1,0x9344,0x9345,0xc8e0,0x9346,0x9347,0x9348,0xd7e1,0xdeef,0xc3e8, -0xcce1,0x9349,0xb2e5,0x934a,0x934b,0x934c,0xd2be,0x934d,0x934e,0x934f,0x9350,0x9351,0x9352,0x9353,0xdeee,0x9354, -0xdeeb,0xced5,0x9355,0xb4a7,0x9356,0x9357,0x9358,0x9359,0x935a,0xbfab,0xbebe,0x935b,0x935c,0xbdd2,0x935d,0x935e, -0x935f,0x9360,0xdee9,0x9361,0xd4ae,0x9362,0xdede,0x9363,0xdeea,0x9364,0x9365,0x9366,0x9367,0xc0bf,0x9368,0xdeec, -0xb2f3,0xb8e9,0xc2a7,0x9369,0x936a,0xbdc1,0x936b,0x936c,0x936d,0x936e,0x936f,0xdef5,0xdef8,0x9370,0x9371,0xb2ab, -0xb4a4,0x9372,0x9373,0xb4ea,0xc9a6,0x9374,0x9375,0x9376,0x9377,0x9378,0x9379,0xdef6,0xcbd1,0x937a,0xb8e3,0x937b, -0xdef7,0xdefa,0x937c,0x937d,0x937e,0x9380,0xdef9,0x9381,0x9382,0x9383,0xccc2,0x9384,0xb0e1,0xb4ee,0x9385,0x9386, -0x9387,0x9388,0x9389,0x938a,0xe5ba,0x938b,0x938c,0x938d,0x938e,0x938f,0xd0af,0x9390,0x9391,0xb2eb,0x9392,0xeba1, -0x9393,0xdef4,0x9394,0x9395,0xc9e3,0xdef3,0xb0da,0xd2a1,0xb1f7,0x9396,0xccaf,0x9397,0x9398,0x9399,0x939a,0x939b, -0x939c,0x939d,0xdef0,0x939e,0xcba4,0x939f,0x93a0,0x93a1,0xd5aa,0x93a2,0x93a3,0x93a4,0x93a5,0x93a6,0xdefb,0x93a7, -0x93a8,0x93a9,0x93aa,0x93ab,0x93ac,0x93ad,0x93ae,0xb4dd,0x93af,0xc4a6,0x93b0,0x93b1,0x93b2,0xdefd,0x93b3,0x93b4, -0x93b5,0x93b6,0x93b7,0x93b8,0x93b9,0x93ba,0x93bb,0x93bc,0xc3fe,0xc4a1,0xdfa1,0x93bd,0x93be,0x93bf,0x93c0,0x93c1, -0x93c2,0x93c3,0xc1cc,0x93c4,0xdefc,0xbeef,0x93c5,0xc6b2,0x93c6,0x93c7,0x93c8,0x93c9,0x93ca,0x93cb,0x93cc,0x93cd, -0x93ce,0xb3c5,0xc8f6,0x93cf,0x93d0,0xcbba,0xdefe,0x93d1,0x93d2,0xdfa4,0x93d3,0x93d4,0x93d5,0x93d6,0xd7b2,0x93d7, -0x93d8,0x93d9,0x93da,0x93db,0xb3b7,0x93dc,0x93dd,0x93de,0x93df,0xc1c3,0x93e0,0x93e1,0xc7cb,0xb2a5,0xb4e9,0x93e2, -0xd7ab,0x93e3,0x93e4,0x93e5,0x93e6,0xc4ec,0x93e7,0xdfa2,0xdfa3,0x93e8,0xdfa5,0x93e9,0xbab3,0x93ea,0x93eb,0x93ec, -0xdfa6,0x93ed,0xc0de,0x93ee,0x93ef,0xc9c3,0x93f0,0x93f1,0x93f2,0x93f3,0x93f4,0x93f5,0x93f6,0xb2d9,0xc7e6,0x93f7, -0xdfa7,0x93f8,0xc7dc,0x93f9,0x93fa,0x93fb,0x93fc,0xdfa8,0xeba2,0x93fd,0x93fe,0x9440,0x9441,0x9442,0xcbd3,0x9443, -0x9444,0x9445,0xdfaa,0x9446,0xdfa9,0x9447,0xb2c1,0x9448,0x9449,0x944a,0x944b,0x944c,0x944d,0x944e,0x944f,0x9450, -0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,0x9458,0x9459,0x945a,0x945b,0x945c,0x945d,0x945e,0x945f,0x9460, -0xc5ca,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467,0x9468,0xdfab,0x9469,0x946a,0x946b,0x946c,0x946d,0x946e, -0x946f,0x9470,0xd4dc,0x9471,0x9472,0x9473,0x9474,0x9475,0xc8c1,0x9476,0x9477,0x9478,0x9479,0x947a,0x947b,0x947c, -0x947d,0x947e,0x9480,0x9481,0x9482,0xdfac,0x9483,0x9484,0x9485,0x9486,0x9487,0xbef0,0x9488,0x9489,0xdfad,0xd6a7, -0x948a,0x948b,0x948c,0x948d,0xeab7,0xebb6,0xcad5,0x948e,0xd8fc,0xb8c4,0x948f,0xb9a5,0x9490,0x9491,0xb7c5,0xd5fe, -0x9492,0x9493,0x9494,0x9495,0x9496,0xb9ca,0x9497,0x9498,0xd0a7,0xf4cd,0x9499,0x949a,0xb5d0,0x949b,0x949c,0xc3f4, -0x949d,0xbec8,0x949e,0x949f,0x94a0,0xebb7,0xb0bd,0x94a1,0x94a2,0xbdcc,0x94a3,0xc1b2,0x94a4,0xb1d6,0xb3a8,0x94a5, -0x94a6,0x94a7,0xb8d2,0xc9a2,0x94a8,0x94a9,0xb6d8,0x94aa,0x94ab,0x94ac,0x94ad,0xebb8,0xbeb4,0x94ae,0x94af,0x94b0, -0xcafd,0x94b1,0xc7c3,0x94b2,0xd5fb,0x94b3,0x94b4,0xb7f3,0x94b5,0x94b6,0x94b7,0x94b8,0x94b9,0x94ba,0x94bb,0x94bc, -0x94bd,0x94be,0x94bf,0x94c0,0x94c1,0x94c2,0x94c3,0xcec4,0x94c4,0x94c5,0x94c6,0xd5ab,0xb1f3,0x94c7,0x94c8,0x94c9, -0xecb3,0xb0df,0x94ca,0xecb5,0x94cb,0x94cc,0x94cd,0xb6b7,0x94ce,0xc1cf,0x94cf,0xf5fa,0xd0b1,0x94d0,0x94d1,0xd5e5, -0x94d2,0xced3,0x94d3,0x94d4,0xbdef,0xb3e2,0x94d5,0xb8ab,0x94d6,0xd5b6,0x94d7,0xedbd,0x94d8,0xb6cf,0x94d9,0xcbb9, -0xd0c2,0x94da,0x94db,0x94dc,0x94dd,0x94de,0x94df,0x94e0,0x94e1,0xb7bd,0x94e2,0x94e3,0xecb6,0xcaa9,0x94e4,0x94e5, -0x94e6,0xc5d4,0x94e7,0xecb9,0xecb8,0xc2c3,0xecb7,0x94e8,0x94e9,0x94ea,0x94eb,0xd0fd,0xecba,0x94ec,0xecbb,0xd7e5, -0x94ed,0x94ee,0xecbc,0x94ef,0x94f0,0x94f1,0xecbd,0xc6ec,0x94f2,0x94f3,0x94f4,0x94f5,0x94f6,0x94f7,0x94f8,0x94f9, -0xcede,0x94fa,0xbcc8,0x94fb,0x94fc,0xc8d5,0xb5a9,0xbec9,0xd6bc,0xd4e7,0x94fd,0x94fe,0xd1ae,0xd0f1,0xeab8,0xeab9, -0xeaba,0xbab5,0x9540,0x9541,0x9542,0x9543,0xcab1,0xbff5,0x9544,0x9545,0xcdfa,0x9546,0x9547,0x9548,0x9549,0x954a, -0xeac0,0x954b,0xb0ba,0xeabe,0x954c,0x954d,0xc0a5,0x954e,0x954f,0x9550,0xeabb,0x9551,0xb2fd,0x9552,0xc3f7,0xbbe8, -0x9553,0x9554,0x9555,0xd2d7,0xcef4,0xeabf,0x9556,0x9557,0x9558,0xeabc,0x9559,0x955a,0x955b,0xeac3,0x955c,0xd0c7, -0xd3b3,0x955d,0x955e,0x955f,0x9560,0xb4ba,0x9561,0xc3c1,0xd7f2,0x9562,0x9563,0x9564,0x9565,0xd5d1,0x9566,0xcac7, -0x9567,0xeac5,0x9568,0x9569,0xeac4,0xeac7,0xeac6,0x956a,0x956b,0x956c,0x956d,0x956e,0xd6e7,0x956f,0xcfd4,0x9570, -0x9571,0xeacb,0x9572,0xbbce,0x9573,0x9574,0x9575,0x9576,0x9577,0x9578,0x9579,0xbdfa,0xc9ce,0x957a,0x957b,0xeacc, -0x957c,0x957d,0xc9b9,0xcffe,0xeaca,0xd4ce,0xeacd,0xeacf,0x957e,0x9580,0xcded,0x9581,0x9582,0x9583,0x9584,0xeac9, -0x9585,0xeace,0x9586,0x9587,0xceee,0x9588,0xbbde,0x9589,0xb3bf,0x958a,0x958b,0x958c,0x958d,0x958e,0xc6d5,0xbeb0, -0xcefa,0x958f,0x9590,0x9591,0xc7e7,0x9592,0xbea7,0xead0,0x9593,0x9594,0xd6c7,0x9595,0x9596,0x9597,0xc1c0,0x9598, -0x9599,0x959a,0xd4dd,0x959b,0xead1,0x959c,0x959d,0xcfbe,0x959e,0x959f,0x95a0,0x95a1,0xead2,0x95a2,0x95a3,0x95a4, -0x95a5,0xcaee,0x95a6,0x95a7,0x95a8,0x95a9,0xc5af,0xb0b5,0x95aa,0x95ab,0x95ac,0x95ad,0x95ae,0xead4,0x95af,0x95b0, -0x95b1,0x95b2,0x95b3,0x95b4,0x95b5,0x95b6,0x95b7,0xead3,0xf4df,0x95b8,0x95b9,0x95ba,0x95bb,0x95bc,0xc4ba,0x95bd, -0x95be,0x95bf,0x95c0,0x95c1,0xb1a9,0x95c2,0x95c3,0x95c4,0x95c5,0xe5df,0x95c6,0x95c7,0x95c8,0x95c9,0xead5,0x95ca, -0x95cb,0x95cc,0x95cd,0x95ce,0x95cf,0x95d0,0x95d1,0x95d2,0x95d3,0x95d4,0x95d5,0x95d6,0x95d7,0x95d8,0x95d9,0x95da, -0x95db,0x95dc,0x95dd,0x95de,0x95df,0x95e0,0x95e1,0x95e2,0x95e3,0xcaef,0x95e4,0xead6,0xead7,0xc6d8,0x95e5,0x95e6, -0x95e7,0x95e8,0x95e9,0x95ea,0x95eb,0x95ec,0xead8,0x95ed,0x95ee,0xead9,0x95ef,0x95f0,0x95f1,0x95f2,0x95f3,0x95f4, -0xd4bb,0x95f5,0xc7fa,0xd2b7,0xb8fc,0x95f6,0x95f7,0xeac2,0x95f8,0xb2dc,0x95f9,0x95fa,0xc2fc,0x95fb,0xd4f8,0xcce6, -0xd7ee,0x95fc,0x95fd,0x95fe,0x9640,0x9641,0x9642,0x9643,0xd4c2,0xd3d0,0xebc3,0xc5f3,0x9644,0xb7fe,0x9645,0x9646, -0xebd4,0x9647,0x9648,0x9649,0xcbb7,0xebde,0x964a,0xc0ca,0x964b,0x964c,0x964d,0xcdfb,0x964e,0xb3af,0x964f,0xc6da, -0x9650,0x9651,0x9652,0x9653,0x9654,0x9655,0xebfc,0x9656,0xc4be,0x9657,0xceb4,0xc4a9,0xb1be,0xd4fd,0x9658,0xcaf5, -0x9659,0xd6ec,0x965a,0x965b,0xc6d3,0xb6e4,0x965c,0x965d,0x965e,0x965f,0xbbfa,0x9660,0x9661,0xd0e0,0x9662,0x9663, -0xc9b1,0x9664,0xd4d3,0xc8a8,0x9665,0x9666,0xb8cb,0x9667,0xe8be,0xc9bc,0x9668,0x9669,0xe8bb,0x966a,0xc0ee,0xd0d3, -0xb2c4,0xb4e5,0x966b,0xe8bc,0x966c,0x966d,0xd5c8,0x966e,0x966f,0x9670,0x9671,0x9672,0xb6c5,0x9673,0xe8bd,0xcaf8, -0xb8dc,0xccf5,0x9674,0x9675,0x9676,0xc0b4,0x9677,0x9678,0xd1ee,0xe8bf,0xe8c2,0x9679,0x967a,0xbabc,0x967b,0xb1ad, -0xbddc,0x967c,0xeabd,0xe8c3,0x967d,0xe8c6,0x967e,0xe8cb,0x9680,0x9681,0x9682,0x9683,0xe8cc,0x9684,0xcbc9,0xb0e5, -0x9685,0xbcab,0x9686,0x9687,0xb9b9,0x9688,0x9689,0xe8c1,0x968a,0xcdf7,0x968b,0xe8ca,0x968c,0x968d,0x968e,0x968f, -0xcef6,0x9690,0x9691,0x9692,0x9693,0xd5ed,0x9694,0xc1d6,0xe8c4,0x9695,0xc3b6,0x9696,0xb9fb,0xd6a6,0xe8c8,0x9697, -0x9698,0x9699,0xcae0,0xd4e6,0x969a,0xe8c0,0x969b,0xe8c5,0xe8c7,0x969c,0xc7b9,0xb7e3,0x969d,0xe8c9,0x969e,0xbfdd, -0xe8d2,0x969f,0x96a0,0xe8d7,0x96a1,0xe8d5,0xbcdc,0xbccf,0xe8db,0x96a2,0x96a3,0x96a4,0x96a5,0x96a6,0x96a7,0x96a8, -0x96a9,0xe8de,0x96aa,0xe8da,0xb1fa,0x96ab,0x96ac,0x96ad,0x96ae,0x96af,0x96b0,0x96b1,0x96b2,0x96b3,0x96b4,0xb0d8, -0xc4b3,0xb8cc,0xc6e2,0xc8be,0xc8e1,0x96b5,0x96b6,0x96b7,0xe8cf,0xe8d4,0xe8d6,0x96b8,0xb9f1,0xe8d8,0xd7f5,0x96b9, -0xc4fb,0x96ba,0xe8dc,0x96bb,0x96bc,0xb2e9,0x96bd,0x96be,0x96bf,0xe8d1,0x96c0,0x96c1,0xbced,0x96c2,0x96c3,0xbfc2, -0xe8cd,0xd6f9,0x96c4,0xc1f8,0xb2f1,0x96c5,0x96c6,0x96c7,0x96c8,0x96c9,0x96ca,0x96cb,0x96cc,0xe8df,0x96cd,0xcac1, -0xe8d9,0x96ce,0x96cf,0x96d0,0x96d1,0xd5a4,0x96d2,0xb1ea,0xd5bb,0xe8ce,0xe8d0,0xb6b0,0xe8d3,0x96d3,0xe8dd,0xc0b8, -0x96d4,0xcaf7,0x96d5,0xcba8,0x96d6,0x96d7,0xc6dc,0xc0f5,0x96d8,0x96d9,0x96da,0x96db,0x96dc,0xe8e9,0x96dd,0x96de, -0x96df,0xd0a3,0x96e0,0x96e1,0x96e2,0x96e3,0x96e4,0x96e5,0x96e6,0xe8f2,0xd6ea,0x96e7,0x96e8,0x96e9,0x96ea,0x96eb, -0x96ec,0x96ed,0xe8e0,0xe8e1,0x96ee,0x96ef,0x96f0,0xd1f9,0xbacb,0xb8f9,0x96f1,0x96f2,0xb8f1,0xd4d4,0xe8ef,0x96f3, -0xe8ee,0xe8ec,0xb9f0,0xccd2,0xe8e6,0xcea6,0xbff2,0x96f4,0xb0b8,0xe8f1,0xe8f0,0x96f5,0xd7c0,0x96f6,0xe8e4,0x96f7, -0xcda9,0xc9a3,0x96f8,0xbbb8,0xbddb,0xe8ea,0x96f9,0x96fa,0x96fb,0x96fc,0x96fd,0x96fe,0x9740,0x9741,0x9742,0x9743, -0xe8e2,0xe8e3,0xe8e5,0xb5b5,0xe8e7,0xc7c5,0xe8eb,0xe8ed,0xbdb0,0xd7ae,0x9744,0xe8f8,0x9745,0x9746,0x9747,0x9748, -0x9749,0x974a,0x974b,0x974c,0xe8f5,0x974d,0xcdb0,0xe8f6,0x974e,0x974f,0x9750,0x9751,0x9752,0x9753,0x9754,0x9755, -0x9756,0xc1ba,0x9757,0xe8e8,0x9758,0xc3b7,0xb0f0,0x9759,0x975a,0x975b,0x975c,0x975d,0x975e,0x975f,0x9760,0xe8f4, -0x9761,0x9762,0x9763,0xe8f7,0x9764,0x9765,0x9766,0xb9a3,0x9767,0x9768,0x9769,0x976a,0x976b,0x976c,0x976d,0x976e, -0x976f,0x9770,0xc9d2,0x9771,0x9772,0x9773,0xc3ce,0xcee0,0xc0e6,0x9774,0x9775,0x9776,0x9777,0xcbf3,0x9778,0xccdd, -0xd0b5,0x9779,0x977a,0xcae1,0x977b,0xe8f3,0x977c,0x977d,0x977e,0x9780,0x9781,0x9782,0x9783,0x9784,0x9785,0x9786, -0xbcec,0x9787,0xe8f9,0x9788,0x9789,0x978a,0x978b,0x978c,0x978d,0xc3de,0x978e,0xc6e5,0x978f,0xb9f7,0x9790,0x9791, -0x9792,0x9793,0xb0f4,0x9794,0x9795,0xd7d8,0x9796,0x9797,0xbcac,0x9798,0xc5ef,0x9799,0x979a,0x979b,0x979c,0x979d, -0xccc4,0x979e,0x979f,0xe9a6,0x97a0,0x97a1,0x97a2,0x97a3,0x97a4,0x97a5,0x97a6,0x97a7,0x97a8,0x97a9,0xc9ad,0x97aa, -0xe9a2,0xc0e2,0x97ab,0x97ac,0x97ad,0xbfc3,0x97ae,0x97af,0x97b0,0xe8fe,0xb9d7,0x97b1,0xe8fb,0x97b2,0x97b3,0x97b4, -0x97b5,0xe9a4,0x97b6,0x97b7,0x97b8,0xd2ce,0x97b9,0x97ba,0x97bb,0x97bc,0x97bd,0xe9a3,0x97be,0xd6b2,0xd7b5,0x97bf, -0xe9a7,0x97c0,0xbdb7,0x97c1,0x97c2,0x97c3,0x97c4,0x97c5,0x97c6,0x97c7,0x97c8,0x97c9,0x97ca,0x97cb,0x97cc,0xe8fc, -0xe8fd,0x97cd,0x97ce,0x97cf,0xe9a1,0x97d0,0x97d1,0x97d2,0x97d3,0x97d4,0x97d5,0x97d6,0x97d7,0xcdd6,0x97d8,0x97d9, -0xd2ac,0x97da,0x97db,0x97dc,0xe9b2,0x97dd,0x97de,0x97df,0x97e0,0xe9a9,0x97e1,0x97e2,0x97e3,0xb4aa,0x97e4,0xb4bb, -0x97e5,0x97e6,0xe9ab,0x97e7,0x97e8,0x97e9,0x97ea,0x97eb,0x97ec,0x97ed,0x97ee,0x97ef,0x97f0,0x97f1,0x97f2,0x97f3, -0x97f4,0x97f5,0x97f6,0x97f7,0xd0a8,0x97f8,0x97f9,0xe9a5,0x97fa,0x97fb,0xb3fe,0x97fc,0x97fd,0xe9ac,0xc0e3,0x97fe, -0xe9aa,0x9840,0x9841,0xe9b9,0x9842,0x9843,0xe9b8,0x9844,0x9845,0x9846,0x9847,0xe9ae,0x9848,0x9849,0xe8fa,0x984a, -0x984b,0xe9a8,0x984c,0x984d,0x984e,0x984f,0x9850,0xbfac,0xe9b1,0xe9ba,0x9851,0x9852,0xc2a5,0x9853,0x9854,0x9855, -0xe9af,0x9856,0xb8c5,0x9857,0xe9ad,0x9858,0xd3dc,0xe9b4,0xe9b5,0xe9b7,0x9859,0x985a,0x985b,0xe9c7,0x985c,0x985d, -0x985e,0x985f,0x9860,0x9861,0xc0c6,0xe9c5,0x9862,0x9863,0xe9b0,0x9864,0x9865,0xe9bb,0xb0f1,0x9866,0x9867,0x9868, -0x9869,0x986a,0x986b,0x986c,0x986d,0x986e,0x986f,0xe9bc,0xd5a5,0x9870,0x9871,0xe9be,0x9872,0xe9bf,0x9873,0x9874, -0x9875,0xe9c1,0x9876,0x9877,0xc1f1,0x9878,0x9879,0xc8b6,0x987a,0x987b,0x987c,0xe9bd,0x987d,0x987e,0x9880,0x9881, -0x9882,0xe9c2,0x9883,0x9884,0x9885,0x9886,0x9887,0x9888,0x9889,0x988a,0xe9c3,0x988b,0xe9b3,0x988c,0xe9b6,0x988d, -0xbbb1,0x988e,0x988f,0x9890,0xe9c0,0x9891,0x9892,0x9893,0x9894,0x9895,0x9896,0xbcf7,0x9897,0x9898,0x9899,0xe9c4, -0xe9c6,0x989a,0x989b,0x989c,0x989d,0x989e,0x989f,0x98a0,0x98a1,0x98a2,0x98a3,0x98a4,0x98a5,0xe9ca,0x98a6,0x98a7, -0x98a8,0x98a9,0xe9ce,0x98aa,0x98ab,0x98ac,0x98ad,0x98ae,0x98af,0x98b0,0x98b1,0x98b2,0x98b3,0xb2db,0x98b4,0xe9c8, -0x98b5,0x98b6,0x98b7,0x98b8,0x98b9,0x98ba,0x98bb,0x98bc,0x98bd,0x98be,0xb7ae,0x98bf,0x98c0,0x98c1,0x98c2,0x98c3, -0x98c4,0x98c5,0x98c6,0x98c7,0x98c8,0x98c9,0x98ca,0xe9cb,0xe9cc,0x98cb,0x98cc,0x98cd,0x98ce,0x98cf,0x98d0,0xd5c1, -0x98d1,0xc4a3,0x98d2,0x98d3,0x98d4,0x98d5,0x98d6,0x98d7,0xe9d8,0x98d8,0xbae1,0x98d9,0x98da,0x98db,0x98dc,0xe9c9, -0x98dd,0xd3a3,0x98de,0x98df,0x98e0,0xe9d4,0x98e1,0x98e2,0x98e3,0x98e4,0x98e5,0x98e6,0x98e7,0xe9d7,0xe9d0,0x98e8, -0x98e9,0x98ea,0x98eb,0x98ec,0xe9cf,0x98ed,0x98ee,0xc7c1,0x98ef,0x98f0,0x98f1,0x98f2,0x98f3,0x98f4,0x98f5,0x98f6, -0xe9d2,0x98f7,0x98f8,0x98f9,0x98fa,0x98fb,0x98fc,0x98fd,0xe9d9,0xb3c8,0x98fe,0xe9d3,0x9940,0x9941,0x9942,0x9943, -0x9944,0xcff0,0x9945,0x9946,0x9947,0xe9cd,0x9948,0x9949,0x994a,0x994b,0x994c,0x994d,0x994e,0x994f,0x9950,0x9951, -0x9952,0xb3f7,0x9953,0x9954,0x9955,0x9956,0x9957,0x9958,0x9959,0xe9d6,0x995a,0x995b,0xe9da,0x995c,0x995d,0x995e, -0xccb4,0x995f,0x9960,0x9961,0xcfad,0x9962,0x9963,0x9964,0x9965,0x9966,0x9967,0x9968,0x9969,0x996a,0xe9d5,0x996b, -0xe9dc,0xe9db,0x996c,0x996d,0x996e,0x996f,0x9970,0xe9de,0x9971,0x9972,0x9973,0x9974,0x9975,0x9976,0x9977,0x9978, -0xe9d1,0x9979,0x997a,0x997b,0x997c,0x997d,0x997e,0x9980,0x9981,0xe9dd,0x9982,0xe9df,0xc3ca,0x9983,0x9984,0x9985, -0x9986,0x9987,0x9988,0x9989,0x998a,0x998b,0x998c,0x998d,0x998e,0x998f,0x9990,0x9991,0x9992,0x9993,0x9994,0x9995, -0x9996,0x9997,0x9998,0x9999,0x999a,0x999b,0x999c,0x999d,0x999e,0x999f,0x99a0,0x99a1,0x99a2,0x99a3,0x99a4,0x99a5, -0x99a6,0x99a7,0x99a8,0x99a9,0x99aa,0x99ab,0x99ac,0x99ad,0x99ae,0x99af,0x99b0,0x99b1,0x99b2,0x99b3,0x99b4,0x99b5, -0x99b6,0x99b7,0x99b8,0x99b9,0x99ba,0x99bb,0x99bc,0x99bd,0x99be,0x99bf,0x99c0,0x99c1,0x99c2,0x99c3,0x99c4,0x99c5, -0x99c6,0x99c7,0x99c8,0x99c9,0x99ca,0x99cb,0x99cc,0x99cd,0x99ce,0x99cf,0x99d0,0x99d1,0x99d2,0x99d3,0x99d4,0x99d5, -0x99d6,0x99d7,0x99d8,0x99d9,0x99da,0x99db,0x99dc,0x99dd,0x99de,0x99df,0x99e0,0x99e1,0x99e2,0x99e3,0x99e4,0x99e5, -0x99e6,0x99e7,0x99e8,0x99e9,0x99ea,0x99eb,0x99ec,0x99ed,0x99ee,0x99ef,0x99f0,0x99f1,0x99f2,0x99f3,0x99f4,0x99f5, -0xc7b7,0xb4ce,0xbbb6,0xd0c0,0xeca3,0x99f6,0x99f7,0xc5b7,0x99f8,0x99f9,0x99fa,0x99fb,0x99fc,0x99fd,0x99fe,0x9a40, -0x9a41,0x9a42,0xd3fb,0x9a43,0x9a44,0x9a45,0x9a46,0xeca4,0x9a47,0xeca5,0xc6db,0x9a48,0x9a49,0x9a4a,0xbfee,0x9a4b, -0x9a4c,0x9a4d,0x9a4e,0xeca6,0x9a4f,0x9a50,0xeca7,0xd0aa,0x9a51,0xc7b8,0x9a52,0x9a53,0xb8e8,0x9a54,0x9a55,0x9a56, -0x9a57,0x9a58,0x9a59,0x9a5a,0x9a5b,0x9a5c,0x9a5d,0x9a5e,0x9a5f,0xeca8,0x9a60,0x9a61,0x9a62,0x9a63,0x9a64,0x9a65, -0x9a66,0x9a67,0xd6b9,0xd5fd,0xb4cb,0xb2bd,0xcee4,0xc6e7,0x9a68,0x9a69,0xcde1,0x9a6a,0x9a6b,0x9a6c,0x9a6d,0x9a6e, -0x9a6f,0x9a70,0x9a71,0x9a72,0x9a73,0x9a74,0x9a75,0x9a76,0x9a77,0xb4f5,0x9a78,0xcbc0,0xbcdf,0x9a79,0x9a7a,0x9a7b, -0x9a7c,0xe9e2,0xe9e3,0xd1ea,0xe9e5,0x9a7d,0xb4f9,0xe9e4,0x9a7e,0xd1b3,0xcae2,0xb2d0,0x9a80,0xe9e8,0x9a81,0x9a82, -0x9a83,0x9a84,0xe9e6,0xe9e7,0x9a85,0x9a86,0xd6b3,0x9a87,0x9a88,0x9a89,0xe9e9,0xe9ea,0x9a8a,0x9a8b,0x9a8c,0x9a8d, -0x9a8e,0xe9eb,0x9a8f,0x9a90,0x9a91,0x9a92,0x9a93,0x9a94,0x9a95,0x9a96,0xe9ec,0x9a97,0x9a98,0x9a99,0x9a9a,0x9a9b, -0x9a9c,0x9a9d,0x9a9e,0xecaf,0xc5b9,0xb6ce,0x9a9f,0xd2f3,0x9aa0,0x9aa1,0x9aa2,0x9aa3,0x9aa4,0x9aa5,0x9aa6,0xb5ee, -0x9aa7,0xbbd9,0xecb1,0x9aa8,0x9aa9,0xd2e3,0x9aaa,0x9aab,0x9aac,0x9aad,0x9aae,0xcee3,0x9aaf,0xc4b8,0x9ab0,0xc3bf, -0x9ab1,0x9ab2,0xb6be,0xd8b9,0xb1c8,0xb1cf,0xb1d1,0xc5fe,0x9ab3,0xb1d0,0x9ab4,0xc3ab,0x9ab5,0x9ab6,0x9ab7,0x9ab8, -0x9ab9,0xd5b1,0x9aba,0x9abb,0x9abc,0x9abd,0x9abe,0x9abf,0x9ac0,0x9ac1,0xeba4,0xbac1,0x9ac2,0x9ac3,0x9ac4,0xccba, -0x9ac5,0x9ac6,0x9ac7,0xeba5,0x9ac8,0xeba7,0x9ac9,0x9aca,0x9acb,0xeba8,0x9acc,0x9acd,0x9ace,0xeba6,0x9acf,0x9ad0, -0x9ad1,0x9ad2,0x9ad3,0x9ad4,0x9ad5,0xeba9,0xebab,0xebaa,0x9ad6,0x9ad7,0x9ad8,0x9ad9,0x9ada,0xebac,0x9adb,0xcacf, -0xd8b5,0xc3f1,0x9adc,0xc3a5,0xc6f8,0xebad,0xc4ca,0x9add,0xebae,0xebaf,0xebb0,0xb7d5,0x9ade,0x9adf,0x9ae0,0xb7fa, -0x9ae1,0xebb1,0xc7e2,0x9ae2,0xebb3,0x9ae3,0xbaa4,0xd1f5,0xb0b1,0xebb2,0xebb4,0x9ae4,0x9ae5,0x9ae6,0xb5aa,0xc2c8, -0xc7e8,0x9ae7,0xebb5,0x9ae8,0xcbae,0xe3df,0x9ae9,0x9aea,0xd3c0,0x9aeb,0x9aec,0x9aed,0x9aee,0xd9db,0x9aef,0x9af0, -0xcda1,0xd6ad,0xc7f3,0x9af1,0x9af2,0x9af3,0xd9e0,0xbbe3,0x9af4,0xbaba,0xe3e2,0x9af5,0x9af6,0x9af7,0x9af8,0x9af9, -0xcfab,0x9afa,0x9afb,0x9afc,0xe3e0,0xc9c7,0x9afd,0xbab9,0x9afe,0x9b40,0x9b41,0xd1b4,0xe3e1,0xc8ea,0xb9af,0xbdad, -0xb3d8,0xcedb,0x9b42,0x9b43,0xccc0,0x9b44,0x9b45,0x9b46,0xe3e8,0xe3e9,0xcdf4,0x9b47,0x9b48,0x9b49,0x9b4a,0x9b4b, -0xccad,0x9b4c,0xbcb3,0x9b4d,0xe3ea,0x9b4e,0xe3eb,0x9b4f,0x9b50,0xd0da,0x9b51,0x9b52,0x9b53,0xc6fb,0xb7da,0x9b54, -0x9b55,0xc7df,0xd2ca,0xced6,0x9b56,0xe3e4,0xe3ec,0x9b57,0xc9f2,0xb3c1,0x9b58,0x9b59,0xe3e7,0x9b5a,0x9b5b,0xc6e3, -0xe3e5,0x9b5c,0x9b5d,0xedb3,0xe3e6,0x9b5e,0x9b5f,0x9b60,0x9b61,0xc9b3,0x9b62,0xc5e6,0x9b63,0x9b64,0x9b65,0xb9b5, -0x9b66,0xc3bb,0x9b67,0xe3e3,0xc5bd,0xc1a4,0xc2d9,0xb2d7,0x9b68,0xe3ed,0xbba6,0xc4ad,0x9b69,0xe3f0,0xbeda,0x9b6a, -0x9b6b,0xe3fb,0xe3f5,0xbad3,0x9b6c,0x9b6d,0x9b6e,0x9b6f,0xb7d0,0xd3cd,0x9b70,0xd6ce,0xd5d3,0xb9c1,0xd5b4,0xd1d8, -0x9b71,0x9b72,0x9b73,0x9b74,0xd0b9,0xc7f6,0x9b75,0x9b76,0x9b77,0xc8aa,0xb2b4,0x9b78,0xc3da,0x9b79,0x9b7a,0x9b7b, -0xe3ee,0x9b7c,0x9b7d,0xe3fc,0xe3ef,0xb7a8,0xe3f7,0xe3f4,0x9b7e,0x9b80,0x9b81,0xb7ba,0x9b82,0x9b83,0xc5a2,0x9b84, -0xe3f6,0xc5dd,0xb2a8,0xc6fc,0x9b85,0xc4e0,0x9b86,0x9b87,0xd7a2,0x9b88,0xc0e1,0xe3f9,0x9b89,0x9b8a,0xe3fa,0xe3fd, -0xcca9,0xe3f3,0x9b8b,0xd3be,0x9b8c,0xb1c3,0xedb4,0xe3f1,0xe3f2,0x9b8d,0xe3f8,0xd0ba,0xc6c3,0xd4f3,0xe3fe,0x9b8e, -0x9b8f,0xbde0,0x9b90,0x9b91,0xe4a7,0x9b92,0x9b93,0xe4a6,0x9b94,0x9b95,0x9b96,0xd1f3,0xe4a3,0x9b97,0xe4a9,0x9b98, -0x9b99,0x9b9a,0xc8f7,0x9b9b,0x9b9c,0x9b9d,0x9b9e,0xcfb4,0x9b9f,0xe4a8,0xe4ae,0xc2e5,0x9ba0,0x9ba1,0xb6b4,0x9ba2, -0x9ba3,0x9ba4,0x9ba5,0x9ba6,0x9ba7,0xbdf2,0x9ba8,0xe4a2,0x9ba9,0x9baa,0xbae9,0xe4aa,0x9bab,0x9bac,0xe4ac,0x9bad, -0x9bae,0xb6fd,0xd6de,0xe4b2,0x9baf,0xe4ad,0x9bb0,0x9bb1,0x9bb2,0xe4a1,0x9bb3,0xbbee,0xcddd,0xc7a2,0xc5c9,0x9bb4, -0x9bb5,0xc1f7,0x9bb6,0xe4a4,0x9bb7,0xc7b3,0xbdac,0xbdbd,0xe4a5,0x9bb8,0xd7c7,0xb2e2,0x9bb9,0xe4ab,0xbcc3,0xe4af, -0x9bba,0xbbeb,0xe4b0,0xc5a8,0xe4b1,0x9bbb,0x9bbc,0x9bbd,0x9bbe,0xd5e3,0xbfa3,0x9bbf,0xe4ba,0x9bc0,0xe4b7,0x9bc1, -0xe4bb,0x9bc2,0x9bc3,0xe4bd,0x9bc4,0x9bc5,0xc6d6,0x9bc6,0x9bc7,0xbac6,0xc0cb,0x9bc8,0x9bc9,0x9bca,0xb8a1,0xe4b4, -0x9bcb,0x9bcc,0x9bcd,0x9bce,0xd4a1,0x9bcf,0x9bd0,0xbaa3,0xbdfe,0x9bd1,0x9bd2,0x9bd3,0xe4bc,0x9bd4,0x9bd5,0x9bd6, -0x9bd7,0x9bd8,0xcdbf,0x9bd9,0x9bda,0xc4f9,0x9bdb,0x9bdc,0xcffb,0xc9e6,0x9bdd,0x9bde,0xd3bf,0x9bdf,0xcfd1,0x9be0, -0x9be1,0xe4b3,0x9be2,0xe4b8,0xe4b9,0xcce9,0x9be3,0x9be4,0x9be5,0x9be6,0x9be7,0xccce,0x9be8,0xc0d4,0xe4b5,0xc1b0, -0xe4b6,0xced0,0x9be9,0xbbc1,0xb5d3,0x9bea,0xc8f3,0xbda7,0xd5c7,0xc9ac,0xb8a2,0xe4ca,0x9beb,0x9bec,0xe4cc,0xd1c4, -0x9bed,0x9bee,0xd2ba,0x9bef,0x9bf0,0xbaad,0x9bf1,0x9bf2,0xbad4,0x9bf3,0x9bf4,0x9bf5,0x9bf6,0x9bf7,0x9bf8,0xe4c3, -0xb5ed,0x9bf9,0x9bfa,0x9bfb,0xd7cd,0xe4c0,0xcffd,0xe4bf,0x9bfc,0x9bfd,0x9bfe,0xc1dc,0xccca,0x9c40,0x9c41,0x9c42, -0x9c43,0xcae7,0x9c44,0x9c45,0x9c46,0x9c47,0xc4d7,0x9c48,0xccd4,0xe4c8,0x9c49,0x9c4a,0x9c4b,0xe4c7,0xe4c1,0x9c4c, -0xe4c4,0xb5ad,0x9c4d,0x9c4e,0xd3d9,0x9c4f,0xe4c6,0x9c50,0x9c51,0x9c52,0x9c53,0xd2f9,0xb4e3,0x9c54,0xbbb4,0x9c55, -0x9c56,0xc9ee,0x9c57,0xb4be,0x9c58,0x9c59,0x9c5a,0xbbec,0x9c5b,0xd1cd,0x9c5c,0xcced,0xedb5,0x9c5d,0x9c5e,0x9c5f, -0x9c60,0x9c61,0x9c62,0x9c63,0x9c64,0xc7e5,0x9c65,0x9c66,0x9c67,0x9c68,0xd4a8,0x9c69,0xe4cb,0xd7d5,0xe4c2,0x9c6a, -0xbda5,0xe4c5,0x9c6b,0x9c6c,0xd3e6,0x9c6d,0xe4c9,0xc9f8,0x9c6e,0x9c6f,0xe4be,0x9c70,0x9c71,0xd3e5,0x9c72,0x9c73, -0xc7fe,0xb6c9,0x9c74,0xd4fc,0xb2b3,0xe4d7,0x9c75,0x9c76,0x9c77,0xcec2,0x9c78,0xe4cd,0x9c79,0xcebc,0x9c7a,0xb8db, -0x9c7b,0x9c7c,0xe4d6,0x9c7d,0xbfca,0x9c7e,0x9c80,0x9c81,0xd3ce,0x9c82,0xc3ec,0x9c83,0x9c84,0x9c85,0x9c86,0x9c87, -0x9c88,0x9c89,0x9c8a,0xc5c8,0xe4d8,0x9c8b,0x9c8c,0x9c8d,0x9c8e,0x9c8f,0x9c90,0x9c91,0x9c92,0xcdc4,0xe4cf,0x9c93, -0x9c94,0x9c95,0x9c96,0xe4d4,0xe4d5,0x9c97,0xbafe,0x9c98,0xcfe6,0x9c99,0x9c9a,0xd5bf,0x9c9b,0x9c9c,0x9c9d,0xe4d2, -0x9c9e,0x9c9f,0x9ca0,0x9ca1,0x9ca2,0x9ca3,0x9ca4,0x9ca5,0x9ca6,0x9ca7,0x9ca8,0xe4d0,0x9ca9,0x9caa,0xe4ce,0x9cab, -0x9cac,0x9cad,0x9cae,0x9caf,0x9cb0,0x9cb1,0x9cb2,0x9cb3,0x9cb4,0x9cb5,0x9cb6,0x9cb7,0x9cb8,0x9cb9,0xcde5,0xcaaa, -0x9cba,0x9cbb,0x9cbc,0xc0a3,0x9cbd,0xbda6,0xe4d3,0x9cbe,0x9cbf,0xb8c8,0x9cc0,0x9cc1,0x9cc2,0x9cc3,0x9cc4,0xe4e7, -0xd4b4,0x9cc5,0x9cc6,0x9cc7,0x9cc8,0x9cc9,0x9cca,0x9ccb,0xe4db,0x9ccc,0x9ccd,0x9cce,0xc1ef,0x9ccf,0x9cd0,0xe4e9, -0x9cd1,0x9cd2,0xd2e7,0x9cd3,0x9cd4,0xe4df,0x9cd5,0xe4e0,0x9cd6,0x9cd7,0xcfaa,0x9cd8,0x9cd9,0x9cda,0x9cdb,0xcbdd, -0x9cdc,0xe4da,0xe4d1,0x9cdd,0xe4e5,0x9cde,0xc8dc,0xe4e3,0x9cdf,0x9ce0,0xc4e7,0xe4e2,0x9ce1,0xe4e1,0x9ce2,0x9ce3, -0x9ce4,0xb3fc,0xe4e8,0x9ce5,0x9ce6,0x9ce7,0x9ce8,0xb5e1,0x9ce9,0x9cea,0x9ceb,0xd7cc,0x9cec,0x9ced,0x9cee,0xe4e6, -0x9cef,0xbbac,0x9cf0,0xd7d2,0xcccf,0xebf8,0x9cf1,0xe4e4,0x9cf2,0x9cf3,0xb9f6,0x9cf4,0x9cf5,0x9cf6,0xd6cd,0xe4d9, -0xe4dc,0xc2fa,0xe4de,0x9cf7,0xc2cb,0xc0c4,0xc2d0,0x9cf8,0xb1f5,0xccb2,0x9cf9,0x9cfa,0x9cfb,0x9cfc,0x9cfd,0x9cfe, -0x9d40,0x9d41,0x9d42,0x9d43,0xb5ce,0x9d44,0x9d45,0x9d46,0x9d47,0xe4ef,0x9d48,0x9d49,0x9d4a,0x9d4b,0x9d4c,0x9d4d, -0x9d4e,0x9d4f,0xc6af,0x9d50,0x9d51,0x9d52,0xc6e1,0x9d53,0x9d54,0xe4f5,0x9d55,0x9d56,0x9d57,0x9d58,0x9d59,0xc2a9, -0x9d5a,0x9d5b,0x9d5c,0xc0ec,0xd1dd,0xe4ee,0x9d5d,0x9d5e,0x9d5f,0x9d60,0x9d61,0x9d62,0x9d63,0x9d64,0x9d65,0x9d66, -0xc4ae,0x9d67,0x9d68,0x9d69,0xe4ed,0x9d6a,0x9d6b,0x9d6c,0x9d6d,0xe4f6,0xe4f4,0xc2fe,0x9d6e,0xe4dd,0x9d6f,0xe4f0, -0x9d70,0xcafe,0x9d71,0xd5c4,0x9d72,0x9d73,0xe4f1,0x9d74,0x9d75,0x9d76,0x9d77,0x9d78,0x9d79,0x9d7a,0xd1fa,0x9d7b, -0x9d7c,0x9d7d,0x9d7e,0x9d80,0x9d81,0x9d82,0xe4eb,0xe4ec,0x9d83,0x9d84,0x9d85,0xe4f2,0x9d86,0xceab,0x9d87,0x9d88, -0x9d89,0x9d8a,0x9d8b,0x9d8c,0x9d8d,0x9d8e,0x9d8f,0x9d90,0xc5cb,0x9d91,0x9d92,0x9d93,0xc7b1,0x9d94,0xc2ba,0x9d95, -0x9d96,0x9d97,0xe4ea,0x9d98,0x9d99,0x9d9a,0xc1ca,0x9d9b,0x9d9c,0x9d9d,0x9d9e,0x9d9f,0x9da0,0xccb6,0xb3b1,0x9da1, -0x9da2,0x9da3,0xe4fb,0x9da4,0xe4f3,0x9da5,0x9da6,0x9da7,0xe4fa,0x9da8,0xe4fd,0x9da9,0xe4fc,0x9daa,0x9dab,0x9dac, -0x9dad,0x9dae,0x9daf,0x9db0,0xb3ce,0x9db1,0x9db2,0x9db3,0xb3ba,0xe4f7,0x9db4,0x9db5,0xe4f9,0xe4f8,0xc5ec,0x9db6, -0x9db7,0x9db8,0x9db9,0x9dba,0x9dbb,0x9dbc,0x9dbd,0x9dbe,0x9dbf,0x9dc0,0x9dc1,0x9dc2,0xc0bd,0x9dc3,0x9dc4,0x9dc5, -0x9dc6,0xd4e8,0x9dc7,0x9dc8,0x9dc9,0x9dca,0x9dcb,0xe5a2,0x9dcc,0x9dcd,0x9dce,0x9dcf,0x9dd0,0x9dd1,0x9dd2,0x9dd3, -0x9dd4,0x9dd5,0x9dd6,0xb0c4,0x9dd7,0x9dd8,0xe5a4,0x9dd9,0x9dda,0xe5a3,0x9ddb,0x9ddc,0x9ddd,0x9dde,0x9ddf,0x9de0, -0xbca4,0x9de1,0xe5a5,0x9de2,0x9de3,0x9de4,0x9de5,0x9de6,0x9de7,0xe5a1,0x9de8,0x9de9,0x9dea,0x9deb,0x9dec,0x9ded, -0x9dee,0xe4fe,0xb1f4,0x9def,0x9df0,0x9df1,0x9df2,0x9df3,0x9df4,0x9df5,0x9df6,0x9df7,0x9df8,0x9df9,0xe5a8,0x9dfa, -0xe5a9,0xe5a6,0x9dfb,0x9dfc,0x9dfd,0x9dfe,0x9e40,0x9e41,0x9e42,0x9e43,0x9e44,0x9e45,0x9e46,0x9e47,0xe5a7,0xe5aa, -0x9e48,0x9e49,0x9e4a,0x9e4b,0x9e4c,0x9e4d,0x9e4e,0x9e4f,0x9e50,0x9e51,0x9e52,0x9e53,0x9e54,0x9e55,0x9e56,0x9e57, -0x9e58,0x9e59,0x9e5a,0x9e5b,0x9e5c,0x9e5d,0x9e5e,0x9e5f,0x9e60,0x9e61,0x9e62,0x9e63,0x9e64,0x9e65,0x9e66,0x9e67, -0x9e68,0xc6d9,0x9e69,0x9e6a,0x9e6b,0x9e6c,0x9e6d,0x9e6e,0x9e6f,0x9e70,0xe5ab,0xe5ad,0x9e71,0x9e72,0x9e73,0x9e74, -0x9e75,0x9e76,0x9e77,0xe5ac,0x9e78,0x9e79,0x9e7a,0x9e7b,0x9e7c,0x9e7d,0x9e7e,0x9e80,0x9e81,0x9e82,0x9e83,0x9e84, -0x9e85,0x9e86,0x9e87,0x9e88,0x9e89,0xe5af,0x9e8a,0x9e8b,0x9e8c,0xe5ae,0x9e8d,0x9e8e,0x9e8f,0x9e90,0x9e91,0x9e92, -0x9e93,0x9e94,0x9e95,0x9e96,0x9e97,0x9e98,0x9e99,0x9e9a,0x9e9b,0x9e9c,0x9e9d,0x9e9e,0xb9e0,0x9e9f,0x9ea0,0xe5b0, -0x9ea1,0x9ea2,0x9ea3,0x9ea4,0x9ea5,0x9ea6,0x9ea7,0x9ea8,0x9ea9,0x9eaa,0x9eab,0x9eac,0x9ead,0x9eae,0xe5b1,0x9eaf, -0x9eb0,0x9eb1,0x9eb2,0x9eb3,0x9eb4,0x9eb5,0x9eb6,0x9eb7,0x9eb8,0x9eb9,0x9eba,0xbbf0,0xece1,0xc3f0,0x9ebb,0xb5c6, -0xbbd2,0x9ebc,0x9ebd,0x9ebe,0x9ebf,0xc1e9,0xd4ee,0x9ec0,0xbec4,0x9ec1,0x9ec2,0x9ec3,0xd7c6,0x9ec4,0xd4d6,0xb2d3, -0xecbe,0x9ec5,0x9ec6,0x9ec7,0x9ec8,0xeac1,0x9ec9,0x9eca,0x9ecb,0xc2af,0xb4b6,0x9ecc,0x9ecd,0x9ece,0xd1d7,0x9ecf, -0x9ed0,0x9ed1,0xb3b4,0x9ed2,0xc8b2,0xbfbb,0xecc0,0x9ed3,0x9ed4,0xd6cb,0x9ed5,0x9ed6,0xecbf,0xecc1,0x9ed7,0x9ed8, -0x9ed9,0x9eda,0x9edb,0x9edc,0x9edd,0x9ede,0x9edf,0x9ee0,0x9ee1,0x9ee2,0x9ee3,0xecc5,0xbee6,0xccbf,0xc5da,0xbebc, -0x9ee4,0xecc6,0x9ee5,0xb1fe,0x9ee6,0x9ee7,0x9ee8,0xecc4,0xd5a8,0xb5e3,0x9ee9,0xecc2,0xc1b6,0xb3e3,0x9eea,0x9eeb, -0xecc3,0xcbb8,0xc0c3,0xccfe,0x9eec,0x9eed,0x9eee,0x9eef,0xc1d2,0x9ef0,0xecc8,0x9ef1,0x9ef2,0x9ef3,0x9ef4,0x9ef5, -0x9ef6,0x9ef7,0x9ef8,0x9ef9,0x9efa,0x9efb,0x9efc,0x9efd,0xbae6,0xc0d3,0x9efe,0xd6f2,0x9f40,0x9f41,0x9f42,0xd1cc, -0x9f43,0x9f44,0x9f45,0x9f46,0xbfbe,0x9f47,0xb7b3,0xc9d5,0xecc7,0xbbe2,0x9f48,0xcccc,0xbdfd,0xc8c8,0x9f49,0xcfa9, -0x9f4a,0x9f4b,0x9f4c,0x9f4d,0x9f4e,0x9f4f,0x9f50,0xcde9,0x9f51,0xc5eb,0x9f52,0x9f53,0x9f54,0xb7e9,0x9f55,0x9f56, -0x9f57,0x9f58,0x9f59,0x9f5a,0x9f5b,0x9f5c,0x9f5d,0x9f5e,0x9f5f,0xd1c9,0xbab8,0x9f60,0x9f61,0x9f62,0x9f63,0x9f64, -0xecc9,0x9f65,0x9f66,0xecca,0x9f67,0xbbc0,0xeccb,0x9f68,0xece2,0xb1ba,0xb7d9,0x9f69,0x9f6a,0x9f6b,0x9f6c,0x9f6d, -0x9f6e,0x9f6f,0x9f70,0x9f71,0x9f72,0x9f73,0xbdb9,0x9f74,0x9f75,0x9f76,0x9f77,0x9f78,0x9f79,0x9f7a,0x9f7b,0xeccc, -0xd1e6,0xeccd,0x9f7c,0x9f7d,0x9f7e,0x9f80,0xc8bb,0x9f81,0x9f82,0x9f83,0x9f84,0x9f85,0x9f86,0x9f87,0x9f88,0x9f89, -0x9f8a,0x9f8b,0x9f8c,0x9f8d,0x9f8e,0xecd1,0x9f8f,0x9f90,0x9f91,0x9f92,0xecd3,0x9f93,0xbbcd,0x9f94,0xbce5,0x9f95, -0x9f96,0x9f97,0x9f98,0x9f99,0x9f9a,0x9f9b,0x9f9c,0x9f9d,0x9f9e,0x9f9f,0x9fa0,0x9fa1,0xeccf,0x9fa2,0xc9b7,0x9fa3, -0x9fa4,0x9fa5,0x9fa6,0x9fa7,0xc3ba,0x9fa8,0xece3,0xd5d5,0xecd0,0x9fa9,0x9faa,0x9fab,0x9fac,0x9fad,0xd6f3,0x9fae, -0x9faf,0x9fb0,0xecd2,0xecce,0x9fb1,0x9fb2,0x9fb3,0x9fb4,0xecd4,0x9fb5,0xecd5,0x9fb6,0x9fb7,0xc9bf,0x9fb8,0x9fb9, -0x9fba,0x9fbb,0x9fbc,0x9fbd,0xcfa8,0x9fbe,0x9fbf,0x9fc0,0x9fc1,0x9fc2,0xd0dc,0x9fc3,0x9fc4,0x9fc5,0x9fc6,0xd1ac, -0x9fc7,0x9fc8,0x9fc9,0x9fca,0xc8db,0x9fcb,0x9fcc,0x9fcd,0xecd6,0xcef5,0x9fce,0x9fcf,0x9fd0,0x9fd1,0x9fd2,0xcaec, -0xecda,0x9fd3,0x9fd4,0x9fd5,0x9fd6,0x9fd7,0x9fd8,0x9fd9,0xecd9,0x9fda,0x9fdb,0x9fdc,0xb0be,0x9fdd,0x9fde,0x9fdf, -0x9fe0,0x9fe1,0x9fe2,0xecd7,0x9fe3,0xecd8,0x9fe4,0x9fe5,0x9fe6,0xece4,0x9fe7,0x9fe8,0x9fe9,0x9fea,0x9feb,0x9fec, -0x9fed,0x9fee,0x9fef,0xc8bc,0x9ff0,0x9ff1,0x9ff2,0x9ff3,0x9ff4,0x9ff5,0x9ff6,0x9ff7,0x9ff8,0x9ff9,0xc1c7,0x9ffa, -0x9ffb,0x9ffc,0x9ffd,0x9ffe,0xecdc,0xd1e0,0xa040,0xa041,0xa042,0xa043,0xa044,0xa045,0xa046,0xa047,0xa048,0xa049, -0xecdb,0xa04a,0xa04b,0xa04c,0xa04d,0xd4ef,0xa04e,0xecdd,0xa04f,0xa050,0xa051,0xa052,0xa053,0xa054,0xdbc6,0xa055, -0xa056,0xa057,0xa058,0xa059,0xa05a,0xa05b,0xa05c,0xa05d,0xa05e,0xecde,0xa05f,0xa060,0xa061,0xa062,0xa063,0xa064, -0xa065,0xa066,0xa067,0xa068,0xa069,0xa06a,0xb1ac,0xa06b,0xa06c,0xa06d,0xa06e,0xa06f,0xa070,0xa071,0xa072,0xa073, -0xa074,0xa075,0xa076,0xa077,0xa078,0xa079,0xa07a,0xa07b,0xa07c,0xa07d,0xa07e,0xa080,0xa081,0xecdf,0xa082,0xa083, -0xa084,0xa085,0xa086,0xa087,0xa088,0xa089,0xa08a,0xa08b,0xece0,0xa08c,0xd7a6,0xa08d,0xc5c0,0xa08e,0xa08f,0xa090, -0xebbc,0xb0ae,0xa091,0xa092,0xa093,0xbef4,0xb8b8,0xd2af,0xb0d6,0xb5f9,0xa094,0xd8b3,0xa095,0xcbac,0xa096,0xe3dd, -0xa097,0xa098,0xa099,0xa09a,0xa09b,0xa09c,0xa09d,0xc6ac,0xb0e6,0xa09e,0xa09f,0xa0a0,0xc5c6,0xebb9,0xa0a1,0xa0a2, -0xa0a3,0xa0a4,0xebba,0xa0a5,0xa0a6,0xa0a7,0xebbb,0xa0a8,0xa0a9,0xd1c0,0xa0aa,0xc5a3,0xa0ab,0xeaf2,0xa0ac,0xc4b2, -0xa0ad,0xc4b5,0xc0ce,0xa0ae,0xa0af,0xa0b0,0xeaf3,0xc4c1,0xa0b1,0xceef,0xa0b2,0xa0b3,0xa0b4,0xa0b5,0xeaf0,0xeaf4, -0xa0b6,0xa0b7,0xc9fc,0xa0b8,0xa0b9,0xc7a3,0xa0ba,0xa0bb,0xa0bc,0xccd8,0xcefe,0xa0bd,0xa0be,0xa0bf,0xeaf5,0xeaf6, -0xcfac,0xc0e7,0xa0c0,0xa0c1,0xeaf7,0xa0c2,0xa0c3,0xa0c4,0xa0c5,0xa0c6,0xb6bf,0xeaf8,0xa0c7,0xeaf9,0xa0c8,0xeafa, -0xa0c9,0xa0ca,0xeafb,0xa0cb,0xa0cc,0xa0cd,0xa0ce,0xa0cf,0xa0d0,0xa0d1,0xa0d2,0xa0d3,0xa0d4,0xa0d5,0xa0d6,0xeaf1, -0xa0d7,0xa0d8,0xa0d9,0xa0da,0xa0db,0xa0dc,0xa0dd,0xa0de,0xa0df,0xa0e0,0xa0e1,0xa0e2,0xc8ae,0xe1eb,0xa0e3,0xb7b8, -0xe1ec,0xa0e4,0xa0e5,0xa0e6,0xe1ed,0xa0e7,0xd7b4,0xe1ee,0xe1ef,0xd3cc,0xa0e8,0xa0e9,0xa0ea,0xa0eb,0xa0ec,0xa0ed, -0xa0ee,0xe1f1,0xbff1,0xe1f0,0xb5d2,0xa0ef,0xa0f0,0xa0f1,0xb1b7,0xa0f2,0xa0f3,0xa0f4,0xa0f5,0xe1f3,0xe1f2,0xa0f6, -0xbafc,0xa0f7,0xe1f4,0xa0f8,0xa0f9,0xa0fa,0xa0fb,0xb9b7,0xa0fc,0xbed1,0xa0fd,0xa0fe,0xaa40,0xaa41,0xc4fc,0xaa42, -0xbadd,0xbdc6,0xaa43,0xaa44,0xaa45,0xaa46,0xaa47,0xaa48,0xe1f5,0xe1f7,0xaa49,0xaa4a,0xb6c0,0xcfc1,0xcaa8,0xe1f6, -0xd5f8,0xd3fc,0xe1f8,0xe1fc,0xe1f9,0xaa4b,0xaa4c,0xe1fa,0xc0ea,0xaa4d,0xe1fe,0xe2a1,0xc0c7,0xaa4e,0xaa4f,0xaa50, -0xaa51,0xe1fb,0xaa52,0xe1fd,0xaa53,0xaa54,0xaa55,0xaa56,0xaa57,0xaa58,0xe2a5,0xaa59,0xaa5a,0xaa5b,0xc1d4,0xaa5c, -0xaa5d,0xaa5e,0xaa5f,0xe2a3,0xaa60,0xe2a8,0xb2fe,0xe2a2,0xaa61,0xaa62,0xaa63,0xc3cd,0xb2c2,0xe2a7,0xe2a6,0xaa64, -0xaa65,0xe2a4,0xe2a9,0xaa66,0xaa67,0xe2ab,0xaa68,0xaa69,0xaa6a,0xd0c9,0xd6ed,0xc3a8,0xe2ac,0xaa6b,0xcfd7,0xaa6c, -0xaa6d,0xe2ae,0xaa6e,0xaa6f,0xbaef,0xaa70,0xaa71,0xe9e0,0xe2ad,0xe2aa,0xaa72,0xaa73,0xaa74,0xaa75,0xbbab,0xd4b3, -0xaa76,0xaa77,0xaa78,0xaa79,0xaa7a,0xaa7b,0xaa7c,0xaa7d,0xaa7e,0xaa80,0xaa81,0xaa82,0xaa83,0xe2b0,0xaa84,0xaa85, -0xe2af,0xaa86,0xe9e1,0xaa87,0xaa88,0xaa89,0xaa8a,0xe2b1,0xaa8b,0xaa8c,0xaa8d,0xaa8e,0xaa8f,0xaa90,0xaa91,0xaa92, -0xe2b2,0xaa93,0xaa94,0xaa95,0xaa96,0xaa97,0xaa98,0xaa99,0xaa9a,0xaa9b,0xaa9c,0xaa9d,0xe2b3,0xcca1,0xaa9e,0xe2b4, -0xaa9f,0xaaa0,0xab40,0xab41,0xab42,0xab43,0xab44,0xab45,0xab46,0xab47,0xab48,0xab49,0xab4a,0xab4b,0xe2b5,0xab4c, -0xab4d,0xab4e,0xab4f,0xab50,0xd0fe,0xab51,0xab52,0xc2ca,0xab53,0xd3f1,0xab54,0xcdf5,0xab55,0xab56,0xe7e0,0xab57, -0xab58,0xe7e1,0xab59,0xab5a,0xab5b,0xab5c,0xbec1,0xab5d,0xab5e,0xab5f,0xab60,0xc2ea,0xab61,0xab62,0xab63,0xe7e4, -0xab64,0xab65,0xe7e3,0xab66,0xab67,0xab68,0xab69,0xab6a,0xab6b,0xcde6,0xab6c,0xc3b5,0xab6d,0xab6e,0xe7e2,0xbbb7, -0xcfd6,0xab6f,0xc1e1,0xe7e9,0xab70,0xab71,0xab72,0xe7e8,0xab73,0xab74,0xe7f4,0xb2a3,0xab75,0xab76,0xab77,0xab78, -0xe7ea,0xab79,0xe7e6,0xab7a,0xab7b,0xab7c,0xab7d,0xab7e,0xe7ec,0xe7eb,0xc9ba,0xab80,0xab81,0xd5e4,0xab82,0xe7e5, -0xb7a9,0xe7e7,0xab83,0xab84,0xab85,0xab86,0xab87,0xab88,0xab89,0xe7ee,0xab8a,0xab8b,0xab8c,0xab8d,0xe7f3,0xab8e, -0xd6e9,0xab8f,0xab90,0xab91,0xab92,0xe7ed,0xab93,0xe7f2,0xab94,0xe7f1,0xab95,0xab96,0xab97,0xb0e0,0xab98,0xab99, -0xab9a,0xab9b,0xe7f5,0xab9c,0xab9d,0xab9e,0xab9f,0xaba0,0xac40,0xac41,0xac42,0xac43,0xac44,0xac45,0xac46,0xac47, -0xac48,0xac49,0xac4a,0xc7f2,0xac4b,0xc0c5,0xc0ed,0xac4c,0xac4d,0xc1f0,0xe7f0,0xac4e,0xac4f,0xac50,0xac51,0xe7f6, -0xcbf6,0xac52,0xac53,0xac54,0xac55,0xac56,0xac57,0xac58,0xac59,0xac5a,0xe8a2,0xe8a1,0xac5b,0xac5c,0xac5d,0xac5e, -0xac5f,0xac60,0xd7c1,0xac61,0xac62,0xe7fa,0xe7f9,0xac63,0xe7fb,0xac64,0xe7f7,0xac65,0xe7fe,0xac66,0xe7fd,0xac67, -0xe7fc,0xac68,0xac69,0xc1d5,0xc7d9,0xc5fd,0xc5c3,0xac6a,0xac6b,0xac6c,0xac6d,0xac6e,0xc7ed,0xac6f,0xac70,0xac71, -0xac72,0xe8a3,0xac73,0xac74,0xac75,0xac76,0xac77,0xac78,0xac79,0xac7a,0xac7b,0xac7c,0xac7d,0xac7e,0xac80,0xac81, -0xac82,0xac83,0xac84,0xac85,0xac86,0xe8a6,0xac87,0xe8a5,0xac88,0xe8a7,0xbaf7,0xe7f8,0xe8a4,0xac89,0xc8f0,0xc9aa, -0xac8a,0xac8b,0xac8c,0xac8d,0xac8e,0xac8f,0xac90,0xac91,0xac92,0xac93,0xac94,0xac95,0xac96,0xe8a9,0xac97,0xac98, -0xb9e5,0xac99,0xac9a,0xac9b,0xac9c,0xac9d,0xd1fe,0xe8a8,0xac9e,0xac9f,0xaca0,0xad40,0xad41,0xad42,0xe8aa,0xad43, -0xe8ad,0xe8ae,0xad44,0xc1a7,0xad45,0xad46,0xad47,0xe8af,0xad48,0xad49,0xad4a,0xe8b0,0xad4b,0xad4c,0xe8ac,0xad4d, -0xe8b4,0xad4e,0xad4f,0xad50,0xad51,0xad52,0xad53,0xad54,0xad55,0xad56,0xad57,0xad58,0xe8ab,0xad59,0xe8b1,0xad5a, -0xad5b,0xad5c,0xad5d,0xad5e,0xad5f,0xad60,0xad61,0xe8b5,0xe8b2,0xe8b3,0xad62,0xad63,0xad64,0xad65,0xad66,0xad67, -0xad68,0xad69,0xad6a,0xad6b,0xad6c,0xad6d,0xad6e,0xad6f,0xad70,0xad71,0xe8b7,0xad72,0xad73,0xad74,0xad75,0xad76, -0xad77,0xad78,0xad79,0xad7a,0xad7b,0xad7c,0xad7d,0xad7e,0xad80,0xad81,0xad82,0xad83,0xad84,0xad85,0xad86,0xad87, -0xad88,0xad89,0xe8b6,0xad8a,0xad8b,0xad8c,0xad8d,0xad8e,0xad8f,0xad90,0xad91,0xad92,0xb9cf,0xad93,0xf0ac,0xad94, -0xf0ad,0xad95,0xc6b0,0xb0ea,0xc8bf,0xad96,0xcddf,0xad97,0xad98,0xad99,0xad9a,0xad9b,0xad9c,0xad9d,0xcecd,0xeab1, -0xad9e,0xad9f,0xada0,0xae40,0xeab2,0xae41,0xc6bf,0xb4c9,0xae42,0xae43,0xae44,0xae45,0xae46,0xae47,0xae48,0xeab3, -0xae49,0xae4a,0xae4b,0xae4c,0xd5e7,0xae4d,0xae4e,0xae4f,0xae50,0xae51,0xae52,0xae53,0xae54,0xddf9,0xae55,0xeab4, -0xae56,0xeab5,0xae57,0xeab6,0xae58,0xae59,0xae5a,0xae5b,0xb8ca,0xdfb0,0xc9f5,0xae5c,0xccf0,0xae5d,0xae5e,0xc9fa, -0xae5f,0xae60,0xae61,0xae62,0xae63,0xc9fb,0xae64,0xae65,0xd3c3,0xcba6,0xae66,0xb8a6,0xf0ae,0xb1c2,0xae67,0xe5b8, -0xccef,0xd3c9,0xbcd7,0xc9ea,0xae68,0xb5e7,0xae69,0xc4d0,0xb5e9,0xae6a,0xeeae,0xbbad,0xae6b,0xae6c,0xe7de,0xae6d, -0xeeaf,0xae6e,0xae6f,0xae70,0xae71,0xb3a9,0xae72,0xae73,0xeeb2,0xae74,0xae75,0xeeb1,0xbde7,0xae76,0xeeb0,0xceb7, -0xae77,0xae78,0xae79,0xae7a,0xc5cf,0xae7b,0xae7c,0xae7d,0xae7e,0xc1f4,0xdbce,0xeeb3,0xd0f3,0xae80,0xae81,0xae82, -0xae83,0xae84,0xae85,0xae86,0xae87,0xc2d4,0xc6e8,0xae88,0xae89,0xae8a,0xb7ac,0xae8b,0xae8c,0xae8d,0xae8e,0xae8f, -0xae90,0xae91,0xeeb4,0xae92,0xb3eb,0xae93,0xae94,0xae95,0xbbfb,0xeeb5,0xae96,0xae97,0xae98,0xae99,0xae9a,0xe7dc, -0xae9b,0xae9c,0xae9d,0xeeb6,0xae9e,0xae9f,0xbdae,0xaea0,0xaf40,0xaf41,0xaf42,0xf1e2,0xaf43,0xaf44,0xaf45,0xcae8, -0xaf46,0xd2c9,0xf0da,0xaf47,0xf0db,0xaf48,0xf0dc,0xc1c6,0xaf49,0xb8ed,0xbece,0xaf4a,0xaf4b,0xf0de,0xaf4c,0xc5b1, -0xf0dd,0xd1f1,0xaf4d,0xf0e0,0xb0cc,0xbdea,0xaf4e,0xaf4f,0xaf50,0xaf51,0xaf52,0xd2df,0xf0df,0xaf53,0xb4af,0xb7e8, -0xf0e6,0xf0e5,0xc6a3,0xf0e1,0xf0e2,0xb4c3,0xaf54,0xaf55,0xf0e3,0xd5ee,0xaf56,0xaf57,0xccdb,0xbed2,0xbcb2,0xaf58, -0xaf59,0xaf5a,0xf0e8,0xf0e7,0xf0e4,0xb2a1,0xaf5b,0xd6a2,0xd3b8,0xbeb7,0xc8ac,0xaf5c,0xaf5d,0xf0ea,0xaf5e,0xaf5f, -0xaf60,0xaf61,0xd1f7,0xaf62,0xd6cc,0xbadb,0xf0e9,0xaf63,0xb6bb,0xaf64,0xaf65,0xcdb4,0xaf66,0xaf67,0xc6a6,0xaf68, -0xaf69,0xaf6a,0xc1a1,0xf0eb,0xf0ee,0xaf6b,0xf0ed,0xf0f0,0xf0ec,0xaf6c,0xbbbe,0xf0ef,0xaf6d,0xaf6e,0xaf6f,0xaf70, -0xccb5,0xf0f2,0xaf71,0xaf72,0xb3d5,0xaf73,0xaf74,0xaf75,0xaf76,0xb1d4,0xaf77,0xaf78,0xf0f3,0xaf79,0xaf7a,0xf0f4, -0xf0f6,0xb4e1,0xaf7b,0xf0f1,0xaf7c,0xf0f7,0xaf7d,0xaf7e,0xaf80,0xaf81,0xf0fa,0xaf82,0xf0f8,0xaf83,0xaf84,0xaf85, -0xf0f5,0xaf86,0xaf87,0xaf88,0xaf89,0xf0fd,0xaf8a,0xf0f9,0xf0fc,0xf0fe,0xaf8b,0xf1a1,0xaf8c,0xaf8d,0xaf8e,0xcec1, -0xf1a4,0xaf8f,0xf1a3,0xaf90,0xc1f6,0xf0fb,0xcadd,0xaf91,0xaf92,0xb4f1,0xb1f1,0xccb1,0xaf93,0xf1a6,0xaf94,0xaf95, -0xf1a7,0xaf96,0xaf97,0xf1ac,0xd5ce,0xf1a9,0xaf98,0xaf99,0xc8b3,0xaf9a,0xaf9b,0xaf9c,0xf1a2,0xaf9d,0xf1ab,0xf1a8, -0xf1a5,0xaf9e,0xaf9f,0xf1aa,0xafa0,0xb040,0xb041,0xb042,0xb043,0xb044,0xb045,0xb046,0xb0a9,0xf1ad,0xb047,0xb048, -0xb049,0xb04a,0xb04b,0xb04c,0xf1af,0xb04d,0xf1b1,0xb04e,0xb04f,0xb050,0xb051,0xb052,0xf1b0,0xb053,0xf1ae,0xb054, -0xb055,0xb056,0xb057,0xd1a2,0xb058,0xb059,0xb05a,0xb05b,0xb05c,0xb05d,0xb05e,0xf1b2,0xb05f,0xb060,0xb061,0xf1b3, -0xb062,0xb063,0xb064,0xb065,0xb066,0xb067,0xb068,0xb069,0xb9ef,0xb06a,0xb06b,0xb5c7,0xb06c,0xb0d7,0xb0d9,0xb06d, -0xb06e,0xb06f,0xd4ed,0xb070,0xb5c4,0xb071,0xbdd4,0xbbca,0xf0a7,0xb072,0xb073,0xb8de,0xb074,0xb075,0xf0a8,0xb076, -0xb077,0xb0a8,0xb078,0xf0a9,0xb079,0xb07a,0xcdee,0xb07b,0xb07c,0xf0aa,0xb07d,0xb07e,0xb080,0xb081,0xb082,0xb083, -0xb084,0xb085,0xb086,0xb087,0xf0ab,0xb088,0xb089,0xb08a,0xb08b,0xb08c,0xb08d,0xb08e,0xb08f,0xb090,0xc6a4,0xb091, -0xb092,0xd6e5,0xf1e4,0xb093,0xf1e5,0xb094,0xb095,0xb096,0xb097,0xb098,0xb099,0xb09a,0xb09b,0xb09c,0xb09d,0xc3f3, -0xb09e,0xb09f,0xd3db,0xb0a0,0xb140,0xd6d1,0xc5e8,0xb141,0xd3af,0xb142,0xd2e6,0xb143,0xb144,0xeec1,0xb0bb,0xd5b5, -0xd1ce,0xbce0,0xbad0,0xb145,0xbff8,0xb146,0xb8c7,0xb5c1,0xc5cc,0xb147,0xb148,0xcaa2,0xb149,0xb14a,0xb14b,0xc3cb, -0xb14c,0xb14d,0xb14e,0xb14f,0xb150,0xeec2,0xb151,0xb152,0xb153,0xb154,0xb155,0xb156,0xb157,0xb158,0xc4bf,0xb6a2, -0xb159,0xedec,0xc3a4,0xb15a,0xd6b1,0xb15b,0xb15c,0xb15d,0xcfe0,0xedef,0xb15e,0xb15f,0xc5ce,0xb160,0xb6dc,0xb161, -0xb162,0xcaa1,0xb163,0xb164,0xeded,0xb165,0xb166,0xedf0,0xedf1,0xc3bc,0xb167,0xbfb4,0xb168,0xedee,0xb169,0xb16a, -0xb16b,0xb16c,0xb16d,0xb16e,0xb16f,0xb170,0xb171,0xb172,0xb173,0xedf4,0xedf2,0xb174,0xb175,0xb176,0xb177,0xd5e6, -0xc3df,0xb178,0xedf3,0xb179,0xb17a,0xb17b,0xedf6,0xb17c,0xd5a3,0xd1a3,0xb17d,0xb17e,0xb180,0xedf5,0xb181,0xc3d0, -0xb182,0xb183,0xb184,0xb185,0xb186,0xedf7,0xbff4,0xbeec,0xedf8,0xb187,0xccf7,0xb188,0xd1db,0xb189,0xb18a,0xb18b, -0xd7c5,0xd5f6,0xb18c,0xedfc,0xb18d,0xb18e,0xb18f,0xedfb,0xb190,0xb191,0xb192,0xb193,0xb194,0xb195,0xb196,0xb197, -0xedf9,0xedfa,0xb198,0xb199,0xb19a,0xb19b,0xb19c,0xb19d,0xb19e,0xb19f,0xedfd,0xbea6,0xb1a0,0xb240,0xb241,0xb242, -0xb243,0xcbaf,0xeea1,0xb6bd,0xb244,0xeea2,0xc4c0,0xb245,0xedfe,0xb246,0xb247,0xbdde,0xb2c7,0xb248,0xb249,0xb24a, -0xb24b,0xb24c,0xb24d,0xb24e,0xb24f,0xb250,0xb251,0xb252,0xb253,0xb6c3,0xb254,0xb255,0xb256,0xeea5,0xd8ba,0xeea3, -0xeea6,0xb257,0xb258,0xb259,0xc3e9,0xb3f2,0xb25a,0xb25b,0xb25c,0xb25d,0xb25e,0xb25f,0xeea7,0xeea4,0xcfb9,0xb260, -0xb261,0xeea8,0xc2f7,0xb262,0xb263,0xb264,0xb265,0xb266,0xb267,0xb268,0xb269,0xb26a,0xb26b,0xb26c,0xb26d,0xeea9, -0xeeaa,0xb26e,0xdeab,0xb26f,0xb270,0xc6b3,0xb271,0xc7c6,0xb272,0xd6f5,0xb5c9,0xb273,0xcbb2,0xb274,0xb275,0xb276, -0xeeab,0xb277,0xb278,0xcdab,0xb279,0xeeac,0xb27a,0xb27b,0xb27c,0xb27d,0xb27e,0xd5b0,0xb280,0xeead,0xb281,0xf6c4, -0xb282,0xb283,0xb284,0xb285,0xb286,0xb287,0xb288,0xb289,0xb28a,0xb28b,0xb28c,0xb28d,0xb28e,0xdbc7,0xb28f,0xb290, -0xb291,0xb292,0xb293,0xb294,0xb295,0xb296,0xb297,0xb4a3,0xb298,0xb299,0xb29a,0xc3ac,0xf1e6,0xb29b,0xb29c,0xb29d, -0xb29e,0xb29f,0xcab8,0xd2d3,0xb2a0,0xd6aa,0xb340,0xeff2,0xb341,0xbed8,0xb342,0xbdc3,0xeff3,0xb6cc,0xb0ab,0xb343, -0xb344,0xb345,0xb346,0xcaaf,0xb347,0xb348,0xedb6,0xb349,0xedb7,0xb34a,0xb34b,0xb34c,0xb34d,0xcef9,0xb7af,0xbff3, -0xedb8,0xc2eb,0xc9b0,0xb34e,0xb34f,0xb350,0xb351,0xb352,0xb353,0xedb9,0xb354,0xb355,0xc6f6,0xbfb3,0xb356,0xb357, -0xb358,0xedbc,0xc5f8,0xb359,0xd1d0,0xb35a,0xd7a9,0xedba,0xedbb,0xb35b,0xd1e2,0xb35c,0xedbf,0xedc0,0xb35d,0xedc4, -0xb35e,0xb35f,0xb360,0xedc8,0xb361,0xedc6,0xedce,0xd5e8,0xb362,0xedc9,0xb363,0xb364,0xedc7,0xedbe,0xb365,0xb366, -0xc5e9,0xb367,0xb368,0xb369,0xc6c6,0xb36a,0xb36b,0xc9e9,0xd4d2,0xedc1,0xedc2,0xedc3,0xedc5,0xb36c,0xc0f9,0xb36d, -0xb4a1,0xb36e,0xb36f,0xb370,0xb371,0xb9e8,0xb372,0xedd0,0xb373,0xb374,0xb375,0xb376,0xedd1,0xb377,0xedca,0xb378, -0xedcf,0xb379,0xcef8,0xb37a,0xb37b,0xcbb6,0xedcc,0xedcd,0xb37c,0xb37d,0xb37e,0xb380,0xb381,0xcff5,0xb382,0xb383, -0xb384,0xb385,0xb386,0xb387,0xb388,0xb389,0xb38a,0xb38b,0xb38c,0xb38d,0xedd2,0xc1f2,0xd3b2,0xedcb,0xc8b7,0xb38e, -0xb38f,0xb390,0xb391,0xb392,0xb393,0xb394,0xb395,0xbcef,0xb396,0xb397,0xb398,0xb399,0xc5f0,0xb39a,0xb39b,0xb39c, -0xb39d,0xb39e,0xb39f,0xb3a0,0xb440,0xb441,0xb442,0xedd6,0xb443,0xb5ef,0xb444,0xb445,0xc2b5,0xb0ad,0xcbe9,0xb446, -0xb447,0xb1ae,0xb448,0xedd4,0xb449,0xb44a,0xb44b,0xcdeb,0xb5e2,0xb44c,0xedd5,0xedd3,0xedd7,0xb44d,0xb44e,0xb5fa, -0xb44f,0xedd8,0xb450,0xedd9,0xb451,0xeddc,0xb452,0xb1cc,0xb453,0xb454,0xb455,0xb456,0xb457,0xb458,0xb459,0xb45a, -0xc5f6,0xbcee,0xedda,0xccbc,0xb2ea,0xb45b,0xb45c,0xb45d,0xb45e,0xeddb,0xb45f,0xb460,0xb461,0xb462,0xc4eb,0xb463, -0xb464,0xb4c5,0xb465,0xb466,0xb467,0xb0f5,0xb468,0xb469,0xb46a,0xeddf,0xc0da,0xb4e8,0xb46b,0xb46c,0xb46d,0xb46e, -0xc5cd,0xb46f,0xb470,0xb471,0xeddd,0xbfc4,0xb472,0xb473,0xb474,0xedde,0xb475,0xb476,0xb477,0xb478,0xb479,0xb47a, -0xb47b,0xb47c,0xb47d,0xb47e,0xb480,0xb481,0xb482,0xb483,0xc4a5,0xb484,0xb485,0xb486,0xede0,0xb487,0xb488,0xb489, -0xb48a,0xb48b,0xede1,0xb48c,0xede3,0xb48d,0xb48e,0xc1d7,0xb48f,0xb490,0xbbc7,0xb491,0xb492,0xb493,0xb494,0xb495, -0xb496,0xbdb8,0xb497,0xb498,0xb499,0xede2,0xb49a,0xb49b,0xb49c,0xb49d,0xb49e,0xb49f,0xb4a0,0xb540,0xb541,0xb542, -0xb543,0xb544,0xb545,0xede4,0xb546,0xb547,0xb548,0xb549,0xb54a,0xb54b,0xb54c,0xb54d,0xb54e,0xb54f,0xede6,0xb550, -0xb551,0xb552,0xb553,0xb554,0xede5,0xb555,0xb556,0xb557,0xb558,0xb559,0xb55a,0xb55b,0xb55c,0xb55d,0xb55e,0xb55f, -0xb560,0xb561,0xb562,0xb563,0xede7,0xb564,0xb565,0xb566,0xb567,0xb568,0xcabe,0xecea,0xc0f1,0xb569,0xc9e7,0xb56a, -0xeceb,0xc6ee,0xb56b,0xb56c,0xb56d,0xb56e,0xecec,0xb56f,0xc6ed,0xeced,0xb570,0xb571,0xb572,0xb573,0xb574,0xb575, -0xb576,0xb577,0xb578,0xecf0,0xb579,0xb57a,0xd7e6,0xecf3,0xb57b,0xb57c,0xecf1,0xecee,0xecef,0xd7a3,0xc9f1,0xcbee, -0xecf4,0xb57d,0xecf2,0xb57e,0xb580,0xcfe9,0xb581,0xecf6,0xc6b1,0xb582,0xb583,0xb584,0xb585,0xbcc0,0xb586,0xecf5, -0xb587,0xb588,0xb589,0xb58a,0xb58b,0xb58c,0xb58d,0xb5bb,0xbbf6,0xb58e,0xecf7,0xb58f,0xb590,0xb591,0xb592,0xb593, -0xd9f7,0xbdfb,0xb594,0xb595,0xc2bb,0xecf8,0xb596,0xb597,0xb598,0xb599,0xecf9,0xb59a,0xb59b,0xb59c,0xb59d,0xb8a3, -0xb59e,0xb59f,0xb5a0,0xb640,0xb641,0xb642,0xb643,0xb644,0xb645,0xb646,0xecfa,0xb647,0xb648,0xb649,0xb64a,0xb64b, -0xb64c,0xb64d,0xb64e,0xb64f,0xb650,0xb651,0xb652,0xecfb,0xb653,0xb654,0xb655,0xb656,0xb657,0xb658,0xb659,0xb65a, -0xb65b,0xb65c,0xb65d,0xecfc,0xb65e,0xb65f,0xb660,0xb661,0xb662,0xd3ed,0xd8ae,0xc0eb,0xb663,0xc7dd,0xbacc,0xb664, -0xd0e3,0xcbbd,0xb665,0xcdba,0xb666,0xb667,0xb8d1,0xb668,0xb669,0xb1fc,0xb66a,0xc7ef,0xb66b,0xd6d6,0xb66c,0xb66d, -0xb66e,0xbfc6,0xc3eb,0xb66f,0xb670,0xeff5,0xb671,0xb672,0xc3d8,0xb673,0xb674,0xb675,0xb676,0xb677,0xb678,0xd7e2, -0xb679,0xb67a,0xb67b,0xeff7,0xb3d3,0xb67c,0xc7d8,0xd1ed,0xb67d,0xd6c8,0xb67e,0xeff8,0xb680,0xeff6,0xb681,0xbbfd, -0xb3c6,0xb682,0xb683,0xb684,0xb685,0xb686,0xb687,0xb688,0xbdd5,0xb689,0xb68a,0xd2c6,0xb68b,0xbbe0,0xb68c,0xb68d, -0xcfa1,0xb68e,0xeffc,0xeffb,0xb68f,0xb690,0xeff9,0xb691,0xb692,0xb693,0xb694,0xb3cc,0xb695,0xc9d4,0xcbb0,0xb696, -0xb697,0xb698,0xb699,0xb69a,0xeffe,0xb69b,0xb69c,0xb0de,0xb69d,0xb69e,0xd6c9,0xb69f,0xb6a0,0xb740,0xeffd,0xb741, -0xb3ed,0xb742,0xb743,0xf6d5,0xb744,0xb745,0xb746,0xb747,0xb748,0xb749,0xb74a,0xb74b,0xb74c,0xb74d,0xb74e,0xb74f, -0xb750,0xb751,0xb752,0xcec8,0xb753,0xb754,0xb755,0xf0a2,0xb756,0xf0a1,0xb757,0xb5be,0xbcda,0xbbfc,0xb758,0xb8e5, -0xb759,0xb75a,0xb75b,0xb75c,0xb75d,0xb75e,0xc4c2,0xb75f,0xb760,0xb761,0xb762,0xb763,0xb764,0xb765,0xb766,0xb767, -0xb768,0xf0a3,0xb769,0xb76a,0xb76b,0xb76c,0xb76d,0xcbeb,0xb76e,0xb76f,0xb770,0xb771,0xb772,0xb773,0xb774,0xb775, -0xb776,0xb777,0xb778,0xb779,0xb77a,0xb77b,0xb77c,0xb77d,0xb77e,0xb780,0xb781,0xb782,0xb783,0xb784,0xb785,0xb786, -0xf0a6,0xb787,0xb788,0xb789,0xd1a8,0xb78a,0xbebf,0xc7ee,0xf1b6,0xf1b7,0xbfd5,0xb78b,0xb78c,0xb78d,0xb78e,0xb4a9, -0xf1b8,0xcdbb,0xb78f,0xc7d4,0xd5ad,0xb790,0xf1b9,0xb791,0xf1ba,0xb792,0xb793,0xb794,0xb795,0xc7cf,0xb796,0xb797, -0xb798,0xd2a4,0xd6cf,0xb799,0xb79a,0xf1bb,0xbdd1,0xb4b0,0xbebd,0xb79b,0xb79c,0xb79d,0xb4dc,0xced1,0xb79e,0xbfdf, -0xf1bd,0xb79f,0xb7a0,0xb840,0xb841,0xbffa,0xf1bc,0xb842,0xf1bf,0xb843,0xb844,0xb845,0xf1be,0xf1c0,0xb846,0xb847, -0xb848,0xb849,0xb84a,0xf1c1,0xb84b,0xb84c,0xb84d,0xb84e,0xb84f,0xb850,0xb851,0xb852,0xb853,0xb854,0xb855,0xc1fe, -0xb856,0xb857,0xb858,0xb859,0xb85a,0xb85b,0xb85c,0xb85d,0xb85e,0xb85f,0xb860,0xc1a2,0xb861,0xb862,0xb863,0xb864, -0xb865,0xb866,0xb867,0xb868,0xb869,0xb86a,0xcafa,0xb86b,0xb86c,0xd5be,0xb86d,0xb86e,0xb86f,0xb870,0xbeba,0xbeb9, -0xd5c2,0xb871,0xb872,0xbfa2,0xb873,0xcdaf,0xf1b5,0xb874,0xb875,0xb876,0xb877,0xb878,0xb879,0xbddf,0xb87a,0xb6cb, -0xb87b,0xb87c,0xb87d,0xb87e,0xb880,0xb881,0xb882,0xb883,0xb884,0xd6f1,0xf3c3,0xb885,0xb886,0xf3c4,0xb887,0xb8cd, -0xb888,0xb889,0xb88a,0xf3c6,0xf3c7,0xb88b,0xb0ca,0xb88c,0xf3c5,0xb88d,0xf3c9,0xcbf1,0xb88e,0xb88f,0xb890,0xf3cb, -0xb891,0xd0a6,0xb892,0xb893,0xb1ca,0xf3c8,0xb894,0xb895,0xb896,0xf3cf,0xb897,0xb5d1,0xb898,0xb899,0xf3d7,0xb89a, -0xf3d2,0xb89b,0xb89c,0xb89d,0xf3d4,0xf3d3,0xb7fb,0xb89e,0xb1bf,0xb89f,0xf3ce,0xf3ca,0xb5da,0xb8a0,0xf3d0,0xb940, -0xb941,0xf3d1,0xb942,0xf3d5,0xb943,0xb944,0xb945,0xb946,0xf3cd,0xb947,0xbce3,0xb948,0xc1fd,0xb949,0xf3d6,0xb94a, -0xb94b,0xb94c,0xb94d,0xb94e,0xb94f,0xf3da,0xb950,0xf3cc,0xb951,0xb5c8,0xb952,0xbdee,0xf3dc,0xb953,0xb954,0xb7a4, -0xbff0,0xd6fe,0xcdb2,0xb955,0xb4f0,0xb956,0xb2df,0xb957,0xf3d8,0xb958,0xf3d9,0xc9b8,0xb959,0xf3dd,0xb95a,0xb95b, -0xf3de,0xb95c,0xf3e1,0xb95d,0xb95e,0xb95f,0xb960,0xb961,0xb962,0xb963,0xb964,0xb965,0xb966,0xb967,0xf3df,0xb968, -0xb969,0xf3e3,0xf3e2,0xb96a,0xb96b,0xf3db,0xb96c,0xbfea,0xb96d,0xb3ef,0xb96e,0xf3e0,0xb96f,0xb970,0xc7a9,0xb971, -0xbcf2,0xb972,0xb973,0xb974,0xb975,0xf3eb,0xb976,0xb977,0xb978,0xb979,0xb97a,0xb97b,0xb97c,0xb9bf,0xb97d,0xb97e, -0xf3e4,0xb980,0xb981,0xb982,0xb2ad,0xbbfe,0xb983,0xcbe3,0xb984,0xb985,0xb986,0xb987,0xf3ed,0xf3e9,0xb988,0xb989, -0xb98a,0xb9dc,0xf3ee,0xb98b,0xb98c,0xb98d,0xf3e5,0xf3e6,0xf3ea,0xc2e1,0xf3ec,0xf3ef,0xf3e8,0xbcfd,0xb98e,0xb98f, -0xb990,0xcfe4,0xb991,0xb992,0xf3f0,0xb993,0xb994,0xb995,0xf3e7,0xb996,0xb997,0xb998,0xb999,0xb99a,0xb99b,0xb99c, -0xb99d,0xf3f2,0xb99e,0xb99f,0xb9a0,0xba40,0xd7ad,0xc6aa,0xba41,0xba42,0xba43,0xba44,0xf3f3,0xba45,0xba46,0xba47, -0xba48,0xf3f1,0xba49,0xc2a8,0xba4a,0xba4b,0xba4c,0xba4d,0xba4e,0xb8dd,0xf3f5,0xba4f,0xba50,0xf3f4,0xba51,0xba52, -0xba53,0xb4db,0xba54,0xba55,0xba56,0xf3f6,0xf3f7,0xba57,0xba58,0xba59,0xf3f8,0xba5a,0xba5b,0xba5c,0xc0ba,0xba5d, -0xba5e,0xc0e9,0xba5f,0xba60,0xba61,0xba62,0xba63,0xc5f1,0xba64,0xba65,0xba66,0xba67,0xf3fb,0xba68,0xf3fa,0xba69, -0xba6a,0xba6b,0xba6c,0xba6d,0xba6e,0xba6f,0xba70,0xb4d8,0xba71,0xba72,0xba73,0xf3fe,0xf3f9,0xba74,0xba75,0xf3fc, -0xba76,0xba77,0xba78,0xba79,0xba7a,0xba7b,0xf3fd,0xba7c,0xba7d,0xba7e,0xba80,0xba81,0xba82,0xba83,0xba84,0xf4a1, -0xba85,0xba86,0xba87,0xba88,0xba89,0xba8a,0xf4a3,0xbbc9,0xba8b,0xba8c,0xf4a2,0xba8d,0xba8e,0xba8f,0xba90,0xba91, -0xba92,0xba93,0xba94,0xba95,0xba96,0xba97,0xba98,0xba99,0xf4a4,0xba9a,0xba9b,0xba9c,0xba9d,0xba9e,0xba9f,0xb2be, -0xf4a6,0xf4a5,0xbaa0,0xbb40,0xbb41,0xbb42,0xbb43,0xbb44,0xbb45,0xbb46,0xbb47,0xbb48,0xbb49,0xbcae,0xbb4a,0xbb4b, -0xbb4c,0xbb4d,0xbb4e,0xbb4f,0xbb50,0xbb51,0xbb52,0xbb53,0xbb54,0xbb55,0xbb56,0xbb57,0xbb58,0xbb59,0xbb5a,0xbb5b, -0xbb5c,0xbb5d,0xbb5e,0xbb5f,0xbb60,0xbb61,0xbb62,0xbb63,0xbb64,0xbb65,0xbb66,0xbb67,0xbb68,0xbb69,0xbb6a,0xbb6b, -0xbb6c,0xbb6d,0xbb6e,0xc3d7,0xd9e1,0xbb6f,0xbb70,0xbb71,0xbb72,0xbb73,0xbb74,0xc0e0,0xf4cc,0xd7d1,0xbb75,0xbb76, -0xbb77,0xbb78,0xbb79,0xbb7a,0xbb7b,0xbb7c,0xbb7d,0xbb7e,0xbb80,0xb7db,0xbb81,0xbb82,0xbb83,0xbb84,0xbb85,0xbb86, -0xbb87,0xf4ce,0xc1a3,0xbb88,0xbb89,0xc6c9,0xbb8a,0xb4d6,0xd5b3,0xbb8b,0xbb8c,0xbb8d,0xf4d0,0xf4cf,0xf4d1,0xcbda, -0xbb8e,0xbb8f,0xf4d2,0xbb90,0xd4c1,0xd6e0,0xbb91,0xbb92,0xbb93,0xbb94,0xb7e0,0xbb95,0xbb96,0xbb97,0xc1b8,0xbb98, -0xbb99,0xc1bb,0xf4d3,0xbeac,0xbb9a,0xbb9b,0xbb9c,0xbb9d,0xbb9e,0xb4e2,0xbb9f,0xbba0,0xf4d4,0xf4d5,0xbeab,0xbc40, -0xbc41,0xf4d6,0xbc42,0xbc43,0xbc44,0xf4db,0xbc45,0xf4d7,0xf4da,0xbc46,0xbafd,0xbc47,0xf4d8,0xf4d9,0xbc48,0xbc49, -0xbc4a,0xbc4b,0xbc4c,0xbc4d,0xbc4e,0xb8e2,0xccc7,0xf4dc,0xbc4f,0xb2da,0xbc50,0xbc51,0xc3d3,0xbc52,0xbc53,0xd4e3, -0xbfb7,0xbc54,0xbc55,0xbc56,0xbc57,0xbc58,0xbc59,0xbc5a,0xf4dd,0xbc5b,0xbc5c,0xbc5d,0xbc5e,0xbc5f,0xbc60,0xc5b4, -0xbc61,0xbc62,0xbc63,0xbc64,0xbc65,0xbc66,0xbc67,0xbc68,0xf4e9,0xbc69,0xbc6a,0xcfb5,0xbc6b,0xbc6c,0xbc6d,0xbc6e, -0xbc6f,0xbc70,0xbc71,0xbc72,0xbc73,0xbc74,0xbc75,0xbc76,0xbc77,0xbc78,0xcec9,0xbc79,0xbc7a,0xbc7b,0xbc7c,0xbc7d, -0xbc7e,0xbc80,0xbc81,0xbc82,0xbc83,0xbc84,0xbc85,0xbc86,0xbc87,0xbc88,0xbc89,0xbc8a,0xbc8b,0xbc8c,0xbc8d,0xbc8e, -0xcbd8,0xbc8f,0xcbf7,0xbc90,0xbc91,0xbc92,0xbc93,0xbdf4,0xbc94,0xbc95,0xbc96,0xd7cf,0xbc97,0xbc98,0xbc99,0xc0db, -0xbc9a,0xbc9b,0xbc9c,0xbc9d,0xbc9e,0xbc9f,0xbca0,0xbd40,0xbd41,0xbd42,0xbd43,0xbd44,0xbd45,0xbd46,0xbd47,0xbd48, -0xbd49,0xbd4a,0xbd4b,0xbd4c,0xbd4d,0xbd4e,0xbd4f,0xbd50,0xbd51,0xbd52,0xbd53,0xbd54,0xbd55,0xbd56,0xbd57,0xbd58, -0xbd59,0xbd5a,0xbd5b,0xbd5c,0xbd5d,0xbd5e,0xbd5f,0xbd60,0xbd61,0xbd62,0xbd63,0xbd64,0xbd65,0xbd66,0xbd67,0xbd68, -0xbd69,0xbd6a,0xbd6b,0xbd6c,0xbd6d,0xbd6e,0xbd6f,0xbd70,0xbd71,0xbd72,0xbd73,0xbd74,0xbd75,0xbd76,0xd0f5,0xbd77, -0xbd78,0xbd79,0xbd7a,0xbd7b,0xbd7c,0xbd7d,0xbd7e,0xf4ea,0xbd80,0xbd81,0xbd82,0xbd83,0xbd84,0xbd85,0xbd86,0xbd87, -0xbd88,0xbd89,0xbd8a,0xbd8b,0xbd8c,0xbd8d,0xbd8e,0xbd8f,0xbd90,0xbd91,0xbd92,0xbd93,0xbd94,0xbd95,0xbd96,0xbd97, -0xbd98,0xbd99,0xbd9a,0xbd9b,0xbd9c,0xbd9d,0xbd9e,0xbd9f,0xbda0,0xbe40,0xbe41,0xbe42,0xbe43,0xbe44,0xbe45,0xbe46, -0xbe47,0xbe48,0xbe49,0xbe4a,0xbe4b,0xbe4c,0xf4eb,0xbe4d,0xbe4e,0xbe4f,0xbe50,0xbe51,0xbe52,0xbe53,0xf4ec,0xbe54, -0xbe55,0xbe56,0xbe57,0xbe58,0xbe59,0xbe5a,0xbe5b,0xbe5c,0xbe5d,0xbe5e,0xbe5f,0xbe60,0xbe61,0xbe62,0xbe63,0xbe64, -0xbe65,0xbe66,0xbe67,0xbe68,0xbe69,0xbe6a,0xbe6b,0xbe6c,0xbe6d,0xbe6e,0xbe6f,0xbe70,0xbe71,0xbe72,0xbe73,0xbe74, -0xbe75,0xbe76,0xbe77,0xbe78,0xbe79,0xbe7a,0xbe7b,0xbe7c,0xbe7d,0xbe7e,0xbe80,0xbe81,0xbe82,0xbe83,0xbe84,0xbe85, -0xbe86,0xbe87,0xbe88,0xbe89,0xbe8a,0xbe8b,0xbe8c,0xbe8d,0xbe8e,0xbe8f,0xbe90,0xbe91,0xbe92,0xbe93,0xbe94,0xbe95, -0xbe96,0xbe97,0xbe98,0xbe99,0xbe9a,0xbe9b,0xbe9c,0xbe9d,0xbe9e,0xbe9f,0xbea0,0xbf40,0xbf41,0xbf42,0xbf43,0xbf44, -0xbf45,0xbf46,0xbf47,0xbf48,0xbf49,0xbf4a,0xbf4b,0xbf4c,0xbf4d,0xbf4e,0xbf4f,0xbf50,0xbf51,0xbf52,0xbf53,0xbf54, -0xbf55,0xbf56,0xbf57,0xbf58,0xbf59,0xbf5a,0xbf5b,0xbf5c,0xbf5d,0xbf5e,0xbf5f,0xbf60,0xbf61,0xbf62,0xbf63,0xbf64, -0xbf65,0xbf66,0xbf67,0xbf68,0xbf69,0xbf6a,0xbf6b,0xbf6c,0xbf6d,0xbf6e,0xbf6f,0xbf70,0xbf71,0xbf72,0xbf73,0xbf74, -0xbf75,0xbf76,0xbf77,0xbf78,0xbf79,0xbf7a,0xbf7b,0xbf7c,0xbf7d,0xbf7e,0xbf80,0xf7e3,0xbf81,0xbf82,0xbf83,0xbf84, -0xbf85,0xb7b1,0xbf86,0xbf87,0xbf88,0xbf89,0xbf8a,0xf4ed,0xbf8b,0xbf8c,0xbf8d,0xbf8e,0xbf8f,0xbf90,0xbf91,0xbf92, -0xbf93,0xbf94,0xbf95,0xbf96,0xbf97,0xbf98,0xbf99,0xbf9a,0xbf9b,0xbf9c,0xbf9d,0xbf9e,0xbf9f,0xbfa0,0xc040,0xc041, -0xc042,0xc043,0xc044,0xc045,0xc046,0xc047,0xc048,0xc049,0xc04a,0xc04b,0xc04c,0xc04d,0xc04e,0xc04f,0xc050,0xc051, -0xc052,0xc053,0xc054,0xc055,0xc056,0xc057,0xc058,0xc059,0xc05a,0xc05b,0xc05c,0xc05d,0xc05e,0xc05f,0xc060,0xc061, -0xc062,0xc063,0xd7eb,0xc064,0xc065,0xc066,0xc067,0xc068,0xc069,0xc06a,0xc06b,0xc06c,0xc06d,0xc06e,0xc06f,0xc070, -0xc071,0xc072,0xc073,0xc074,0xc075,0xc076,0xc077,0xc078,0xc079,0xc07a,0xc07b,0xf4ee,0xc07c,0xc07d,0xc07e,0xe6f9, -0xbec0,0xe6fa,0xbaec,0xe6fb,0xcfcb,0xe6fc,0xd4bc,0xbcb6,0xe6fd,0xe6fe,0xbccd,0xc8d2,0xceb3,0xe7a1,0xc080,0xb4bf, -0xe7a2,0xc9b4,0xb8d9,0xc4c9,0xc081,0xd7dd,0xc2da,0xb7d7,0xd6bd,0xcec6,0xb7c4,0xc082,0xc083,0xc5a6,0xe7a3,0xcfdf, -0xe7a4,0xe7a5,0xe7a6,0xc1b7,0xd7e9,0xc9f0,0xcfb8,0xd6af,0xd6d5,0xe7a7,0xb0ed,0xe7a8,0xe7a9,0xc9dc,0xd2ef,0xbead, -0xe7aa,0xb0f3,0xc8de,0xbde1,0xe7ab,0xc8c6,0xc084,0xe7ac,0xbbe6,0xb8f8,0xd1a4,0xe7ad,0xc2e7,0xbef8,0xbdca,0xcdb3, -0xe7ae,0xe7af,0xbeee,0xd0e5,0xc085,0xcbe7,0xccd0,0xbccc,0xe7b0,0xbca8,0xd0f7,0xe7b1,0xc086,0xd0f8,0xe7b2,0xe7b3, -0xb4c2,0xe7b4,0xe7b5,0xc9fe,0xceac,0xc3e0,0xe7b7,0xb1c1,0xb3f1,0xc087,0xe7b8,0xe7b9,0xd7db,0xd5c0,0xe7ba,0xc2cc, -0xd7ba,0xe7bb,0xe7bc,0xe7bd,0xbcea,0xc3e5,0xc0c2,0xe7be,0xe7bf,0xbca9,0xc088,0xe7c0,0xe7c1,0xe7b6,0xb6d0,0xe7c2, -0xc089,0xe7c3,0xe7c4,0xbbba,0xb5de,0xc2c6,0xb1e0,0xe7c5,0xd4b5,0xe7c6,0xb8bf,0xe7c8,0xe7c7,0xb7ec,0xc08a,0xe7c9, -0xb2f8,0xe7ca,0xe7cb,0xe7cc,0xe7cd,0xe7ce,0xe7cf,0xe7d0,0xd3a7,0xcbf5,0xe7d1,0xe7d2,0xe7d3,0xe7d4,0xc9c9,0xe7d5, -0xe7d6,0xe7d7,0xe7d8,0xe7d9,0xbdc9,0xe7da,0xf3be,0xc08b,0xb8d7,0xc08c,0xc8b1,0xc08d,0xc08e,0xc08f,0xc090,0xc091, -0xc092,0xc093,0xf3bf,0xc094,0xf3c0,0xf3c1,0xc095,0xc096,0xc097,0xc098,0xc099,0xc09a,0xc09b,0xc09c,0xc09d,0xc09e, -0xb9de,0xcdf8,0xc09f,0xc0a0,0xd8e8,0xbab1,0xc140,0xc2de,0xeeb7,0xc141,0xb7a3,0xc142,0xc143,0xc144,0xc145,0xeeb9, -0xc146,0xeeb8,0xb0d5,0xc147,0xc148,0xc149,0xc14a,0xc14b,0xeebb,0xd5d6,0xd7ef,0xc14c,0xc14d,0xc14e,0xd6c3,0xc14f, -0xc150,0xeebd,0xcaf0,0xc151,0xeebc,0xc152,0xc153,0xc154,0xc155,0xeebe,0xc156,0xc157,0xc158,0xc159,0xeec0,0xc15a, -0xc15b,0xeebf,0xc15c,0xc15d,0xc15e,0xc15f,0xc160,0xc161,0xc162,0xc163,0xd1f2,0xc164,0xc7bc,0xc165,0xc3c0,0xc166, -0xc167,0xc168,0xc169,0xc16a,0xb8e1,0xc16b,0xc16c,0xc16d,0xc16e,0xc16f,0xc1e7,0xc170,0xc171,0xf4c6,0xd0df,0xf4c7, -0xc172,0xcfdb,0xc173,0xc174,0xc8ba,0xc175,0xc176,0xf4c8,0xc177,0xc178,0xc179,0xc17a,0xc17b,0xc17c,0xc17d,0xf4c9, -0xf4ca,0xc17e,0xf4cb,0xc180,0xc181,0xc182,0xc183,0xc184,0xd9fa,0xb8fe,0xc185,0xc186,0xe5f1,0xd3f0,0xc187,0xf4e0, -0xc188,0xcecc,0xc189,0xc18a,0xc18b,0xb3e1,0xc18c,0xc18d,0xc18e,0xc18f,0xf1b4,0xc190,0xd2ee,0xc191,0xf4e1,0xc192, -0xc193,0xc194,0xc195,0xc196,0xcfe8,0xf4e2,0xc197,0xc198,0xc7cc,0xc199,0xc19a,0xc19b,0xc19c,0xc19d,0xc19e,0xb5d4, -0xb4e4,0xf4e4,0xc19f,0xc1a0,0xc240,0xf4e3,0xf4e5,0xc241,0xc242,0xf4e6,0xc243,0xc244,0xc245,0xc246,0xf4e7,0xc247, -0xbab2,0xb0bf,0xc248,0xf4e8,0xc249,0xc24a,0xc24b,0xc24c,0xc24d,0xc24e,0xc24f,0xb7ad,0xd2ed,0xc250,0xc251,0xc252, -0xd2ab,0xc0cf,0xc253,0xbfbc,0xeba3,0xd5df,0xeac8,0xc254,0xc255,0xc256,0xc257,0xf1f3,0xb6f8,0xcba3,0xc258,0xc259, -0xc4cd,0xc25a,0xf1e7,0xc25b,0xf1e8,0xb8fb,0xf1e9,0xbac4,0xd4c5,0xb0d2,0xc25c,0xc25d,0xf1ea,0xc25e,0xc25f,0xc260, -0xf1eb,0xc261,0xf1ec,0xc262,0xc263,0xf1ed,0xf1ee,0xf1ef,0xf1f1,0xf1f0,0xc5d5,0xc264,0xc265,0xc266,0xc267,0xc268, -0xc269,0xf1f2,0xc26a,0xb6fa,0xc26b,0xf1f4,0xd2ae,0xdec7,0xcbca,0xc26c,0xc26d,0xb3dc,0xc26e,0xb5a2,0xc26f,0xb9a2, -0xc270,0xc271,0xc4f4,0xf1f5,0xc272,0xc273,0xf1f6,0xc274,0xc275,0xc276,0xc1c4,0xc1fb,0xd6b0,0xf1f7,0xc277,0xc278, -0xc279,0xc27a,0xf1f8,0xc27b,0xc1aa,0xc27c,0xc27d,0xc27e,0xc6b8,0xc280,0xbedb,0xc281,0xc282,0xc283,0xc284,0xc285, -0xc286,0xc287,0xc288,0xc289,0xc28a,0xc28b,0xc28c,0xc28d,0xc28e,0xf1f9,0xb4cf,0xc28f,0xc290,0xc291,0xc292,0xc293, -0xc294,0xf1fa,0xc295,0xc296,0xc297,0xc298,0xc299,0xc29a,0xc29b,0xc29c,0xc29d,0xc29e,0xc29f,0xc2a0,0xc340,0xedb2, -0xedb1,0xc341,0xc342,0xcbe0,0xd2de,0xc343,0xcbc1,0xd5d8,0xc344,0xc8e2,0xc345,0xc0df,0xbca1,0xc346,0xc347,0xc348, -0xc349,0xc34a,0xc34b,0xebc1,0xc34c,0xc34d,0xd0a4,0xc34e,0xd6e2,0xc34f,0xb6c7,0xb8d8,0xebc0,0xb8ce,0xc350,0xebbf, -0xb3a6,0xb9c9,0xd6ab,0xc351,0xb7f4,0xb7ca,0xc352,0xc353,0xc354,0xbce7,0xb7be,0xebc6,0xc355,0xebc7,0xb0b9,0xbfcf, -0xc356,0xebc5,0xd3fd,0xc357,0xebc8,0xc358,0xc359,0xebc9,0xc35a,0xc35b,0xb7ce,0xc35c,0xebc2,0xebc4,0xc9f6,0xd6d7, -0xd5cd,0xd0b2,0xebcf,0xceb8,0xebd0,0xc35d,0xb5a8,0xc35e,0xc35f,0xc360,0xc361,0xc362,0xb1b3,0xebd2,0xcca5,0xc363, -0xc364,0xc365,0xc366,0xc367,0xc368,0xc369,0xc5d6,0xebd3,0xc36a,0xebd1,0xc5df,0xebce,0xcaa4,0xebd5,0xb0fb,0xc36b, -0xc36c,0xbafa,0xc36d,0xc36e,0xd8b7,0xf1e3,0xc36f,0xebca,0xebcb,0xebcc,0xebcd,0xebd6,0xe6c0,0xebd9,0xc370,0xbfe8, -0xd2c8,0xebd7,0xebdc,0xb8ec,0xebd8,0xc371,0xbdba,0xc372,0xd0d8,0xc373,0xb0b7,0xc374,0xebdd,0xc4dc,0xc375,0xc376, -0xc377,0xc378,0xd6ac,0xc379,0xc37a,0xc37b,0xb4e0,0xc37c,0xc37d,0xc2f6,0xbcb9,0xc37e,0xc380,0xebda,0xebdb,0xd4e0, -0xc6ea,0xc4d4,0xebdf,0xc5a7,0xd9f5,0xc381,0xb2b1,0xc382,0xebe4,0xc383,0xbdc5,0xc384,0xc385,0xc386,0xebe2,0xc387, -0xc388,0xc389,0xc38a,0xc38b,0xc38c,0xc38d,0xc38e,0xc38f,0xc390,0xc391,0xc392,0xc393,0xebe3,0xc394,0xc395,0xb8ac, -0xc396,0xcdd1,0xebe5,0xc397,0xc398,0xc399,0xebe1,0xc39a,0xc1b3,0xc39b,0xc39c,0xc39d,0xc39e,0xc39f,0xc6a2,0xc3a0, -0xc440,0xc441,0xc442,0xc443,0xc444,0xc445,0xccf3,0xc446,0xebe6,0xc447,0xc0b0,0xd2b8,0xebe7,0xc448,0xc449,0xc44a, -0xb8af,0xb8ad,0xc44b,0xebe8,0xc7bb,0xcdf3,0xc44c,0xc44d,0xc44e,0xebea,0xebeb,0xc44f,0xc450,0xc451,0xc452,0xc453, -0xebed,0xc454,0xc455,0xc456,0xc457,0xd0c8,0xc458,0xebf2,0xc459,0xebee,0xc45a,0xc45b,0xc45c,0xebf1,0xc8f9,0xc45d, -0xd1fc,0xebec,0xc45e,0xc45f,0xebe9,0xc460,0xc461,0xc462,0xc463,0xb8b9,0xcfd9,0xc4e5,0xebef,0xebf0,0xccda,0xcdc8, -0xb0f2,0xc464,0xebf6,0xc465,0xc466,0xc467,0xc468,0xc469,0xebf5,0xc46a,0xb2b2,0xc46b,0xc46c,0xc46d,0xc46e,0xb8e0, -0xc46f,0xebf7,0xc470,0xc471,0xc472,0xc473,0xc474,0xc475,0xb1ec,0xc476,0xc477,0xccc5,0xc4a4,0xcfa5,0xc478,0xc479, -0xc47a,0xc47b,0xc47c,0xebf9,0xc47d,0xc47e,0xeca2,0xc480,0xc5f2,0xc481,0xebfa,0xc482,0xc483,0xc484,0xc485,0xc486, -0xc487,0xc488,0xc489,0xc9c5,0xc48a,0xc48b,0xc48c,0xc48d,0xc48e,0xc48f,0xe2df,0xebfe,0xc490,0xc491,0xc492,0xc493, -0xcdce,0xeca1,0xb1db,0xd3b7,0xc494,0xc495,0xd2dc,0xc496,0xc497,0xc498,0xebfd,0xc499,0xebfb,0xc49a,0xc49b,0xc49c, -0xc49d,0xc49e,0xc49f,0xc4a0,0xc540,0xc541,0xc542,0xc543,0xc544,0xc545,0xc546,0xc547,0xc548,0xc549,0xc54a,0xc54b, -0xc54c,0xc54d,0xc54e,0xb3bc,0xc54f,0xc550,0xc551,0xeab0,0xc552,0xc553,0xd7d4,0xc554,0xf4ab,0xb3f4,0xc555,0xc556, -0xc557,0xc558,0xc559,0xd6c1,0xd6c2,0xc55a,0xc55b,0xc55c,0xc55d,0xc55e,0xc55f,0xd5e9,0xbeca,0xc560,0xf4a7,0xc561, -0xd2a8,0xf4a8,0xf4a9,0xc562,0xf4aa,0xbecb,0xd3df,0xc563,0xc564,0xc565,0xc566,0xc567,0xc9e0,0xc9e1,0xc568,0xc569, -0xf3c2,0xc56a,0xcae6,0xc56b,0xccf2,0xc56c,0xc56d,0xc56e,0xc56f,0xc570,0xc571,0xe2b6,0xcbb4,0xc572,0xcee8,0xd6db, -0xc573,0xf4ad,0xf4ae,0xf4af,0xc574,0xc575,0xc576,0xc577,0xf4b2,0xc578,0xbabd,0xf4b3,0xb0e3,0xf4b0,0xc579,0xf4b1, -0xbda2,0xb2d5,0xc57a,0xf4b6,0xf4b7,0xb6e6,0xb2b0,0xcfcf,0xf4b4,0xb4ac,0xc57b,0xf4b5,0xc57c,0xc57d,0xf4b8,0xc57e, -0xc580,0xc581,0xc582,0xc583,0xf4b9,0xc584,0xc585,0xcda7,0xc586,0xf4ba,0xc587,0xf4bb,0xc588,0xc589,0xc58a,0xf4bc, -0xc58b,0xc58c,0xc58d,0xc58e,0xc58f,0xc590,0xc591,0xc592,0xcbd2,0xc593,0xf4bd,0xc594,0xc595,0xc596,0xc597,0xf4be, -0xc598,0xc599,0xc59a,0xc59b,0xc59c,0xc59d,0xc59e,0xc59f,0xf4bf,0xc5a0,0xc640,0xc641,0xc642,0xc643,0xf4de,0xc1bc, -0xbce8,0xc644,0xc9ab,0xd1de,0xe5f5,0xc645,0xc646,0xc647,0xc648,0xdcb3,0xd2d5,0xc649,0xc64a,0xdcb4,0xb0ac,0xdcb5, -0xc64b,0xc64c,0xbdda,0xc64d,0xdcb9,0xc64e,0xc64f,0xc650,0xd8c2,0xc651,0xdcb7,0xd3f3,0xc652,0xc9d6,0xdcba,0xdcb6, -0xc653,0xdcbb,0xc3a2,0xc654,0xc655,0xc656,0xc657,0xdcbc,0xdcc5,0xdcbd,0xc658,0xc659,0xcedf,0xd6a5,0xc65a,0xdccf, -0xc65b,0xdccd,0xc65c,0xc65d,0xdcd2,0xbde6,0xc2ab,0xc65e,0xdcb8,0xdccb,0xdcce,0xdcbe,0xb7d2,0xb0c5,0xdcc7,0xd0be, -0xdcc1,0xbba8,0xc65f,0xb7bc,0xdccc,0xc660,0xc661,0xdcc6,0xdcbf,0xc7db,0xc662,0xc663,0xc664,0xd1bf,0xdcc0,0xc665, -0xc666,0xdcca,0xc667,0xc668,0xdcd0,0xc669,0xc66a,0xcead,0xdcc2,0xc66b,0xdcc3,0xdcc8,0xdcc9,0xb2d4,0xdcd1,0xcbd5, -0xc66c,0xd4b7,0xdcdb,0xdcdf,0xcca6,0xdce6,0xc66d,0xc3e7,0xdcdc,0xc66e,0xc66f,0xbfc1,0xdcd9,0xc670,0xb0fa,0xb9b6, -0xdce5,0xdcd3,0xc671,0xdcc4,0xdcd6,0xc8f4,0xbfe0,0xc672,0xc673,0xc674,0xc675,0xc9bb,0xc676,0xc677,0xc678,0xb1bd, -0xc679,0xd3a2,0xc67a,0xc67b,0xdcda,0xc67c,0xc67d,0xdcd5,0xc67e,0xc6bb,0xc680,0xdcde,0xc681,0xc682,0xc683,0xc684, -0xc685,0xd7c2,0xc3af,0xb7b6,0xc7d1,0xc3a9,0xdce2,0xdcd8,0xdceb,0xdcd4,0xc686,0xc687,0xdcdd,0xc688,0xbea5,0xdcd7, -0xc689,0xdce0,0xc68a,0xc68b,0xdce3,0xdce4,0xc68c,0xdcf8,0xc68d,0xc68e,0xdce1,0xdda2,0xdce7,0xc68f,0xc690,0xc691, -0xc692,0xc693,0xc694,0xc695,0xc696,0xc697,0xc698,0xbceb,0xb4c4,0xc699,0xc69a,0xc3a3,0xb2e7,0xdcfa,0xc69b,0xdcf2, -0xc69c,0xdcef,0xc69d,0xdcfc,0xdcee,0xd2f0,0xb2e8,0xc69e,0xc8d7,0xc8e3,0xdcfb,0xc69f,0xdced,0xc6a0,0xc740,0xc741, -0xdcf7,0xc742,0xc743,0xdcf5,0xc744,0xc745,0xbea3,0xdcf4,0xc746,0xb2dd,0xc747,0xc748,0xc749,0xc74a,0xc74b,0xdcf3, -0xbcf6,0xdce8,0xbbc4,0xc74c,0xc0f3,0xc74d,0xc74e,0xc74f,0xc750,0xc751,0xbcd4,0xdce9,0xdcea,0xc752,0xdcf1,0xdcf6, -0xdcf9,0xb5b4,0xc753,0xc8d9,0xbbe7,0xdcfe,0xdcfd,0xd3ab,0xdda1,0xdda3,0xdda5,0xd2f1,0xdda4,0xdda6,0xdda7,0xd2a9, -0xc754,0xc755,0xc756,0xc757,0xc758,0xc759,0xc75a,0xbac9,0xdda9,0xc75b,0xc75c,0xddb6,0xddb1,0xddb4,0xc75d,0xc75e, -0xc75f,0xc760,0xc761,0xc762,0xc763,0xddb0,0xc6ce,0xc764,0xc765,0xc0f2,0xc766,0xc767,0xc768,0xc769,0xc9af,0xc76a, -0xc76b,0xc76c,0xdcec,0xddae,0xc76d,0xc76e,0xc76f,0xc770,0xddb7,0xc771,0xc772,0xdcf0,0xddaf,0xc773,0xddb8,0xc774, -0xddac,0xc775,0xc776,0xc777,0xc778,0xc779,0xc77a,0xc77b,0xddb9,0xddb3,0xddad,0xc4aa,0xc77c,0xc77d,0xc77e,0xc780, -0xdda8,0xc0b3,0xc1ab,0xddaa,0xddab,0xc781,0xddb2,0xbbf1,0xddb5,0xd3a8,0xddba,0xc782,0xddbb,0xc3a7,0xc783,0xc784, -0xddd2,0xddbc,0xc785,0xc786,0xc787,0xddd1,0xc788,0xb9bd,0xc789,0xc78a,0xbed5,0xc78b,0xbefa,0xc78c,0xc78d,0xbaca, -0xc78e,0xc78f,0xc790,0xc791,0xddca,0xc792,0xddc5,0xc793,0xddbf,0xc794,0xc795,0xc796,0xb2cb,0xddc3,0xc797,0xddcb, -0xb2a4,0xddd5,0xc798,0xc799,0xc79a,0xddbe,0xc79b,0xc79c,0xc79d,0xc6d0,0xddd0,0xc79e,0xc79f,0xc7a0,0xc840,0xc841, -0xddd4,0xc1e2,0xb7c6,0xc842,0xc843,0xc844,0xc845,0xc846,0xddce,0xddcf,0xc847,0xc848,0xc849,0xddc4,0xc84a,0xc84b, -0xc84c,0xddbd,0xc84d,0xddcd,0xccd1,0xc84e,0xddc9,0xc84f,0xc850,0xc851,0xc852,0xddc2,0xc3c8,0xc6bc,0xceae,0xddcc, -0xc853,0xddc8,0xc854,0xc855,0xc856,0xc857,0xc858,0xc859,0xddc1,0xc85a,0xc85b,0xc85c,0xddc6,0xc2dc,0xc85d,0xc85e, -0xc85f,0xc860,0xc861,0xc862,0xd3a9,0xd3aa,0xddd3,0xcff4,0xc8f8,0xc863,0xc864,0xc865,0xc866,0xc867,0xc868,0xc869, -0xc86a,0xdde6,0xc86b,0xc86c,0xc86d,0xc86e,0xc86f,0xc870,0xddc7,0xc871,0xc872,0xc873,0xdde0,0xc2e4,0xc874,0xc875, -0xc876,0xc877,0xc878,0xc879,0xc87a,0xc87b,0xdde1,0xc87c,0xc87d,0xc87e,0xc880,0xc881,0xc882,0xc883,0xc884,0xc885, -0xc886,0xddd7,0xc887,0xc888,0xc889,0xc88a,0xc88b,0xd6f8,0xc88c,0xddd9,0xddd8,0xb8f0,0xddd6,0xc88d,0xc88e,0xc88f, -0xc890,0xc6cf,0xc891,0xb6ad,0xc892,0xc893,0xc894,0xc895,0xc896,0xdde2,0xc897,0xbaf9,0xd4e1,0xdde7,0xc898,0xc899, -0xc89a,0xb4d0,0xc89b,0xddda,0xc89c,0xbffb,0xdde3,0xc89d,0xdddf,0xc89e,0xdddd,0xc89f,0xc8a0,0xc940,0xc941,0xc942, -0xc943,0xc944,0xb5d9,0xc945,0xc946,0xc947,0xc948,0xdddb,0xdddc,0xddde,0xc949,0xbdaf,0xdde4,0xc94a,0xdde5,0xc94b, -0xc94c,0xc94d,0xc94e,0xc94f,0xc950,0xc951,0xc952,0xddf5,0xc953,0xc3c9,0xc954,0xc955,0xcbe2,0xc956,0xc957,0xc958, -0xc959,0xddf2,0xc95a,0xc95b,0xc95c,0xc95d,0xc95e,0xc95f,0xc960,0xc961,0xc962,0xc963,0xc964,0xc965,0xc966,0xd8e1, -0xc967,0xc968,0xc6d1,0xc969,0xddf4,0xc96a,0xc96b,0xc96c,0xd5f4,0xddf3,0xddf0,0xc96d,0xc96e,0xddec,0xc96f,0xddef, -0xc970,0xdde8,0xc971,0xc972,0xd0ee,0xc973,0xc974,0xc975,0xc976,0xc8d8,0xddee,0xc977,0xc978,0xdde9,0xc979,0xc97a, -0xddea,0xcbf2,0xc97b,0xdded,0xc97c,0xc97d,0xb1cd,0xc97e,0xc980,0xc981,0xc982,0xc983,0xc984,0xc0b6,0xc985,0xbcbb, -0xddf1,0xc986,0xc987,0xddf7,0xc988,0xddf6,0xddeb,0xc989,0xc98a,0xc98b,0xc98c,0xc98d,0xc5ee,0xc98e,0xc98f,0xc990, -0xddfb,0xc991,0xc992,0xc993,0xc994,0xc995,0xc996,0xc997,0xc998,0xc999,0xc99a,0xc99b,0xdea4,0xc99c,0xc99d,0xdea3, -0xc99e,0xc99f,0xc9a0,0xca40,0xca41,0xca42,0xca43,0xca44,0xca45,0xca46,0xca47,0xca48,0xddf8,0xca49,0xca4a,0xca4b, -0xca4c,0xc3ef,0xca4d,0xc2fb,0xca4e,0xca4f,0xca50,0xd5e1,0xca51,0xca52,0xceb5,0xca53,0xca54,0xca55,0xca56,0xddfd, -0xca57,0xb2cc,0xca58,0xca59,0xca5a,0xca5b,0xca5c,0xca5d,0xca5e,0xca5f,0xca60,0xc4e8,0xcadf,0xca61,0xca62,0xca63, -0xca64,0xca65,0xca66,0xca67,0xca68,0xca69,0xca6a,0xc7be,0xddfa,0xddfc,0xddfe,0xdea2,0xb0aa,0xb1ce,0xca6b,0xca6c, -0xca6d,0xca6e,0xca6f,0xdeac,0xca70,0xca71,0xca72,0xca73,0xdea6,0xbdb6,0xc8ef,0xca74,0xca75,0xca76,0xca77,0xca78, -0xca79,0xca7a,0xca7b,0xca7c,0xca7d,0xca7e,0xdea1,0xca80,0xca81,0xdea5,0xca82,0xca83,0xca84,0xca85,0xdea9,0xca86, -0xca87,0xca88,0xca89,0xca8a,0xdea8,0xca8b,0xca8c,0xca8d,0xdea7,0xca8e,0xca8f,0xca90,0xca91,0xca92,0xca93,0xca94, -0xca95,0xca96,0xdead,0xca97,0xd4cc,0xca98,0xca99,0xca9a,0xca9b,0xdeb3,0xdeaa,0xdeae,0xca9c,0xca9d,0xc0d9,0xca9e, -0xca9f,0xcaa0,0xcb40,0xcb41,0xb1a1,0xdeb6,0xcb42,0xdeb1,0xcb43,0xcb44,0xcb45,0xcb46,0xcb47,0xcb48,0xcb49,0xdeb2, -0xcb4a,0xcb4b,0xcb4c,0xcb4d,0xcb4e,0xcb4f,0xcb50,0xcb51,0xcb52,0xcb53,0xcb54,0xd1a6,0xdeb5,0xcb55,0xcb56,0xcb57, -0xcb58,0xcb59,0xcb5a,0xcb5b,0xdeaf,0xcb5c,0xcb5d,0xcb5e,0xdeb0,0xcb5f,0xd0bd,0xcb60,0xcb61,0xcb62,0xdeb4,0xcaed, -0xdeb9,0xcb63,0xcb64,0xcb65,0xcb66,0xcb67,0xcb68,0xdeb8,0xcb69,0xdeb7,0xcb6a,0xcb6b,0xcb6c,0xcb6d,0xcb6e,0xcb6f, -0xcb70,0xdebb,0xcb71,0xcb72,0xcb73,0xcb74,0xcb75,0xcb76,0xcb77,0xbde5,0xcb78,0xcb79,0xcb7a,0xcb7b,0xcb7c,0xb2d8, -0xc3ea,0xcb7d,0xcb7e,0xdeba,0xcb80,0xc5ba,0xcb81,0xcb82,0xcb83,0xcb84,0xcb85,0xcb86,0xdebc,0xcb87,0xcb88,0xcb89, -0xcb8a,0xcb8b,0xcb8c,0xcb8d,0xccd9,0xcb8e,0xcb8f,0xcb90,0xcb91,0xb7aa,0xcb92,0xcb93,0xcb94,0xcb95,0xcb96,0xcb97, -0xcb98,0xcb99,0xcb9a,0xcb9b,0xcb9c,0xcb9d,0xcb9e,0xcb9f,0xcba0,0xcc40,0xcc41,0xd4e5,0xcc42,0xcc43,0xcc44,0xdebd, -0xcc45,0xcc46,0xcc47,0xcc48,0xcc49,0xdebf,0xcc4a,0xcc4b,0xcc4c,0xcc4d,0xcc4e,0xcc4f,0xcc50,0xcc51,0xcc52,0xcc53, -0xcc54,0xc4a2,0xcc55,0xcc56,0xcc57,0xcc58,0xdec1,0xcc59,0xcc5a,0xcc5b,0xcc5c,0xcc5d,0xcc5e,0xcc5f,0xcc60,0xcc61, -0xcc62,0xcc63,0xcc64,0xcc65,0xcc66,0xcc67,0xcc68,0xdebe,0xcc69,0xdec0,0xcc6a,0xcc6b,0xcc6c,0xcc6d,0xcc6e,0xcc6f, -0xcc70,0xcc71,0xcc72,0xcc73,0xcc74,0xcc75,0xcc76,0xcc77,0xd5ba,0xcc78,0xcc79,0xcc7a,0xdec2,0xcc7b,0xcc7c,0xcc7d, -0xcc7e,0xcc80,0xcc81,0xcc82,0xcc83,0xcc84,0xcc85,0xcc86,0xcc87,0xcc88,0xcc89,0xcc8a,0xcc8b,0xf2ae,0xbba2,0xc2b2, -0xc5b0,0xc2c7,0xcc8c,0xcc8d,0xf2af,0xcc8e,0xcc8f,0xcc90,0xcc91,0xcc92,0xd0e9,0xcc93,0xcc94,0xcc95,0xd3dd,0xcc96, -0xcc97,0xcc98,0xebbd,0xcc99,0xcc9a,0xcc9b,0xcc9c,0xcc9d,0xcc9e,0xcc9f,0xcca0,0xb3e6,0xf2b0,0xcd40,0xf2b1,0xcd41, -0xcd42,0xcaad,0xcd43,0xcd44,0xcd45,0xcd46,0xcd47,0xcd48,0xcd49,0xbae7,0xf2b3,0xf2b5,0xf2b4,0xcbe4,0xcfba,0xf2b2, -0xcab4,0xd2cf,0xc2ec,0xcd4a,0xcd4b,0xcd4c,0xcd4d,0xcd4e,0xcd4f,0xcd50,0xcec3,0xf2b8,0xb0f6,0xf2b7,0xcd51,0xcd52, -0xcd53,0xcd54,0xcd55,0xf2be,0xcd56,0xb2cf,0xcd57,0xcd58,0xcd59,0xcd5a,0xcd5b,0xcd5c,0xd1c1,0xf2ba,0xcd5d,0xcd5e, -0xcd5f,0xcd60,0xcd61,0xf2bc,0xd4e9,0xcd62,0xcd63,0xf2bb,0xf2b6,0xf2bf,0xf2bd,0xcd64,0xf2b9,0xcd65,0xcd66,0xf2c7, -0xf2c4,0xf2c6,0xcd67,0xcd68,0xf2ca,0xf2c2,0xf2c0,0xcd69,0xcd6a,0xcd6b,0xf2c5,0xcd6c,0xcd6d,0xcd6e,0xcd6f,0xcd70, -0xd6fb,0xcd71,0xcd72,0xcd73,0xf2c1,0xcd74,0xc7f9,0xc9df,0xcd75,0xf2c8,0xb9c6,0xb5b0,0xcd76,0xcd77,0xf2c3,0xf2c9, -0xf2d0,0xf2d6,0xcd78,0xcd79,0xbbd7,0xcd7a,0xcd7b,0xcd7c,0xf2d5,0xcddc,0xcd7d,0xd6eb,0xcd7e,0xcd80,0xf2d2,0xf2d4, -0xcd81,0xcd82,0xcd83,0xcd84,0xb8f2,0xcd85,0xcd86,0xcd87,0xcd88,0xf2cb,0xcd89,0xcd8a,0xcd8b,0xf2ce,0xc2f9,0xcd8c, -0xd5dd,0xf2cc,0xf2cd,0xf2cf,0xf2d3,0xcd8d,0xcd8e,0xcd8f,0xf2d9,0xd3bc,0xcd90,0xcd91,0xcd92,0xcd93,0xb6ea,0xcd94, -0xcaf1,0xcd95,0xb7e4,0xf2d7,0xcd96,0xcd97,0xcd98,0xf2d8,0xf2da,0xf2dd,0xf2db,0xcd99,0xcd9a,0xf2dc,0xcd9b,0xcd9c, -0xcd9d,0xcd9e,0xd1d1,0xf2d1,0xcd9f,0xcdc9,0xcda0,0xcecf,0xd6a9,0xce40,0xf2e3,0xce41,0xc3db,0xce42,0xf2e0,0xce43, -0xce44,0xc0af,0xf2ec,0xf2de,0xce45,0xf2e1,0xce46,0xce47,0xce48,0xf2e8,0xce49,0xce4a,0xce4b,0xce4c,0xf2e2,0xce4d, -0xce4e,0xf2e7,0xce4f,0xce50,0xf2e6,0xce51,0xce52,0xf2e9,0xce53,0xce54,0xce55,0xf2df,0xce56,0xce57,0xf2e4,0xf2ea, -0xce58,0xce59,0xce5a,0xce5b,0xce5c,0xce5d,0xce5e,0xd3ac,0xf2e5,0xb2f5,0xce5f,0xce60,0xf2f2,0xce61,0xd0ab,0xce62, -0xce63,0xce64,0xce65,0xf2f5,0xce66,0xce67,0xce68,0xbbc8,0xce69,0xf2f9,0xce6a,0xce6b,0xce6c,0xce6d,0xce6e,0xce6f, -0xf2f0,0xce70,0xce71,0xf2f6,0xf2f8,0xf2fa,0xce72,0xce73,0xce74,0xce75,0xce76,0xce77,0xce78,0xce79,0xf2f3,0xce7a, -0xf2f1,0xce7b,0xce7c,0xce7d,0xbafb,0xce7e,0xb5fb,0xce80,0xce81,0xce82,0xce83,0xf2ef,0xf2f7,0xf2ed,0xf2ee,0xce84, -0xce85,0xce86,0xf2eb,0xf3a6,0xce87,0xf3a3,0xce88,0xce89,0xf3a2,0xce8a,0xce8b,0xf2f4,0xce8c,0xc8da,0xce8d,0xce8e, -0xce8f,0xce90,0xce91,0xf2fb,0xce92,0xce93,0xce94,0xf3a5,0xce95,0xce96,0xce97,0xce98,0xce99,0xce9a,0xce9b,0xc3f8, -0xce9c,0xce9d,0xce9e,0xce9f,0xcea0,0xcf40,0xcf41,0xcf42,0xf2fd,0xcf43,0xcf44,0xf3a7,0xf3a9,0xf3a4,0xcf45,0xf2fc, -0xcf46,0xcf47,0xcf48,0xf3ab,0xcf49,0xf3aa,0xcf4a,0xcf4b,0xcf4c,0xcf4d,0xc2dd,0xcf4e,0xcf4f,0xf3ae,0xcf50,0xcf51, -0xf3b0,0xcf52,0xcf53,0xcf54,0xcf55,0xcf56,0xf3a1,0xcf57,0xcf58,0xcf59,0xf3b1,0xf3ac,0xcf5a,0xcf5b,0xcf5c,0xcf5d, -0xcf5e,0xf3af,0xf2fe,0xf3ad,0xcf5f,0xcf60,0xcf61,0xcf62,0xcf63,0xcf64,0xcf65,0xf3b2,0xcf66,0xcf67,0xcf68,0xcf69, -0xf3b4,0xcf6a,0xcf6b,0xcf6c,0xcf6d,0xf3a8,0xcf6e,0xcf6f,0xcf70,0xcf71,0xf3b3,0xcf72,0xcf73,0xcf74,0xf3b5,0xcf75, -0xcf76,0xcf77,0xcf78,0xcf79,0xcf7a,0xcf7b,0xcf7c,0xcf7d,0xcf7e,0xd0b7,0xcf80,0xcf81,0xcf82,0xcf83,0xf3b8,0xcf84, -0xcf85,0xcf86,0xcf87,0xd9f9,0xcf88,0xcf89,0xcf8a,0xcf8b,0xcf8c,0xcf8d,0xf3b9,0xcf8e,0xcf8f,0xcf90,0xcf91,0xcf92, -0xcf93,0xcf94,0xcf95,0xf3b7,0xcf96,0xc8e4,0xf3b6,0xcf97,0xcf98,0xcf99,0xcf9a,0xf3ba,0xcf9b,0xcf9c,0xcf9d,0xcf9e, -0xcf9f,0xf3bb,0xb4c0,0xcfa0,0xd040,0xd041,0xd042,0xd043,0xd044,0xd045,0xd046,0xd047,0xd048,0xd049,0xd04a,0xd04b, -0xd04c,0xd04d,0xeec3,0xd04e,0xd04f,0xd050,0xd051,0xd052,0xd053,0xf3bc,0xd054,0xd055,0xf3bd,0xd056,0xd057,0xd058, -0xd1aa,0xd059,0xd05a,0xd05b,0xf4ac,0xd0c6,0xd05c,0xd05d,0xd05e,0xd05f,0xd060,0xd061,0xd0d0,0xd1dc,0xd062,0xd063, -0xd064,0xd065,0xd066,0xd067,0xcfce,0xd068,0xd069,0xbdd6,0xd06a,0xd1c3,0xd06b,0xd06c,0xd06d,0xd06e,0xd06f,0xd070, -0xd071,0xbae2,0xe1e9,0xd2c2,0xf1c2,0xb2b9,0xd072,0xd073,0xb1ed,0xf1c3,0xd074,0xc9c0,0xb3c4,0xd075,0xd9f2,0xd076, -0xcba5,0xd077,0xf1c4,0xd078,0xd079,0xd07a,0xd07b,0xd6d4,0xd07c,0xd07d,0xd07e,0xd080,0xd081,0xf1c5,0xf4c0,0xf1c6, -0xd082,0xd4ac,0xf1c7,0xd083,0xb0c0,0xf4c1,0xd084,0xd085,0xf4c2,0xd086,0xd087,0xb4fc,0xd088,0xc5db,0xd089,0xd08a, -0xd08b,0xd08c,0xccbb,0xd08d,0xd08e,0xd08f,0xd0e4,0xd090,0xd091,0xd092,0xd093,0xd094,0xcde0,0xd095,0xd096,0xd097, -0xd098,0xd099,0xf1c8,0xd09a,0xd9f3,0xd09b,0xd09c,0xd09d,0xd09e,0xd09f,0xd0a0,0xb1bb,0xd140,0xcfae,0xd141,0xd142, -0xd143,0xb8a4,0xd144,0xd145,0xd146,0xd147,0xd148,0xf1ca,0xd149,0xd14a,0xd14b,0xd14c,0xf1cb,0xd14d,0xd14e,0xd14f, -0xd150,0xb2c3,0xc1d1,0xd151,0xd152,0xd7b0,0xf1c9,0xd153,0xd154,0xf1cc,0xd155,0xd156,0xd157,0xd158,0xf1ce,0xd159, -0xd15a,0xd15b,0xd9f6,0xd15c,0xd2e1,0xd4a3,0xd15d,0xd15e,0xf4c3,0xc8b9,0xd15f,0xd160,0xd161,0xd162,0xd163,0xf4c4, -0xd164,0xd165,0xf1cd,0xf1cf,0xbfe3,0xf1d0,0xd166,0xd167,0xf1d4,0xd168,0xd169,0xd16a,0xd16b,0xd16c,0xd16d,0xd16e, -0xf1d6,0xf1d1,0xd16f,0xc9d1,0xc5e1,0xd170,0xd171,0xd172,0xc2e3,0xb9fc,0xd173,0xd174,0xf1d3,0xd175,0xf1d5,0xd176, -0xd177,0xd178,0xb9d3,0xd179,0xd17a,0xd17b,0xd17c,0xd17d,0xd17e,0xd180,0xf1db,0xd181,0xd182,0xd183,0xd184,0xd185, -0xbad6,0xd186,0xb0fd,0xf1d9,0xd187,0xd188,0xd189,0xd18a,0xd18b,0xf1d8,0xf1d2,0xf1da,0xd18c,0xd18d,0xd18e,0xd18f, -0xd190,0xf1d7,0xd191,0xd192,0xd193,0xc8ec,0xd194,0xd195,0xd196,0xd197,0xcdca,0xf1dd,0xd198,0xd199,0xd19a,0xd19b, -0xe5bd,0xd19c,0xd19d,0xd19e,0xf1dc,0xd19f,0xf1de,0xd1a0,0xd240,0xd241,0xd242,0xd243,0xd244,0xd245,0xd246,0xd247, -0xd248,0xf1df,0xd249,0xd24a,0xcfe5,0xd24b,0xd24c,0xd24d,0xd24e,0xd24f,0xd250,0xd251,0xd252,0xd253,0xd254,0xd255, -0xd256,0xd257,0xd258,0xd259,0xd25a,0xd25b,0xd25c,0xd25d,0xd25e,0xd25f,0xd260,0xd261,0xd262,0xd263,0xf4c5,0xbdf3, -0xd264,0xd265,0xd266,0xd267,0xd268,0xd269,0xf1e0,0xd26a,0xd26b,0xd26c,0xd26d,0xd26e,0xd26f,0xd270,0xd271,0xd272, -0xd273,0xd274,0xd275,0xd276,0xd277,0xd278,0xd279,0xd27a,0xd27b,0xd27c,0xd27d,0xf1e1,0xd27e,0xd280,0xd281,0xcef7, -0xd282,0xd2aa,0xd283,0xf1fb,0xd284,0xd285,0xb8b2,0xd286,0xd287,0xd288,0xd289,0xd28a,0xd28b,0xd28c,0xd28d,0xd28e, -0xd28f,0xd290,0xd291,0xd292,0xd293,0xd294,0xd295,0xd296,0xd297,0xd298,0xd299,0xd29a,0xd29b,0xd29c,0xd29d,0xd29e, -0xd29f,0xd2a0,0xd340,0xd341,0xd342,0xd343,0xd344,0xd345,0xd346,0xd347,0xd348,0xd349,0xd34a,0xd34b,0xd34c,0xd34d, -0xd34e,0xd34f,0xd350,0xd351,0xd352,0xd353,0xd354,0xd355,0xd356,0xd357,0xd358,0xd359,0xd35a,0xd35b,0xd35c,0xd35d, -0xd35e,0xbcfb,0xb9db,0xd35f,0xb9e6,0xc3d9,0xcad3,0xeae8,0xc0c0,0xbef5,0xeae9,0xeaea,0xeaeb,0xd360,0xeaec,0xeaed, -0xeaee,0xeaef,0xbdc7,0xd361,0xd362,0xd363,0xf5fb,0xd364,0xd365,0xd366,0xf5fd,0xd367,0xf5fe,0xd368,0xf5fc,0xd369, -0xd36a,0xd36b,0xd36c,0xbde2,0xd36d,0xf6a1,0xb4a5,0xd36e,0xd36f,0xd370,0xd371,0xf6a2,0xd372,0xd373,0xd374,0xf6a3, -0xd375,0xd376,0xd377,0xecb2,0xd378,0xd379,0xd37a,0xd37b,0xd37c,0xd37d,0xd37e,0xd380,0xd381,0xd382,0xd383,0xd384, -0xd1d4,0xd385,0xd386,0xd387,0xd388,0xd389,0xd38a,0xd9ea,0xd38b,0xd38c,0xd38d,0xd38e,0xd38f,0xd390,0xd391,0xd392, -0xd393,0xd394,0xd395,0xd396,0xd397,0xd398,0xd399,0xd39a,0xd39b,0xd39c,0xd39d,0xd39e,0xd39f,0xd3a0,0xd440,0xd441, -0xd442,0xd443,0xd444,0xd445,0xd446,0xd447,0xd448,0xd449,0xd44a,0xd44b,0xd44c,0xd44d,0xd44e,0xd44f,0xd450,0xd451, -0xd452,0xd453,0xd454,0xd455,0xd456,0xd457,0xd458,0xd459,0xd45a,0xd45b,0xd45c,0xd45d,0xd45e,0xd45f,0xf6a4,0xd460, -0xd461,0xd462,0xd463,0xd464,0xd465,0xd466,0xd467,0xd468,0xeeba,0xd469,0xd46a,0xd46b,0xd46c,0xd46d,0xd46e,0xd46f, -0xd470,0xd471,0xd472,0xd473,0xd474,0xd475,0xd476,0xd477,0xd478,0xd479,0xd47a,0xd47b,0xd47c,0xd47d,0xd47e,0xd480, -0xd481,0xd482,0xd483,0xd484,0xd485,0xd486,0xd487,0xd488,0xd489,0xd48a,0xd48b,0xd48c,0xd48d,0xd48e,0xd48f,0xd490, -0xd491,0xd492,0xd493,0xd494,0xd495,0xd496,0xd497,0xd498,0xd499,0xd5b2,0xd49a,0xd49b,0xd49c,0xd49d,0xd49e,0xd49f, -0xd4a0,0xd540,0xd541,0xd542,0xd543,0xd544,0xd545,0xd546,0xd547,0xd3fe,0xccdc,0xd548,0xd549,0xd54a,0xd54b,0xd54c, -0xd54d,0xd54e,0xd54f,0xcac4,0xd550,0xd551,0xd552,0xd553,0xd554,0xd555,0xd556,0xd557,0xd558,0xd559,0xd55a,0xd55b, -0xd55c,0xd55d,0xd55e,0xd55f,0xd560,0xd561,0xd562,0xd563,0xd564,0xd565,0xd566,0xd567,0xd568,0xd569,0xd56a,0xd56b, -0xd56c,0xd56d,0xd56e,0xd56f,0xd570,0xd571,0xd572,0xd573,0xd574,0xd575,0xd576,0xd577,0xd578,0xd579,0xd57a,0xd57b, -0xd57c,0xd57d,0xd57e,0xd580,0xd581,0xd582,0xd583,0xd584,0xd585,0xd586,0xd587,0xd588,0xd589,0xd58a,0xd58b,0xd58c, -0xd58d,0xd58e,0xd58f,0xd590,0xd591,0xd592,0xd593,0xd594,0xd595,0xd596,0xd597,0xd598,0xd599,0xd59a,0xd59b,0xd59c, -0xd59d,0xd59e,0xd59f,0xd5a0,0xd640,0xd641,0xd642,0xd643,0xd644,0xd645,0xd646,0xd647,0xd648,0xd649,0xd64a,0xd64b, -0xd64c,0xd64d,0xd64e,0xd64f,0xd650,0xd651,0xd652,0xd653,0xd654,0xd655,0xd656,0xd657,0xd658,0xd659,0xd65a,0xd65b, -0xd65c,0xd65d,0xd65e,0xd65f,0xd660,0xd661,0xd662,0xe5c0,0xd663,0xd664,0xd665,0xd666,0xd667,0xd668,0xd669,0xd66a, -0xd66b,0xd66c,0xd66d,0xd66e,0xd66f,0xd670,0xd671,0xd672,0xd673,0xd674,0xd675,0xd676,0xd677,0xd678,0xd679,0xd67a, -0xd67b,0xd67c,0xd67d,0xd67e,0xd680,0xd681,0xf6a5,0xd682,0xd683,0xd684,0xd685,0xd686,0xd687,0xd688,0xd689,0xd68a, -0xd68b,0xd68c,0xd68d,0xd68e,0xd68f,0xd690,0xd691,0xd692,0xd693,0xd694,0xd695,0xd696,0xd697,0xd698,0xd699,0xd69a, -0xd69b,0xd69c,0xd69d,0xd69e,0xd69f,0xd6a0,0xd740,0xd741,0xd742,0xd743,0xd744,0xd745,0xd746,0xd747,0xd748,0xd749, -0xd74a,0xd74b,0xd74c,0xd74d,0xd74e,0xd74f,0xd750,0xd751,0xd752,0xd753,0xd754,0xd755,0xd756,0xd757,0xd758,0xd759, -0xd75a,0xd75b,0xd75c,0xd75d,0xd75e,0xd75f,0xbeaf,0xd760,0xd761,0xd762,0xd763,0xd764,0xc6a9,0xd765,0xd766,0xd767, -0xd768,0xd769,0xd76a,0xd76b,0xd76c,0xd76d,0xd76e,0xd76f,0xd770,0xd771,0xd772,0xd773,0xd774,0xd775,0xd776,0xd777, -0xd778,0xd779,0xd77a,0xd77b,0xd77c,0xd77d,0xd77e,0xd780,0xd781,0xd782,0xd783,0xd784,0xd785,0xd786,0xd787,0xd788, -0xd789,0xd78a,0xd78b,0xd78c,0xd78d,0xd78e,0xd78f,0xd790,0xd791,0xd792,0xd793,0xd794,0xd795,0xd796,0xd797,0xd798, -0xdaa5,0xbcc6,0xb6a9,0xb8bc,0xc8cf,0xbca5,0xdaa6,0xdaa7,0xccd6,0xc8c3,0xdaa8,0xc6fd,0xd799,0xd1b5,0xd2e9,0xd1b6, -0xbcc7,0xd79a,0xbdb2,0xbbe4,0xdaa9,0xdaaa,0xd1c8,0xdaab,0xd0ed,0xb6ef,0xc2db,0xd79b,0xcbcf,0xb7ed,0xc9e8,0xb7c3, -0xbef7,0xd6a4,0xdaac,0xdaad,0xc6c0,0xd7e7,0xcab6,0xd79c,0xd5a9,0xcbdf,0xd5ef,0xdaae,0xd6df,0xb4ca,0xdab0,0xdaaf, -0xd79d,0xd2eb,0xdab1,0xdab2,0xdab3,0xcad4,0xdab4,0xcaab,0xdab5,0xdab6,0xb3cf,0xd6ef,0xdab7,0xbbb0,0xb5ae,0xdab8, -0xdab9,0xb9ee,0xd1af,0xd2e8,0xdaba,0xb8c3,0xcfea,0xb2ef,0xdabb,0xdabc,0xd79e,0xbdeb,0xcedc,0xd3ef,0xdabd,0xcef3, -0xdabe,0xd3d5,0xbbe5,0xdabf,0xcbb5,0xcbd0,0xdac0,0xc7eb,0xd6ee,0xdac1,0xc5b5,0xb6c1,0xdac2,0xb7cc,0xbfce,0xdac3, -0xdac4,0xcbad,0xdac5,0xb5f7,0xdac6,0xc1c2,0xd7bb,0xdac7,0xccb8,0xd79f,0xd2ea,0xc4b1,0xdac8,0xb5fd,0xbbd1,0xdac9, -0xd0b3,0xdaca,0xdacb,0xcebd,0xdacc,0xdacd,0xdace,0xb2f7,0xdad1,0xdacf,0xd1e8,0xdad0,0xc3d5,0xdad2,0xd7a0,0xdad3, -0xdad4,0xdad5,0xd0bb,0xd2a5,0xb0f9,0xdad6,0xc7ab,0xdad7,0xbdf7,0xc3a1,0xdad8,0xdad9,0xc3fd,0xccb7,0xdada,0xdadb, -0xc0be,0xc6d7,0xdadc,0xdadd,0xc7b4,0xdade,0xdadf,0xb9c8,0xd840,0xd841,0xd842,0xd843,0xd844,0xd845,0xd846,0xd847, -0xd848,0xbbed,0xd849,0xd84a,0xd84b,0xd84c,0xb6b9,0xf4f8,0xd84d,0xf4f9,0xd84e,0xd84f,0xcde3,0xd850,0xd851,0xd852, -0xd853,0xd854,0xd855,0xd856,0xd857,0xf5b9,0xd858,0xd859,0xd85a,0xd85b,0xebe0,0xd85c,0xd85d,0xd85e,0xd85f,0xd860, -0xd861,0xcff3,0xbbbf,0xd862,0xd863,0xd864,0xd865,0xd866,0xd867,0xd868,0xbac0,0xd4a5,0xd869,0xd86a,0xd86b,0xd86c, -0xd86d,0xd86e,0xd86f,0xe1d9,0xd870,0xd871,0xd872,0xd873,0xf5f4,0xb1aa,0xb2f2,0xd874,0xd875,0xd876,0xd877,0xd878, -0xd879,0xd87a,0xf5f5,0xd87b,0xd87c,0xf5f7,0xd87d,0xd87e,0xd880,0xbad1,0xf5f6,0xd881,0xc3b2,0xd882,0xd883,0xd884, -0xd885,0xd886,0xd887,0xd888,0xf5f9,0xd889,0xd88a,0xd88b,0xf5f8,0xd88c,0xd88d,0xd88e,0xd88f,0xd890,0xd891,0xd892, -0xd893,0xd894,0xd895,0xd896,0xd897,0xd898,0xd899,0xd89a,0xd89b,0xd89c,0xd89d,0xd89e,0xd89f,0xd8a0,0xd940,0xd941, -0xd942,0xd943,0xd944,0xd945,0xd946,0xd947,0xd948,0xd949,0xd94a,0xd94b,0xd94c,0xd94d,0xd94e,0xd94f,0xd950,0xd951, -0xd952,0xd953,0xd954,0xd955,0xd956,0xd957,0xd958,0xd959,0xd95a,0xd95b,0xd95c,0xd95d,0xd95e,0xd95f,0xd960,0xd961, -0xd962,0xd963,0xd964,0xd965,0xd966,0xd967,0xd968,0xd969,0xd96a,0xd96b,0xd96c,0xd96d,0xd96e,0xd96f,0xd970,0xd971, -0xd972,0xd973,0xd974,0xd975,0xd976,0xd977,0xd978,0xd979,0xd97a,0xd97b,0xd97c,0xd97d,0xd97e,0xd980,0xd981,0xd982, -0xd983,0xd984,0xd985,0xd986,0xd987,0xd988,0xd989,0xd98a,0xd98b,0xd98c,0xd98d,0xd98e,0xd98f,0xd990,0xd991,0xd992, -0xd993,0xd994,0xd995,0xd996,0xd997,0xd998,0xd999,0xd99a,0xd99b,0xd99c,0xd99d,0xd99e,0xd99f,0xd9a0,0xda40,0xda41, -0xda42,0xda43,0xda44,0xda45,0xda46,0xda47,0xda48,0xda49,0xda4a,0xda4b,0xda4c,0xda4d,0xda4e,0xb1b4,0xd5ea,0xb8ba, -0xda4f,0xb9b1,0xb2c6,0xd4f0,0xcfcd,0xb0dc,0xd5cb,0xbbf5,0xd6ca,0xb7b7,0xccb0,0xc6b6,0xb1e1,0xb9ba,0xd6fc,0xb9e1, -0xb7a1,0xbcfa,0xeada,0xeadb,0xccf9,0xb9f3,0xeadc,0xb4fb,0xc3b3,0xb7d1,0xbad8,0xeadd,0xd4f4,0xeade,0xbcd6,0xbbdf, -0xeadf,0xc1de,0xc2b8,0xd4df,0xd7ca,0xeae0,0xeae1,0xeae4,0xeae2,0xeae3,0xc9de,0xb8b3,0xb6c4,0xeae5,0xcaea,0xc9cd, -0xb4cd,0xda50,0xda51,0xe2d9,0xc5e2,0xeae6,0xc0b5,0xda52,0xd7b8,0xeae7,0xd7ac,0xc8fc,0xd8d3,0xd8cd,0xd4de,0xda53, -0xd4f9,0xc9c4,0xd3ae,0xb8d3,0xb3e0,0xda54,0xc9e2,0xf4f6,0xda55,0xda56,0xda57,0xbad5,0xda58,0xf4f7,0xda59,0xda5a, -0xd7df,0xda5b,0xda5c,0xf4f1,0xb8b0,0xd5d4,0xb8cf,0xc6f0,0xda5d,0xda5e,0xda5f,0xda60,0xda61,0xda62,0xda63,0xda64, -0xda65,0xb3c3,0xda66,0xda67,0xf4f2,0xb3ac,0xda68,0xda69,0xda6a,0xda6b,0xd4bd,0xc7f7,0xda6c,0xda6d,0xda6e,0xda6f, -0xda70,0xf4f4,0xda71,0xda72,0xf4f3,0xda73,0xda74,0xda75,0xda76,0xda77,0xda78,0xda79,0xda7a,0xda7b,0xda7c,0xcccb, -0xda7d,0xda7e,0xda80,0xc8a4,0xda81,0xda82,0xda83,0xda84,0xda85,0xda86,0xda87,0xda88,0xda89,0xda8a,0xda8b,0xda8c, -0xda8d,0xf4f5,0xda8e,0xd7e3,0xc5bf,0xf5c0,0xda8f,0xda90,0xf5bb,0xda91,0xf5c3,0xda92,0xf5c2,0xda93,0xd6ba,0xf5c1, -0xda94,0xda95,0xda96,0xd4be,0xf5c4,0xda97,0xf5cc,0xda98,0xda99,0xda9a,0xda9b,0xb0cf,0xb5f8,0xda9c,0xf5c9,0xf5ca, -0xda9d,0xc5dc,0xda9e,0xda9f,0xdaa0,0xdb40,0xf5c5,0xf5c6,0xdb41,0xdb42,0xf5c7,0xf5cb,0xdb43,0xbee0,0xf5c8,0xb8fa, -0xdb44,0xdb45,0xdb46,0xf5d0,0xf5d3,0xdb47,0xdb48,0xdb49,0xbfe7,0xdb4a,0xb9f2,0xf5bc,0xf5cd,0xdb4b,0xdb4c,0xc2b7, -0xdb4d,0xdb4e,0xdb4f,0xccf8,0xdb50,0xbcf9,0xdb51,0xf5ce,0xf5cf,0xf5d1,0xb6e5,0xf5d2,0xdb52,0xf5d5,0xdb53,0xdb54, -0xdb55,0xdb56,0xdb57,0xdb58,0xdb59,0xf5bd,0xdb5a,0xdb5b,0xdb5c,0xf5d4,0xd3bb,0xdb5d,0xb3ec,0xdb5e,0xdb5f,0xcca4, -0xdb60,0xdb61,0xdb62,0xdb63,0xf5d6,0xdb64,0xdb65,0xdb66,0xdb67,0xdb68,0xdb69,0xdb6a,0xdb6b,0xf5d7,0xbee1,0xf5d8, -0xdb6c,0xdb6d,0xccdf,0xf5db,0xdb6e,0xdb6f,0xdb70,0xdb71,0xdb72,0xb2c8,0xd7d9,0xdb73,0xf5d9,0xdb74,0xf5da,0xf5dc, -0xdb75,0xf5e2,0xdb76,0xdb77,0xdb78,0xf5e0,0xdb79,0xdb7a,0xdb7b,0xf5df,0xf5dd,0xdb7c,0xdb7d,0xf5e1,0xdb7e,0xdb80, -0xf5de,0xf5e4,0xf5e5,0xdb81,0xcce3,0xdb82,0xdb83,0xe5bf,0xb5b8,0xf5e3,0xf5e8,0xcca3,0xdb84,0xdb85,0xdb86,0xdb87, -0xdb88,0xf5e6,0xf5e7,0xdb89,0xdb8a,0xdb8b,0xdb8c,0xdb8d,0xdb8e,0xf5be,0xdb8f,0xdb90,0xdb91,0xdb92,0xdb93,0xdb94, -0xdb95,0xdb96,0xdb97,0xdb98,0xdb99,0xdb9a,0xb1c4,0xdb9b,0xdb9c,0xf5bf,0xdb9d,0xdb9e,0xb5c5,0xb2e4,0xdb9f,0xf5ec, -0xf5e9,0xdba0,0xb6d7,0xdc40,0xf5ed,0xdc41,0xf5ea,0xdc42,0xdc43,0xdc44,0xdc45,0xdc46,0xf5eb,0xdc47,0xdc48,0xb4da, -0xdc49,0xd4ea,0xdc4a,0xdc4b,0xdc4c,0xf5ee,0xdc4d,0xb3f9,0xdc4e,0xdc4f,0xdc50,0xdc51,0xdc52,0xdc53,0xdc54,0xf5ef, -0xf5f1,0xdc55,0xdc56,0xdc57,0xf5f0,0xdc58,0xdc59,0xdc5a,0xdc5b,0xdc5c,0xdc5d,0xdc5e,0xf5f2,0xdc5f,0xf5f3,0xdc60, -0xdc61,0xdc62,0xdc63,0xdc64,0xdc65,0xdc66,0xdc67,0xdc68,0xdc69,0xdc6a,0xdc6b,0xc9ed,0xb9aa,0xdc6c,0xdc6d,0xc7fb, -0xdc6e,0xdc6f,0xb6e3,0xdc70,0xdc71,0xdc72,0xdc73,0xdc74,0xdc75,0xdc76,0xccc9,0xdc77,0xdc78,0xdc79,0xdc7a,0xdc7b, -0xdc7c,0xdc7d,0xdc7e,0xdc80,0xdc81,0xdc82,0xdc83,0xdc84,0xdc85,0xdc86,0xdc87,0xdc88,0xdc89,0xdc8a,0xeaa6,0xdc8b, -0xdc8c,0xdc8d,0xdc8e,0xdc8f,0xdc90,0xdc91,0xdc92,0xdc93,0xdc94,0xdc95,0xdc96,0xdc97,0xdc98,0xdc99,0xdc9a,0xdc9b, -0xdc9c,0xdc9d,0xdc9e,0xdc9f,0xdca0,0xdd40,0xdd41,0xdd42,0xdd43,0xdd44,0xdd45,0xdd46,0xdd47,0xdd48,0xdd49,0xdd4a, -0xdd4b,0xdd4c,0xdd4d,0xdd4e,0xdd4f,0xdd50,0xdd51,0xdd52,0xdd53,0xdd54,0xdd55,0xdd56,0xdd57,0xdd58,0xdd59,0xdd5a, -0xdd5b,0xdd5c,0xdd5d,0xdd5e,0xdd5f,0xdd60,0xdd61,0xdd62,0xdd63,0xdd64,0xdd65,0xdd66,0xdd67,0xdd68,0xdd69,0xdd6a, -0xdd6b,0xdd6c,0xdd6d,0xdd6e,0xdd6f,0xdd70,0xdd71,0xdd72,0xdd73,0xdd74,0xdd75,0xdd76,0xdd77,0xdd78,0xdd79,0xdd7a, -0xdd7b,0xdd7c,0xdd7d,0xdd7e,0xdd80,0xdd81,0xdd82,0xdd83,0xdd84,0xdd85,0xdd86,0xdd87,0xdd88,0xdd89,0xdd8a,0xdd8b, -0xdd8c,0xdd8d,0xdd8e,0xdd8f,0xdd90,0xdd91,0xdd92,0xdd93,0xdd94,0xdd95,0xdd96,0xdd97,0xdd98,0xdd99,0xdd9a,0xdd9b, -0xdd9c,0xdd9d,0xdd9e,0xdd9f,0xdda0,0xde40,0xde41,0xde42,0xde43,0xde44,0xde45,0xde46,0xde47,0xde48,0xde49,0xde4a, -0xde4b,0xde4c,0xde4d,0xde4e,0xde4f,0xde50,0xde51,0xde52,0xde53,0xde54,0xde55,0xde56,0xde57,0xde58,0xde59,0xde5a, -0xde5b,0xde5c,0xde5d,0xde5e,0xde5f,0xde60,0xb3b5,0xd4fe,0xb9ec,0xd0f9,0xde61,0xe9ed,0xd7aa,0xe9ee,0xc2d6,0xc8ed, -0xbae4,0xe9ef,0xe9f0,0xe9f1,0xd6e1,0xe9f2,0xe9f3,0xe9f5,0xe9f4,0xe9f6,0xe9f7,0xc7e1,0xe9f8,0xd4d8,0xe9f9,0xbdce, -0xde62,0xe9fa,0xe9fb,0xbdcf,0xe9fc,0xb8a8,0xc1be,0xe9fd,0xb1b2,0xbbd4,0xb9f5,0xe9fe,0xde63,0xeaa1,0xeaa2,0xeaa3, -0xb7f8,0xbcad,0xde64,0xcae4,0xe0ce,0xd4af,0xcfbd,0xd5b7,0xeaa4,0xd5de,0xeaa5,0xd0c1,0xb9bc,0xde65,0xb4c7,0xb1d9, -0xde66,0xde67,0xde68,0xc0b1,0xde69,0xde6a,0xde6b,0xde6c,0xb1e6,0xb1e7,0xde6d,0xb1e8,0xde6e,0xde6f,0xde70,0xde71, -0xb3bd,0xc8e8,0xde72,0xde73,0xde74,0xde75,0xe5c1,0xde76,0xde77,0xb1df,0xde78,0xde79,0xde7a,0xc1c9,0xb4ef,0xde7b, -0xde7c,0xc7a8,0xd3d8,0xde7d,0xc6f9,0xd1b8,0xde7e,0xb9fd,0xc2f5,0xde80,0xde81,0xde82,0xde83,0xde84,0xd3ad,0xde85, -0xd4cb,0xbdfc,0xde86,0xe5c2,0xb7b5,0xe5c3,0xde87,0xde88,0xbbb9,0xd5e2,0xde89,0xbdf8,0xd4b6,0xcea5,0xc1ac,0xb3d9, -0xde8a,0xde8b,0xccf6,0xde8c,0xe5c6,0xe5c4,0xe5c8,0xde8d,0xe5ca,0xe5c7,0xb5cf,0xc6c8,0xde8e,0xb5fc,0xe5c5,0xde8f, -0xcaf6,0xde90,0xde91,0xe5c9,0xde92,0xde93,0xde94,0xc3d4,0xb1c5,0xbca3,0xde95,0xde96,0xde97,0xd7b7,0xde98,0xde99, -0xcdcb,0xcbcd,0xcaca,0xccd3,0xe5cc,0xe5cb,0xc4e6,0xde9a,0xde9b,0xd1a1,0xd1b7,0xe5cd,0xde9c,0xe5d0,0xde9d,0xcdb8, -0xd6f0,0xe5cf,0xb5dd,0xde9e,0xcdbe,0xde9f,0xe5d1,0xb6ba,0xdea0,0xdf40,0xcda8,0xb9e4,0xdf41,0xcac5,0xb3d1,0xcbd9, -0xd4ec,0xe5d2,0xb7ea,0xdf42,0xdf43,0xdf44,0xe5ce,0xdf45,0xdf46,0xdf47,0xdf48,0xdf49,0xdf4a,0xe5d5,0xb4fe,0xe5d6, -0xdf4b,0xdf4c,0xdf4d,0xdf4e,0xdf4f,0xe5d3,0xe5d4,0xdf50,0xd2dd,0xdf51,0xdf52,0xc2df,0xb1c6,0xdf53,0xd3e2,0xdf54, -0xdf55,0xb6dd,0xcbec,0xdf56,0xe5d7,0xdf57,0xdf58,0xd3f6,0xdf59,0xdf5a,0xdf5b,0xdf5c,0xdf5d,0xb1e9,0xdf5e,0xb6f4, -0xe5da,0xe5d8,0xe5d9,0xb5c0,0xdf5f,0xdf60,0xdf61,0xd2c5,0xe5dc,0xdf62,0xdf63,0xe5de,0xdf64,0xdf65,0xdf66,0xdf67, -0xdf68,0xdf69,0xe5dd,0xc7b2,0xdf6a,0xd2a3,0xdf6b,0xdf6c,0xe5db,0xdf6d,0xdf6e,0xdf6f,0xdf70,0xd4e2,0xd5da,0xdf71, -0xdf72,0xdf73,0xdf74,0xdf75,0xe5e0,0xd7f1,0xdf76,0xdf77,0xdf78,0xdf79,0xdf7a,0xdf7b,0xdf7c,0xe5e1,0xdf7d,0xb1dc, -0xd1fb,0xdf7e,0xe5e2,0xe5e4,0xdf80,0xdf81,0xdf82,0xdf83,0xe5e3,0xdf84,0xdf85,0xe5e5,0xdf86,0xdf87,0xdf88,0xdf89, -0xdf8a,0xd2d8,0xdf8b,0xb5cb,0xdf8c,0xe7df,0xdf8d,0xdaf5,0xdf8e,0xdaf8,0xdf8f,0xdaf6,0xdf90,0xdaf7,0xdf91,0xdf92, -0xdf93,0xdafa,0xd0cf,0xc4c7,0xdf94,0xdf95,0xb0ee,0xdf96,0xdf97,0xdf98,0xd0b0,0xdf99,0xdaf9,0xdf9a,0xd3ca,0xbaaa, -0xdba2,0xc7f1,0xdf9b,0xdafc,0xdafb,0xc9db,0xdafd,0xdf9c,0xdba1,0xd7de,0xdafe,0xc1da,0xdf9d,0xdf9e,0xdba5,0xdf9f, -0xdfa0,0xd3f4,0xe040,0xe041,0xdba7,0xdba4,0xe042,0xdba8,0xe043,0xe044,0xbdbc,0xe045,0xe046,0xe047,0xc0c9,0xdba3, -0xdba6,0xd6a3,0xe048,0xdba9,0xe049,0xe04a,0xe04b,0xdbad,0xe04c,0xe04d,0xe04e,0xdbae,0xdbac,0xbac2,0xe04f,0xe050, -0xe051,0xbfa4,0xdbab,0xe052,0xe053,0xe054,0xdbaa,0xd4c7,0xb2bf,0xe055,0xe056,0xdbaf,0xe057,0xb9f9,0xe058,0xdbb0, -0xe059,0xe05a,0xe05b,0xe05c,0xb3bb,0xe05d,0xe05e,0xe05f,0xb5a6,0xe060,0xe061,0xe062,0xe063,0xb6bc,0xdbb1,0xe064, -0xe065,0xe066,0xb6f5,0xe067,0xdbb2,0xe068,0xe069,0xe06a,0xe06b,0xe06c,0xe06d,0xe06e,0xe06f,0xe070,0xe071,0xe072, -0xe073,0xe074,0xe075,0xe076,0xe077,0xe078,0xe079,0xe07a,0xe07b,0xb1c9,0xe07c,0xe07d,0xe07e,0xe080,0xdbb4,0xe081, -0xe082,0xe083,0xdbb3,0xdbb5,0xe084,0xe085,0xe086,0xe087,0xe088,0xe089,0xe08a,0xe08b,0xe08c,0xe08d,0xe08e,0xdbb7, -0xe08f,0xdbb6,0xe090,0xe091,0xe092,0xe093,0xe094,0xe095,0xe096,0xdbb8,0xe097,0xe098,0xe099,0xe09a,0xe09b,0xe09c, -0xe09d,0xe09e,0xe09f,0xdbb9,0xe0a0,0xe140,0xdbba,0xe141,0xe142,0xd3cf,0xf4fa,0xc7f5,0xd7c3,0xc5e4,0xf4fc,0xf4fd, -0xf4fb,0xe143,0xbec6,0xe144,0xe145,0xe146,0xe147,0xd0ef,0xe148,0xe149,0xb7d3,0xe14a,0xe14b,0xd4cd,0xccaa,0xe14c, -0xe14d,0xf5a2,0xf5a1,0xbaa8,0xf4fe,0xcbd6,0xe14e,0xe14f,0xe150,0xf5a4,0xc0d2,0xe151,0xb3ea,0xe152,0xcdaa,0xf5a5, -0xf5a3,0xbdb4,0xf5a8,0xe153,0xf5a9,0xbdcd,0xc3b8,0xbfe1,0xcbe1,0xf5aa,0xe154,0xe155,0xe156,0xf5a6,0xf5a7,0xc4f0, -0xe157,0xe158,0xe159,0xe15a,0xe15b,0xf5ac,0xe15c,0xb4bc,0xe15d,0xd7ed,0xe15e,0xb4d7,0xf5ab,0xf5ae,0xe15f,0xe160, -0xf5ad,0xf5af,0xd0d1,0xe161,0xe162,0xe163,0xe164,0xe165,0xe166,0xe167,0xc3d1,0xc8a9,0xe168,0xe169,0xe16a,0xe16b, -0xe16c,0xe16d,0xf5b0,0xf5b1,0xe16e,0xe16f,0xe170,0xe171,0xe172,0xe173,0xf5b2,0xe174,0xe175,0xf5b3,0xf5b4,0xf5b5, -0xe176,0xe177,0xe178,0xe179,0xf5b7,0xf5b6,0xe17a,0xe17b,0xe17c,0xe17d,0xf5b8,0xe17e,0xe180,0xe181,0xe182,0xe183, -0xe184,0xe185,0xe186,0xe187,0xe188,0xe189,0xe18a,0xb2c9,0xe18b,0xd3d4,0xcacd,0xe18c,0xc0ef,0xd6d8,0xd2b0,0xc1bf, -0xe18d,0xbdf0,0xe18e,0xe18f,0xe190,0xe191,0xe192,0xe193,0xe194,0xe195,0xe196,0xe197,0xb8aa,0xe198,0xe199,0xe19a, -0xe19b,0xe19c,0xe19d,0xe19e,0xe19f,0xe1a0,0xe240,0xe241,0xe242,0xe243,0xe244,0xe245,0xe246,0xe247,0xe248,0xe249, -0xe24a,0xe24b,0xe24c,0xe24d,0xe24e,0xe24f,0xe250,0xe251,0xe252,0xe253,0xe254,0xe255,0xe256,0xe257,0xe258,0xe259, -0xe25a,0xe25b,0xe25c,0xe25d,0xe25e,0xe25f,0xe260,0xe261,0xe262,0xe263,0xe264,0xe265,0xe266,0xe267,0xe268,0xe269, -0xe26a,0xe26b,0xe26c,0xe26d,0xe26e,0xe26f,0xe270,0xe271,0xe272,0xe273,0xe274,0xe275,0xe276,0xe277,0xe278,0xe279, -0xe27a,0xe27b,0xe27c,0xe27d,0xe27e,0xe280,0xe281,0xe282,0xe283,0xe284,0xe285,0xe286,0xe287,0xe288,0xe289,0xe28a, -0xe28b,0xe28c,0xe28d,0xe28e,0xe28f,0xe290,0xe291,0xe292,0xe293,0xe294,0xe295,0xe296,0xe297,0xe298,0xe299,0xe29a, -0xe29b,0xe29c,0xe29d,0xe29e,0xe29f,0xe2a0,0xe340,0xe341,0xe342,0xe343,0xe344,0xe345,0xe346,0xe347,0xe348,0xe349, -0xe34a,0xe34b,0xe34c,0xe34d,0xe34e,0xe34f,0xe350,0xe351,0xe352,0xe353,0xe354,0xe355,0xe356,0xe357,0xe358,0xe359, -0xe35a,0xe35b,0xe35c,0xe35d,0xe35e,0xe35f,0xe360,0xe361,0xe362,0xe363,0xe364,0xe365,0xe366,0xe367,0xe368,0xe369, -0xe36a,0xe36b,0xe36c,0xe36d,0xbcf8,0xe36e,0xe36f,0xe370,0xe371,0xe372,0xe373,0xe374,0xe375,0xe376,0xe377,0xe378, -0xe379,0xe37a,0xe37b,0xe37c,0xe37d,0xe37e,0xe380,0xe381,0xe382,0xe383,0xe384,0xe385,0xe386,0xe387,0xf6c6,0xe388, -0xe389,0xe38a,0xe38b,0xe38c,0xe38d,0xe38e,0xe38f,0xe390,0xe391,0xe392,0xe393,0xe394,0xe395,0xe396,0xe397,0xe398, -0xe399,0xe39a,0xe39b,0xe39c,0xe39d,0xe39e,0xe39f,0xe3a0,0xe440,0xe441,0xe442,0xe443,0xe444,0xe445,0xf6c7,0xe446, -0xe447,0xe448,0xe449,0xe44a,0xe44b,0xe44c,0xe44d,0xe44e,0xe44f,0xe450,0xe451,0xe452,0xe453,0xe454,0xe455,0xe456, -0xe457,0xe458,0xe459,0xe45a,0xe45b,0xe45c,0xe45d,0xe45e,0xf6c8,0xe45f,0xe460,0xe461,0xe462,0xe463,0xe464,0xe465, -0xe466,0xe467,0xe468,0xe469,0xe46a,0xe46b,0xe46c,0xe46d,0xe46e,0xe46f,0xe470,0xe471,0xe472,0xe473,0xe474,0xe475, -0xe476,0xe477,0xe478,0xe479,0xe47a,0xe47b,0xe47c,0xe47d,0xe47e,0xe480,0xe481,0xe482,0xe483,0xe484,0xe485,0xe486, -0xe487,0xe488,0xe489,0xe48a,0xe48b,0xe48c,0xe48d,0xe48e,0xe48f,0xe490,0xe491,0xe492,0xe493,0xe494,0xe495,0xe496, -0xe497,0xe498,0xe499,0xe49a,0xe49b,0xe49c,0xe49d,0xe49e,0xe49f,0xe4a0,0xe540,0xe541,0xe542,0xe543,0xe544,0xe545, -0xe546,0xe547,0xe548,0xe549,0xe54a,0xe54b,0xe54c,0xe54d,0xe54e,0xe54f,0xe550,0xe551,0xe552,0xe553,0xe554,0xe555, -0xe556,0xe557,0xe558,0xe559,0xe55a,0xe55b,0xe55c,0xe55d,0xe55e,0xe55f,0xe560,0xe561,0xe562,0xe563,0xe564,0xe565, -0xe566,0xe567,0xe568,0xe569,0xe56a,0xe56b,0xe56c,0xe56d,0xe56e,0xe56f,0xe570,0xe571,0xe572,0xe573,0xf6c9,0xe574, -0xe575,0xe576,0xe577,0xe578,0xe579,0xe57a,0xe57b,0xe57c,0xe57d,0xe57e,0xe580,0xe581,0xe582,0xe583,0xe584,0xe585, -0xe586,0xe587,0xe588,0xe589,0xe58a,0xe58b,0xe58c,0xe58d,0xe58e,0xe58f,0xe590,0xe591,0xe592,0xe593,0xe594,0xe595, -0xe596,0xe597,0xe598,0xe599,0xe59a,0xe59b,0xe59c,0xe59d,0xe59e,0xe59f,0xf6ca,0xe5a0,0xe640,0xe641,0xe642,0xe643, -0xe644,0xe645,0xe646,0xe647,0xe648,0xe649,0xe64a,0xe64b,0xe64c,0xe64d,0xe64e,0xe64f,0xe650,0xe651,0xe652,0xe653, -0xe654,0xe655,0xe656,0xe657,0xe658,0xe659,0xe65a,0xe65b,0xe65c,0xe65d,0xe65e,0xe65f,0xe660,0xe661,0xe662,0xf6cc, -0xe663,0xe664,0xe665,0xe666,0xe667,0xe668,0xe669,0xe66a,0xe66b,0xe66c,0xe66d,0xe66e,0xe66f,0xe670,0xe671,0xe672, -0xe673,0xe674,0xe675,0xe676,0xe677,0xe678,0xe679,0xe67a,0xe67b,0xe67c,0xe67d,0xe67e,0xe680,0xe681,0xe682,0xe683, -0xe684,0xe685,0xe686,0xe687,0xe688,0xe689,0xe68a,0xe68b,0xe68c,0xe68d,0xe68e,0xe68f,0xe690,0xe691,0xe692,0xe693, -0xe694,0xe695,0xe696,0xe697,0xe698,0xe699,0xe69a,0xe69b,0xe69c,0xe69d,0xf6cb,0xe69e,0xe69f,0xe6a0,0xe740,0xe741, -0xe742,0xe743,0xe744,0xe745,0xe746,0xe747,0xf7e9,0xe748,0xe749,0xe74a,0xe74b,0xe74c,0xe74d,0xe74e,0xe74f,0xe750, -0xe751,0xe752,0xe753,0xe754,0xe755,0xe756,0xe757,0xe758,0xe759,0xe75a,0xe75b,0xe75c,0xe75d,0xe75e,0xe75f,0xe760, -0xe761,0xe762,0xe763,0xe764,0xe765,0xe766,0xe767,0xe768,0xe769,0xe76a,0xe76b,0xe76c,0xe76d,0xe76e,0xe76f,0xe770, -0xe771,0xe772,0xe773,0xe774,0xe775,0xe776,0xe777,0xe778,0xe779,0xe77a,0xe77b,0xe77c,0xe77d,0xe77e,0xe780,0xe781, -0xe782,0xe783,0xe784,0xe785,0xe786,0xe787,0xe788,0xe789,0xe78a,0xe78b,0xe78c,0xe78d,0xe78e,0xe78f,0xe790,0xe791, -0xe792,0xe793,0xe794,0xe795,0xe796,0xe797,0xe798,0xe799,0xe79a,0xe79b,0xe79c,0xe79d,0xe79e,0xe79f,0xe7a0,0xe840, -0xe841,0xe842,0xe843,0xe844,0xe845,0xe846,0xe847,0xe848,0xe849,0xe84a,0xe84b,0xe84c,0xe84d,0xe84e,0xf6cd,0xe84f, -0xe850,0xe851,0xe852,0xe853,0xe854,0xe855,0xe856,0xe857,0xe858,0xe859,0xe85a,0xe85b,0xe85c,0xe85d,0xe85e,0xe85f, -0xe860,0xe861,0xe862,0xe863,0xe864,0xe865,0xe866,0xe867,0xe868,0xe869,0xe86a,0xe86b,0xe86c,0xe86d,0xe86e,0xe86f, -0xe870,0xe871,0xe872,0xe873,0xe874,0xe875,0xe876,0xe877,0xe878,0xe879,0xe87a,0xf6ce,0xe87b,0xe87c,0xe87d,0xe87e, -0xe880,0xe881,0xe882,0xe883,0xe884,0xe885,0xe886,0xe887,0xe888,0xe889,0xe88a,0xe88b,0xe88c,0xe88d,0xe88e,0xe88f, -0xe890,0xe891,0xe892,0xe893,0xe894,0xeec4,0xeec5,0xeec6,0xd5eb,0xb6a4,0xeec8,0xeec7,0xeec9,0xeeca,0xc7a5,0xeecb, -0xeecc,0xe895,0xb7b0,0xb5f6,0xeecd,0xeecf,0xe896,0xeece,0xe897,0xb8c6,0xeed0,0xeed1,0xeed2,0xb6db,0xb3ae,0xd6d3, -0xc4c6,0xb1b5,0xb8d6,0xeed3,0xeed4,0xd4bf,0xc7d5,0xbefb,0xced9,0xb9b3,0xeed6,0xeed5,0xeed8,0xeed7,0xc5a5,0xeed9, -0xeeda,0xc7ae,0xeedb,0xc7af,0xeedc,0xb2a7,0xeedd,0xeede,0xeedf,0xeee0,0xeee1,0xd7ea,0xeee2,0xeee3,0xbcd8,0xeee4, -0xd3cb,0xccfa,0xb2ac,0xc1e5,0xeee5,0xc7a6,0xc3ad,0xe898,0xeee6,0xeee7,0xeee8,0xeee9,0xeeea,0xeeeb,0xeeec,0xe899, -0xeeed,0xeeee,0xeeef,0xe89a,0xe89b,0xeef0,0xeef1,0xeef2,0xeef4,0xeef3,0xe89c,0xeef5,0xcdad,0xc2c1,0xeef6,0xeef7, -0xeef8,0xd5a1,0xeef9,0xcfb3,0xeefa,0xeefb,0xe89d,0xeefc,0xeefd,0xefa1,0xeefe,0xefa2,0xb8f5,0xc3fa,0xefa3,0xefa4, -0xbdc2,0xd2bf,0xb2f9,0xefa5,0xefa6,0xefa7,0xd2f8,0xefa8,0xd6fd,0xefa9,0xc6cc,0xe89e,0xefaa,0xefab,0xc1b4,0xefac, -0xcffa,0xcbf8,0xefae,0xefad,0xb3fa,0xb9f8,0xefaf,0xefb0,0xd0e2,0xefb1,0xefb2,0xb7e6,0xd0bf,0xefb3,0xefb4,0xefb5, -0xc8f1,0xcce0,0xefb6,0xefb7,0xefb8,0xefb9,0xefba,0xd5e0,0xefbb,0xb4ed,0xc3aa,0xefbc,0xe89f,0xefbd,0xefbe,0xefbf, -0xe8a0,0xcefd,0xefc0,0xc2e0,0xb4b8,0xd7b6,0xbdf5,0xe940,0xcfc7,0xefc3,0xefc1,0xefc2,0xefc4,0xb6a7,0xbcfc,0xbee2, -0xc3cc,0xefc5,0xefc6,0xe941,0xefc7,0xefcf,0xefc8,0xefc9,0xefca,0xc7c2,0xeff1,0xb6cd,0xefcb,0xe942,0xefcc,0xefcd, -0xb6c6,0xc3be,0xefce,0xe943,0xefd0,0xefd1,0xefd2,0xd5f2,0xe944,0xefd3,0xc4f7,0xe945,0xefd4,0xc4f8,0xefd5,0xefd6, -0xb8e4,0xb0f7,0xefd7,0xefd8,0xefd9,0xe946,0xefda,0xefdb,0xefdc,0xefdd,0xe947,0xefde,0xbeb5,0xefe1,0xefdf,0xefe0, -0xe948,0xefe2,0xefe3,0xc1cd,0xefe4,0xefe5,0xefe6,0xefe7,0xefe8,0xefe9,0xefea,0xefeb,0xefec,0xc0d8,0xe949,0xefed, -0xc1ad,0xefee,0xefef,0xeff0,0xe94a,0xe94b,0xcfe2,0xe94c,0xe94d,0xe94e,0xe94f,0xe950,0xe951,0xe952,0xe953,0xb3a4, -0xe954,0xe955,0xe956,0xe957,0xe958,0xe959,0xe95a,0xe95b,0xe95c,0xe95d,0xe95e,0xe95f,0xe960,0xe961,0xe962,0xe963, -0xe964,0xe965,0xe966,0xe967,0xe968,0xe969,0xe96a,0xe96b,0xe96c,0xe96d,0xe96e,0xe96f,0xe970,0xe971,0xe972,0xe973, -0xe974,0xe975,0xe976,0xe977,0xe978,0xe979,0xe97a,0xe97b,0xe97c,0xe97d,0xe97e,0xe980,0xe981,0xe982,0xe983,0xe984, -0xe985,0xe986,0xe987,0xe988,0xe989,0xe98a,0xe98b,0xe98c,0xe98d,0xe98e,0xe98f,0xe990,0xe991,0xe992,0xe993,0xe994, -0xe995,0xe996,0xe997,0xe998,0xe999,0xe99a,0xe99b,0xe99c,0xe99d,0xe99e,0xe99f,0xe9a0,0xea40,0xea41,0xea42,0xea43, -0xea44,0xea45,0xea46,0xea47,0xea48,0xea49,0xea4a,0xea4b,0xea4c,0xea4d,0xea4e,0xea4f,0xea50,0xea51,0xea52,0xea53, -0xea54,0xea55,0xea56,0xea57,0xea58,0xea59,0xea5a,0xea5b,0xc3c5,0xe3c5,0xc9c1,0xe3c6,0xea5c,0xb1d5,0xceca,0xb4b3, -0xc8f2,0xe3c7,0xcfd0,0xe3c8,0xbce4,0xe3c9,0xe3ca,0xc3c6,0xd5a2,0xc4d6,0xb9eb,0xcec5,0xe3cb,0xc3f6,0xe3cc,0xea5d, -0xb7a7,0xb8f3,0xbad2,0xe3cd,0xe3ce,0xd4c4,0xe3cf,0xea5e,0xe3d0,0xd1cb,0xe3d1,0xe3d2,0xe3d3,0xe3d4,0xd1d6,0xe3d5, -0xb2fb,0xc0bb,0xe3d6,0xea5f,0xc0ab,0xe3d7,0xe3d8,0xe3d9,0xea60,0xe3da,0xe3db,0xea61,0xb8b7,0xdae2,0xea62,0xb6d3, -0xea63,0xdae4,0xdae3,0xea64,0xea65,0xea66,0xea67,0xea68,0xea69,0xea6a,0xdae6,0xea6b,0xea6c,0xea6d,0xc8ee,0xea6e, -0xea6f,0xdae5,0xb7c0,0xd1f4,0xd2f5,0xd5f3,0xbdd7,0xea70,0xea71,0xea72,0xea73,0xd7e8,0xdae8,0xdae7,0xea74,0xb0a2, -0xcdd3,0xea75,0xdae9,0xea76,0xb8bd,0xbcca,0xc2bd,0xc2a4,0xb3c2,0xdaea,0xea77,0xc2aa,0xc4b0,0xbdb5,0xea78,0xea79, -0xcfde,0xea7a,0xea7b,0xea7c,0xdaeb,0xc9c2,0xea7d,0xea7e,0xea80,0xea81,0xea82,0xb1dd,0xea83,0xea84,0xea85,0xdaec, -0xea86,0xb6b8,0xd4ba,0xea87,0xb3fd,0xea88,0xea89,0xdaed,0xd4c9,0xcfd5,0xc5e3,0xea8a,0xdaee,0xea8b,0xea8c,0xea8d, -0xea8e,0xea8f,0xdaef,0xea90,0xdaf0,0xc1ea,0xccd5,0xcfdd,0xea91,0xea92,0xea93,0xea94,0xea95,0xea96,0xea97,0xea98, -0xea99,0xea9a,0xea9b,0xea9c,0xea9d,0xd3e7,0xc2a1,0xea9e,0xdaf1,0xea9f,0xeaa0,0xcbe5,0xeb40,0xdaf2,0xeb41,0xcbe6, -0xd2fe,0xeb42,0xeb43,0xeb44,0xb8f4,0xeb45,0xeb46,0xdaf3,0xb0af,0xcfb6,0xeb47,0xeb48,0xd5cf,0xeb49,0xeb4a,0xeb4b, -0xeb4c,0xeb4d,0xeb4e,0xeb4f,0xeb50,0xeb51,0xeb52,0xcbed,0xeb53,0xeb54,0xeb55,0xeb56,0xeb57,0xeb58,0xeb59,0xeb5a, -0xdaf4,0xeb5b,0xeb5c,0xe3c4,0xeb5d,0xeb5e,0xc1a5,0xeb5f,0xeb60,0xf6bf,0xeb61,0xeb62,0xf6c0,0xf6c1,0xc4d1,0xeb63, -0xc8b8,0xd1e3,0xeb64,0xeb65,0xd0db,0xd1c5,0xbcaf,0xb9cd,0xeb66,0xeff4,0xeb67,0xeb68,0xb4c6,0xd3ba,0xf6c2,0xb3fb, -0xeb69,0xeb6a,0xf6c3,0xeb6b,0xeb6c,0xb5f1,0xeb6d,0xeb6e,0xeb6f,0xeb70,0xeb71,0xeb72,0xeb73,0xeb74,0xeb75,0xeb76, -0xf6c5,0xeb77,0xeb78,0xeb79,0xeb7a,0xeb7b,0xeb7c,0xeb7d,0xd3ea,0xf6a7,0xd1a9,0xeb7e,0xeb80,0xeb81,0xeb82,0xf6a9, -0xeb83,0xeb84,0xeb85,0xf6a8,0xeb86,0xeb87,0xc1e3,0xc0d7,0xeb88,0xb1a2,0xeb89,0xeb8a,0xeb8b,0xeb8c,0xceed,0xeb8d, -0xd0e8,0xf6ab,0xeb8e,0xeb8f,0xcff6,0xeb90,0xf6aa,0xd5f0,0xf6ac,0xc3b9,0xeb91,0xeb92,0xeb93,0xbbf4,0xf6ae,0xf6ad, -0xeb94,0xeb95,0xeb96,0xc4de,0xeb97,0xeb98,0xc1d8,0xeb99,0xeb9a,0xeb9b,0xeb9c,0xeb9d,0xcbaa,0xeb9e,0xcfbc,0xeb9f, -0xeba0,0xec40,0xec41,0xec42,0xec43,0xec44,0xec45,0xec46,0xec47,0xec48,0xf6af,0xec49,0xec4a,0xf6b0,0xec4b,0xec4c, -0xf6b1,0xec4d,0xc2b6,0xec4e,0xec4f,0xec50,0xec51,0xec52,0xb0d4,0xc5f9,0xec53,0xec54,0xec55,0xec56,0xf6b2,0xec57, -0xec58,0xec59,0xec5a,0xec5b,0xec5c,0xec5d,0xec5e,0xec5f,0xec60,0xec61,0xec62,0xec63,0xec64,0xec65,0xec66,0xec67, -0xec68,0xec69,0xc7e0,0xf6a6,0xec6a,0xec6b,0xbeb8,0xec6c,0xec6d,0xbeb2,0xec6e,0xb5e5,0xec6f,0xec70,0xb7c7,0xec71, -0xbfbf,0xc3d2,0xc3e6,0xec72,0xec73,0xd8cc,0xec74,0xec75,0xec76,0xb8ef,0xec77,0xec78,0xec79,0xec7a,0xec7b,0xec7c, -0xec7d,0xec7e,0xec80,0xbdf9,0xd1a5,0xec81,0xb0d0,0xec82,0xec83,0xec84,0xec85,0xec86,0xf7b0,0xec87,0xec88,0xec89, -0xec8a,0xec8b,0xec8c,0xec8d,0xec8e,0xf7b1,0xec8f,0xec90,0xec91,0xec92,0xec93,0xd0ac,0xec94,0xb0b0,0xec95,0xec96, -0xec97,0xf7b2,0xf7b3,0xec98,0xf7b4,0xec99,0xec9a,0xec9b,0xc7ca,0xec9c,0xec9d,0xec9e,0xec9f,0xeca0,0xed40,0xed41, -0xbecf,0xed42,0xed43,0xf7b7,0xed44,0xed45,0xed46,0xed47,0xed48,0xed49,0xed4a,0xf7b6,0xed4b,0xb1de,0xed4c,0xf7b5, -0xed4d,0xed4e,0xf7b8,0xed4f,0xf7b9,0xed50,0xed51,0xed52,0xed53,0xed54,0xed55,0xed56,0xed57,0xed58,0xed59,0xed5a, -0xed5b,0xed5c,0xed5d,0xed5e,0xed5f,0xed60,0xed61,0xed62,0xed63,0xed64,0xed65,0xed66,0xed67,0xed68,0xed69,0xed6a, -0xed6b,0xed6c,0xed6d,0xed6e,0xed6f,0xed70,0xed71,0xed72,0xed73,0xed74,0xed75,0xed76,0xed77,0xed78,0xed79,0xed7a, -0xed7b,0xed7c,0xed7d,0xed7e,0xed80,0xed81,0xcea4,0xc8cd,0xed82,0xbaab,0xe8b8,0xe8b9,0xe8ba,0xbec2,0xed83,0xed84, -0xed85,0xed86,0xed87,0xd2f4,0xed88,0xd4cf,0xc9d8,0xed89,0xed8a,0xed8b,0xed8c,0xed8d,0xed8e,0xed8f,0xed90,0xed91, -0xed92,0xed93,0xed94,0xed95,0xed96,0xed97,0xed98,0xed99,0xed9a,0xed9b,0xed9c,0xed9d,0xed9e,0xed9f,0xeda0,0xee40, -0xee41,0xee42,0xee43,0xee44,0xee45,0xee46,0xee47,0xee48,0xee49,0xee4a,0xee4b,0xee4c,0xee4d,0xee4e,0xee4f,0xee50, -0xee51,0xee52,0xee53,0xee54,0xee55,0xee56,0xee57,0xee58,0xee59,0xee5a,0xee5b,0xee5c,0xee5d,0xee5e,0xee5f,0xee60, -0xee61,0xee62,0xee63,0xee64,0xee65,0xee66,0xee67,0xee68,0xee69,0xee6a,0xee6b,0xee6c,0xee6d,0xee6e,0xee6f,0xee70, -0xee71,0xee72,0xee73,0xee74,0xee75,0xee76,0xee77,0xee78,0xee79,0xee7a,0xee7b,0xee7c,0xee7d,0xee7e,0xee80,0xee81, -0xee82,0xee83,0xee84,0xee85,0xee86,0xee87,0xee88,0xee89,0xee8a,0xee8b,0xee8c,0xee8d,0xee8e,0xee8f,0xee90,0xee91, -0xee92,0xee93,0xee94,0xee95,0xee96,0xee97,0xee98,0xee99,0xee9a,0xee9b,0xee9c,0xee9d,0xee9e,0xee9f,0xeea0,0xef40, -0xef41,0xef42,0xef43,0xef44,0xef45,0xd2b3,0xb6a5,0xc7ea,0xf1fc,0xcfee,0xcbb3,0xd0eb,0xe7ef,0xcde7,0xb9cb,0xb6d9, -0xf1fd,0xb0e4,0xcbcc,0xf1fe,0xd4a4,0xc2ad,0xc1ec,0xc6c4,0xbeb1,0xf2a1,0xbcd5,0xef46,0xf2a2,0xf2a3,0xef47,0xf2a4, -0xd2c3,0xc6b5,0xef48,0xcdc7,0xf2a5,0xef49,0xd3b1,0xbfc5,0xcce2,0xef4a,0xf2a6,0xf2a7,0xd1d5,0xb6ee,0xf2a8,0xf2a9, -0xb5df,0xf2aa,0xf2ab,0xef4b,0xb2fc,0xf2ac,0xf2ad,0xc8a7,0xef4c,0xef4d,0xef4e,0xef4f,0xef50,0xef51,0xef52,0xef53, -0xef54,0xef55,0xef56,0xef57,0xef58,0xef59,0xef5a,0xef5b,0xef5c,0xef5d,0xef5e,0xef5f,0xef60,0xef61,0xef62,0xef63, -0xef64,0xef65,0xef66,0xef67,0xef68,0xef69,0xef6a,0xef6b,0xef6c,0xef6d,0xef6e,0xef6f,0xef70,0xef71,0xb7e7,0xef72, -0xef73,0xeca9,0xecaa,0xecab,0xef74,0xecac,0xef75,0xef76,0xc6ae,0xecad,0xecae,0xef77,0xef78,0xef79,0xb7c9,0xcab3, -0xef7a,0xef7b,0xef7c,0xef7d,0xef7e,0xef80,0xef81,0xe2b8,0xf7cf,0xef82,0xef83,0xef84,0xef85,0xef86,0xef87,0xef88, -0xef89,0xef8a,0xef8b,0xef8c,0xef8d,0xef8e,0xef8f,0xef90,0xef91,0xef92,0xef93,0xef94,0xef95,0xef96,0xef97,0xef98, -0xef99,0xef9a,0xef9b,0xef9c,0xef9d,0xef9e,0xef9f,0xefa0,0xf040,0xf041,0xf042,0xf043,0xf044,0xf7d0,0xf045,0xf046, -0xb2cd,0xf047,0xf048,0xf049,0xf04a,0xf04b,0xf04c,0xf04d,0xf04e,0xf04f,0xf050,0xf051,0xf052,0xf053,0xf054,0xf055, -0xf056,0xf057,0xf058,0xf059,0xf05a,0xf05b,0xf05c,0xf05d,0xf05e,0xf05f,0xf060,0xf061,0xf062,0xf063,0xf7d1,0xf064, -0xf065,0xf066,0xf067,0xf068,0xf069,0xf06a,0xf06b,0xf06c,0xf06d,0xf06e,0xf06f,0xf070,0xf071,0xf072,0xf073,0xf074, -0xf075,0xf076,0xf077,0xf078,0xf079,0xf07a,0xf07b,0xf07c,0xf07d,0xf07e,0xf080,0xf081,0xf082,0xf083,0xf084,0xf085, -0xf086,0xf087,0xf088,0xf089,0xf7d3,0xf7d2,0xf08a,0xf08b,0xf08c,0xf08d,0xf08e,0xf08f,0xf090,0xf091,0xf092,0xf093, -0xf094,0xf095,0xf096,0xe2bb,0xf097,0xbca2,0xf098,0xe2bc,0xe2bd,0xe2be,0xe2bf,0xe2c0,0xe2c1,0xb7b9,0xd2fb,0xbda4, -0xcace,0xb1a5,0xcbc7,0xf099,0xe2c2,0xb6fc,0xc8c4,0xe2c3,0xf09a,0xf09b,0xbdc8,0xf09c,0xb1fd,0xe2c4,0xf09d,0xb6f6, -0xe2c5,0xc4d9,0xf09e,0xf09f,0xe2c6,0xcfda,0xb9dd,0xe2c7,0xc0a1,0xf0a0,0xe2c8,0xb2f6,0xf140,0xe2c9,0xf141,0xc1f3, -0xe2ca,0xe2cb,0xc2f8,0xe2cc,0xe2cd,0xe2ce,0xcad7,0xd8b8,0xd9e5,0xcfe3,0xf142,0xf143,0xf144,0xf145,0xf146,0xf147, -0xf148,0xf149,0xf14a,0xf14b,0xf14c,0xf0a5,0xf14d,0xf14e,0xdcb0,0xf14f,0xf150,0xf151,0xf152,0xf153,0xf154,0xf155, -0xf156,0xf157,0xf158,0xf159,0xf15a,0xf15b,0xf15c,0xf15d,0xf15e,0xf15f,0xf160,0xf161,0xf162,0xf163,0xf164,0xf165, -0xf166,0xf167,0xf168,0xf169,0xf16a,0xf16b,0xf16c,0xf16d,0xf16e,0xf16f,0xf170,0xf171,0xf172,0xf173,0xf174,0xf175, -0xf176,0xf177,0xf178,0xf179,0xf17a,0xf17b,0xf17c,0xf17d,0xf17e,0xf180,0xf181,0xf182,0xf183,0xf184,0xf185,0xf186, -0xf187,0xf188,0xf189,0xf18a,0xf18b,0xf18c,0xf18d,0xf18e,0xf18f,0xf190,0xf191,0xf192,0xf193,0xf194,0xf195,0xf196, -0xf197,0xf198,0xf199,0xf19a,0xf19b,0xf19c,0xf19d,0xf19e,0xf19f,0xf1a0,0xf240,0xf241,0xf242,0xf243,0xf244,0xf245, -0xf246,0xf247,0xf248,0xf249,0xf24a,0xf24b,0xf24c,0xf24d,0xf24e,0xf24f,0xf250,0xf251,0xf252,0xf253,0xf254,0xf255, -0xf256,0xf257,0xf258,0xf259,0xf25a,0xf25b,0xf25c,0xf25d,0xf25e,0xf25f,0xf260,0xf261,0xf262,0xf263,0xf264,0xf265, -0xf266,0xf267,0xf268,0xf269,0xf26a,0xf26b,0xf26c,0xf26d,0xf26e,0xf26f,0xf270,0xf271,0xf272,0xf273,0xf274,0xf275, -0xf276,0xf277,0xf278,0xf279,0xf27a,0xf27b,0xf27c,0xf27d,0xf27e,0xf280,0xf281,0xf282,0xf283,0xf284,0xf285,0xf286, -0xf287,0xf288,0xf289,0xf28a,0xf28b,0xf28c,0xf28d,0xf28e,0xf28f,0xf290,0xf291,0xf292,0xf293,0xf294,0xf295,0xf296, -0xf297,0xf298,0xf299,0xf29a,0xf29b,0xf29c,0xf29d,0xf29e,0xf29f,0xf2a0,0xf340,0xf341,0xf342,0xf343,0xf344,0xf345, -0xf346,0xf347,0xf348,0xf349,0xf34a,0xf34b,0xf34c,0xf34d,0xf34e,0xf34f,0xf350,0xf351,0xc2ed,0xd4a6,0xcdd4,0xd1b1, -0xb3db,0xc7fd,0xf352,0xb2b5,0xc2bf,0xe6e0,0xcabb,0xe6e1,0xe6e2,0xbed4,0xe6e3,0xd7a4,0xcdd5,0xe6e5,0xbcdd,0xe6e4, -0xe6e6,0xe6e7,0xc2ee,0xf353,0xbdbe,0xe6e8,0xc2e6,0xbaa7,0xe6e9,0xf354,0xe6ea,0xb3d2,0xd1e9,0xf355,0xf356,0xbfa5, -0xe6eb,0xc6ef,0xe6ec,0xe6ed,0xf357,0xf358,0xe6ee,0xc6ad,0xe6ef,0xf359,0xc9a7,0xe6f0,0xe6f1,0xe6f2,0xe5b9,0xe6f3, -0xe6f4,0xc2e2,0xe6f5,0xe6f6,0xd6e8,0xe6f7,0xf35a,0xe6f8,0xb9c7,0xf35b,0xf35c,0xf35d,0xf35e,0xf35f,0xf360,0xf361, -0xf7bb,0xf7ba,0xf362,0xf363,0xf364,0xf365,0xf7be,0xf7bc,0xbaa1,0xf366,0xf7bf,0xf367,0xf7c0,0xf368,0xf369,0xf36a, -0xf7c2,0xf7c1,0xf7c4,0xf36b,0xf36c,0xf7c3,0xf36d,0xf36e,0xf36f,0xf370,0xf371,0xf7c5,0xf7c6,0xf372,0xf373,0xf374, -0xf375,0xf7c7,0xf376,0xcbe8,0xf377,0xf378,0xf379,0xf37a,0xb8df,0xf37b,0xf37c,0xf37d,0xf37e,0xf380,0xf381,0xf7d4, -0xf382,0xf7d5,0xf383,0xf384,0xf385,0xf386,0xf7d6,0xf387,0xf388,0xf389,0xf38a,0xf7d8,0xf38b,0xf7da,0xf38c,0xf7d7, -0xf38d,0xf38e,0xf38f,0xf390,0xf391,0xf392,0xf393,0xf394,0xf395,0xf7db,0xf396,0xf7d9,0xf397,0xf398,0xf399,0xf39a, -0xf39b,0xf39c,0xf39d,0xd7d7,0xf39e,0xf39f,0xf3a0,0xf440,0xf7dc,0xf441,0xf442,0xf443,0xf444,0xf445,0xf446,0xf7dd, -0xf447,0xf448,0xf449,0xf7de,0xf44a,0xf44b,0xf44c,0xf44d,0xf44e,0xf44f,0xf450,0xf451,0xf452,0xf453,0xf454,0xf7df, -0xf455,0xf456,0xf457,0xf7e0,0xf458,0xf459,0xf45a,0xf45b,0xf45c,0xf45d,0xf45e,0xf45f,0xf460,0xf461,0xf462,0xdbcb, -0xf463,0xf464,0xd8aa,0xf465,0xf466,0xf467,0xf468,0xf469,0xf46a,0xf46b,0xf46c,0xe5f7,0xb9ed,0xf46d,0xf46e,0xf46f, -0xf470,0xbffd,0xbbea,0xf7c9,0xc6c7,0xf7c8,0xf471,0xf7ca,0xf7cc,0xf7cb,0xf472,0xf473,0xf474,0xf7cd,0xf475,0xceba, -0xf476,0xf7ce,0xf477,0xf478,0xc4a7,0xf479,0xf47a,0xf47b,0xf47c,0xf47d,0xf47e,0xf480,0xf481,0xf482,0xf483,0xf484, -0xf485,0xf486,0xf487,0xf488,0xf489,0xf48a,0xf48b,0xf48c,0xf48d,0xf48e,0xf48f,0xf490,0xf491,0xf492,0xf493,0xf494, -0xf495,0xf496,0xf497,0xf498,0xf499,0xf49a,0xf49b,0xf49c,0xf49d,0xf49e,0xf49f,0xf4a0,0xf540,0xf541,0xf542,0xf543, -0xf544,0xf545,0xf546,0xf547,0xf548,0xf549,0xf54a,0xf54b,0xf54c,0xf54d,0xf54e,0xf54f,0xf550,0xf551,0xf552,0xf553, -0xf554,0xf555,0xf556,0xf557,0xf558,0xf559,0xf55a,0xf55b,0xf55c,0xf55d,0xf55e,0xf55f,0xf560,0xf561,0xf562,0xf563, -0xf564,0xf565,0xf566,0xf567,0xf568,0xf569,0xf56a,0xf56b,0xf56c,0xf56d,0xf56e,0xf56f,0xf570,0xf571,0xf572,0xf573, -0xf574,0xf575,0xf576,0xf577,0xf578,0xf579,0xf57a,0xf57b,0xf57c,0xf57d,0xf57e,0xf580,0xf581,0xf582,0xf583,0xf584, -0xf585,0xf586,0xf587,0xf588,0xf589,0xf58a,0xf58b,0xf58c,0xf58d,0xf58e,0xf58f,0xf590,0xf591,0xf592,0xf593,0xf594, -0xf595,0xf596,0xf597,0xf598,0xf599,0xf59a,0xf59b,0xf59c,0xf59d,0xf59e,0xf59f,0xf5a0,0xf640,0xf641,0xf642,0xf643, -0xf644,0xf645,0xf646,0xf647,0xf648,0xf649,0xf64a,0xf64b,0xf64c,0xf64d,0xf64e,0xf64f,0xf650,0xf651,0xf652,0xf653, -0xf654,0xf655,0xf656,0xf657,0xf658,0xf659,0xf65a,0xf65b,0xf65c,0xf65d,0xf65e,0xf65f,0xf660,0xf661,0xf662,0xf663, -0xf664,0xf665,0xf666,0xf667,0xf668,0xf669,0xf66a,0xf66b,0xf66c,0xf66d,0xf66e,0xf66f,0xf670,0xf671,0xf672,0xf673, -0xf674,0xf675,0xf676,0xf677,0xf678,0xf679,0xf67a,0xf67b,0xf67c,0xf67d,0xf67e,0xf680,0xf681,0xf682,0xf683,0xf684, -0xf685,0xf686,0xf687,0xf688,0xf689,0xf68a,0xf68b,0xf68c,0xf68d,0xf68e,0xf68f,0xf690,0xf691,0xf692,0xf693,0xf694, -0xf695,0xf696,0xf697,0xf698,0xf699,0xf69a,0xf69b,0xf69c,0xf69d,0xf69e,0xf69f,0xf6a0,0xf740,0xf741,0xf742,0xf743, -0xf744,0xf745,0xf746,0xf747,0xf748,0xf749,0xf74a,0xf74b,0xf74c,0xf74d,0xf74e,0xf74f,0xf750,0xf751,0xf752,0xf753, -0xf754,0xf755,0xf756,0xf757,0xf758,0xf759,0xf75a,0xf75b,0xf75c,0xf75d,0xf75e,0xf75f,0xf760,0xf761,0xf762,0xf763, -0xf764,0xf765,0xf766,0xf767,0xf768,0xf769,0xf76a,0xf76b,0xf76c,0xf76d,0xf76e,0xf76f,0xf770,0xf771,0xf772,0xf773, -0xf774,0xf775,0xf776,0xf777,0xf778,0xf779,0xf77a,0xf77b,0xf77c,0xf77d,0xf77e,0xf780,0xd3e3,0xf781,0xf782,0xf6cf, -0xf783,0xc2b3,0xf6d0,0xf784,0xf785,0xf6d1,0xf6d2,0xf6d3,0xf6d4,0xf786,0xf787,0xf6d6,0xf788,0xb1ab,0xf6d7,0xf789, -0xf6d8,0xf6d9,0xf6da,0xf78a,0xf6db,0xf6dc,0xf78b,0xf78c,0xf78d,0xf78e,0xf6dd,0xf6de,0xcfca,0xf78f,0xf6df,0xf6e0, -0xf6e1,0xf6e2,0xf6e3,0xf6e4,0xc0f0,0xf6e5,0xf6e6,0xf6e7,0xf6e8,0xf6e9,0xf790,0xf6ea,0xf791,0xf6eb,0xf6ec,0xf792, -0xf6ed,0xf6ee,0xf6ef,0xf6f0,0xf6f1,0xf6f2,0xf6f3,0xf6f4,0xbea8,0xf793,0xf6f5,0xf6f6,0xf6f7,0xf6f8,0xf794,0xf795, -0xf796,0xf797,0xf798,0xc8fa,0xf6f9,0xf6fa,0xf6fb,0xf6fc,0xf799,0xf79a,0xf6fd,0xf6fe,0xf7a1,0xf7a2,0xf7a3,0xf7a4, -0xf7a5,0xf79b,0xf79c,0xf7a6,0xf7a7,0xf7a8,0xb1ee,0xf7a9,0xf7aa,0xf7ab,0xf79d,0xf79e,0xf7ac,0xf7ad,0xc1db,0xf7ae, -0xf79f,0xf7a0,0xf7af,0xf840,0xf841,0xf842,0xf843,0xf844,0xf845,0xf846,0xf847,0xf848,0xf849,0xf84a,0xf84b,0xf84c, -0xf84d,0xf84e,0xf84f,0xf850,0xf851,0xf852,0xf853,0xf854,0xf855,0xf856,0xf857,0xf858,0xf859,0xf85a,0xf85b,0xf85c, -0xf85d,0xf85e,0xf85f,0xf860,0xf861,0xf862,0xf863,0xf864,0xf865,0xf866,0xf867,0xf868,0xf869,0xf86a,0xf86b,0xf86c, -0xf86d,0xf86e,0xf86f,0xf870,0xf871,0xf872,0xf873,0xf874,0xf875,0xf876,0xf877,0xf878,0xf879,0xf87a,0xf87b,0xf87c, -0xf87d,0xf87e,0xf880,0xf881,0xf882,0xf883,0xf884,0xf885,0xf886,0xf887,0xf888,0xf889,0xf88a,0xf88b,0xf88c,0xf88d, -0xf88e,0xf88f,0xf890,0xf891,0xf892,0xf893,0xf894,0xf895,0xf896,0xf897,0xf898,0xf899,0xf89a,0xf89b,0xf89c,0xf89d, -0xf89e,0xf89f,0xf8a0,0xf940,0xf941,0xf942,0xf943,0xf944,0xf945,0xf946,0xf947,0xf948,0xf949,0xf94a,0xf94b,0xf94c, -0xf94d,0xf94e,0xf94f,0xf950,0xf951,0xf952,0xf953,0xf954,0xf955,0xf956,0xf957,0xf958,0xf959,0xf95a,0xf95b,0xf95c, -0xf95d,0xf95e,0xf95f,0xf960,0xf961,0xf962,0xf963,0xf964,0xf965,0xf966,0xf967,0xf968,0xf969,0xf96a,0xf96b,0xf96c, -0xf96d,0xf96e,0xf96f,0xf970,0xf971,0xf972,0xf973,0xf974,0xf975,0xf976,0xf977,0xf978,0xf979,0xf97a,0xf97b,0xf97c, -0xf97d,0xf97e,0xf980,0xf981,0xf982,0xf983,0xf984,0xf985,0xf986,0xf987,0xf988,0xf989,0xf98a,0xf98b,0xf98c,0xf98d, -0xf98e,0xf98f,0xf990,0xf991,0xf992,0xf993,0xf994,0xf995,0xf996,0xf997,0xf998,0xf999,0xf99a,0xf99b,0xf99c,0xf99d, -0xf99e,0xf99f,0xf9a0,0xfa40,0xfa41,0xfa42,0xfa43,0xfa44,0xfa45,0xfa46,0xfa47,0xfa48,0xfa49,0xfa4a,0xfa4b,0xfa4c, -0xfa4d,0xfa4e,0xfa4f,0xfa50,0xfa51,0xfa52,0xfa53,0xfa54,0xfa55,0xfa56,0xfa57,0xfa58,0xfa59,0xfa5a,0xfa5b,0xfa5c, -0xfa5d,0xfa5e,0xfa5f,0xfa60,0xfa61,0xfa62,0xfa63,0xfa64,0xfa65,0xfa66,0xfa67,0xfa68,0xfa69,0xfa6a,0xfa6b,0xfa6c, -0xfa6d,0xfa6e,0xfa6f,0xfa70,0xfa71,0xfa72,0xfa73,0xfa74,0xfa75,0xfa76,0xfa77,0xfa78,0xfa79,0xfa7a,0xfa7b,0xfa7c, -0xfa7d,0xfa7e,0xfa80,0xfa81,0xfa82,0xfa83,0xfa84,0xfa85,0xfa86,0xfa87,0xfa88,0xfa89,0xfa8a,0xfa8b,0xfa8c,0xfa8d, -0xfa8e,0xfa8f,0xfa90,0xfa91,0xfa92,0xfa93,0xfa94,0xfa95,0xfa96,0xfa97,0xfa98,0xfa99,0xfa9a,0xfa9b,0xfa9c,0xfa9d, -0xfa9e,0xfa9f,0xfaa0,0xfb40,0xfb41,0xfb42,0xfb43,0xfb44,0xfb45,0xfb46,0xfb47,0xfb48,0xfb49,0xfb4a,0xfb4b,0xfb4c, -0xfb4d,0xfb4e,0xfb4f,0xfb50,0xfb51,0xfb52,0xfb53,0xfb54,0xfb55,0xfb56,0xfb57,0xfb58,0xfb59,0xfb5a,0xfb5b,0xc4f1, -0xf0af,0xbca6,0xf0b0,0xc3f9,0xfb5c,0xc5b8,0xd1bb,0xfb5d,0xf0b1,0xf0b2,0xf0b3,0xf0b4,0xf0b5,0xd1bc,0xfb5e,0xd1ec, -0xfb5f,0xf0b7,0xf0b6,0xd4a7,0xfb60,0xcdd2,0xf0b8,0xf0ba,0xf0b9,0xf0bb,0xf0bc,0xfb61,0xfb62,0xb8eb,0xf0bd,0xbae8, -0xfb63,0xf0be,0xf0bf,0xbee9,0xf0c0,0xb6ec,0xf0c1,0xf0c2,0xf0c3,0xf0c4,0xc8b5,0xf0c5,0xf0c6,0xfb64,0xf0c7,0xc5f4, -0xfb65,0xf0c8,0xfb66,0xfb67,0xfb68,0xf0c9,0xfb69,0xf0ca,0xf7bd,0xfb6a,0xf0cb,0xf0cc,0xf0cd,0xfb6b,0xf0ce,0xfb6c, -0xfb6d,0xfb6e,0xfb6f,0xf0cf,0xbad7,0xfb70,0xf0d0,0xf0d1,0xf0d2,0xf0d3,0xf0d4,0xf0d5,0xf0d6,0xf0d8,0xfb71,0xfb72, -0xd3a5,0xf0d7,0xfb73,0xf0d9,0xfb74,0xfb75,0xfb76,0xfb77,0xfb78,0xfb79,0xfb7a,0xfb7b,0xfb7c,0xfb7d,0xf5ba,0xc2b9, -0xfb7e,0xfb80,0xf7e4,0xfb81,0xfb82,0xfb83,0xfb84,0xf7e5,0xf7e6,0xfb85,0xfb86,0xf7e7,0xfb87,0xfb88,0xfb89,0xfb8a, -0xfb8b,0xfb8c,0xf7e8,0xc2b4,0xfb8d,0xfb8e,0xfb8f,0xfb90,0xfb91,0xfb92,0xfb93,0xfb94,0xfb95,0xf7ea,0xfb96,0xf7eb, -0xfb97,0xfb98,0xfb99,0xfb9a,0xfb9b,0xfb9c,0xc2f3,0xfb9d,0xfb9e,0xfb9f,0xfba0,0xfc40,0xfc41,0xfc42,0xfc43,0xfc44, -0xfc45,0xfc46,0xfc47,0xfc48,0xf4f0,0xfc49,0xfc4a,0xfc4b,0xf4ef,0xfc4c,0xfc4d,0xc2e9,0xfc4e,0xf7e1,0xf7e2,0xfc4f, -0xfc50,0xfc51,0xfc52,0xfc53,0xbbc6,0xfc54,0xfc55,0xfc56,0xfc57,0xd9e4,0xfc58,0xfc59,0xfc5a,0xcaf2,0xc0e8,0xf0a4, -0xfc5b,0xbada,0xfc5c,0xfc5d,0xc7ad,0xfc5e,0xfc5f,0xfc60,0xc4ac,0xfc61,0xfc62,0xf7ec,0xf7ed,0xf7ee,0xfc63,0xf7f0, -0xf7ef,0xfc64,0xf7f1,0xfc65,0xfc66,0xf7f4,0xfc67,0xf7f3,0xfc68,0xf7f2,0xf7f5,0xfc69,0xfc6a,0xfc6b,0xfc6c,0xf7f6, -0xfc6d,0xfc6e,0xfc6f,0xfc70,0xfc71,0xfc72,0xfc73,0xfc74,0xfc75,0xede9,0xfc76,0xedea,0xedeb,0xfc77,0xf6bc,0xfc78, -0xfc79,0xfc7a,0xfc7b,0xfc7c,0xfc7d,0xfc7e,0xfc80,0xfc81,0xfc82,0xfc83,0xfc84,0xf6bd,0xfc85,0xf6be,0xb6a6,0xfc86, -0xd8be,0xfc87,0xfc88,0xb9c4,0xfc89,0xfc8a,0xfc8b,0xd8bb,0xfc8c,0xdcb1,0xfc8d,0xfc8e,0xfc8f,0xfc90,0xfc91,0xfc92, -0xcaf3,0xfc93,0xf7f7,0xfc94,0xfc95,0xfc96,0xfc97,0xfc98,0xfc99,0xfc9a,0xfc9b,0xfc9c,0xf7f8,0xfc9d,0xfc9e,0xf7f9, -0xfc9f,0xfca0,0xfd40,0xfd41,0xfd42,0xfd43,0xfd44,0xf7fb,0xfd45,0xf7fa,0xfd46,0xb1c7,0xfd47,0xf7fc,0xf7fd,0xfd48, -0xfd49,0xfd4a,0xfd4b,0xfd4c,0xf7fe,0xfd4d,0xfd4e,0xfd4f,0xfd50,0xfd51,0xfd52,0xfd53,0xfd54,0xfd55,0xfd56,0xfd57, -0xc6eb,0xecb4,0xfd58,0xfd59,0xfd5a,0xfd5b,0xfd5c,0xfd5d,0xfd5e,0xfd5f,0xfd60,0xfd61,0xfd62,0xfd63,0xfd64,0xfd65, -0xfd66,0xfd67,0xfd68,0xfd69,0xfd6a,0xfd6b,0xfd6c,0xfd6d,0xfd6e,0xfd6f,0xfd70,0xfd71,0xfd72,0xfd73,0xfd74,0xfd75, -0xfd76,0xfd77,0xfd78,0xfd79,0xfd7a,0xfd7b,0xfd7c,0xfd7d,0xfd7e,0xfd80,0xfd81,0xfd82,0xfd83,0xfd84,0xfd85,0xb3dd, -0xf6b3,0xfd86,0xfd87,0xf6b4,0xc1e4,0xf6b5,0xf6b6,0xf6b7,0xf6b8,0xf6b9,0xf6ba,0xc8a3,0xf6bb,0xfd88,0xfd89,0xfd8a, -0xfd8b,0xfd8c,0xfd8d,0xfd8e,0xfd8f,0xfd90,0xfd91,0xfd92,0xfd93,0xc1fa,0xb9a8,0xede8,0xfd94,0xfd95,0xfd96,0xb9ea, -0xd9df,0xfd97,0xfd98,0xfd99,0xfd9a,0xfd9b -}; - -int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen) -{ - int i = 0; - int j = 0; - int nLen; - unsigned short unicode; - unsigned short gbk; - - (void)nLen; - - for(; i < nBufInLen; i++, j++) - { - if((pszBufIn[i] & 0x80) == 0x00) // 1λ - { - nLen = 1; - pszBufOut[j]= pszBufIn[i]; - } -/* - else if((pszBufIn[i] & 0xE0) == 0xC0)// 2λ - { - nLen = 2; - unicode = (pszBufIn[i] & 0x1F << 6) | (pszBufIn[i+1]& 0x3F); - }*/ - else if ((pszBufIn[i] & 0xF0) == 0xE0) // 3λ - { - - if (i+ 2 >= nBufInLen) return -1; - unicode = (((int)(pszBufIn[i] & 0x0F)) << 12) | (((int)(pszBufIn[i+1] & 0x3F)) << 6) | (pszBufIn[i+2] & 0x3F); - gbk = mb_uni2gb_table[unicode-0x4e00]; - pszBufOut[j]= gbk/256; - pszBufOut[j+1] = gbk%256; - j++; - i+=2; - } - else - { - return -1; - } - } - *pnBufOutLen = j; - fprintf(stderr,"pnbufoutlen=%d\n",*pnBufOutLen); - return 0; -} - diff --git a/ports/quectel/core/source/utils_crc32.c b/ports/quectel/core/source/utils_crc32.c index 7e62831..3b27e08 100644 --- a/ports/quectel/core/source/utils_crc32.c +++ b/ports/quectel/core/source/utils_crc32.c @@ -25,7 +25,100 @@ #include "mperrno.h" #include "modutils.h" -extern unsigned long crc32(unsigned long, const unsigned char *, unsigned int); +typedef unsigned char Byte; /* 8 bits */ +//typedef Byte FAR Bytef; +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned int uInt; /* 32 bits or more */ +//typedef uInt FAR uLongf; + + +#define local static +#define ZEXPORT /* empty */ +unsigned int crc32_v2 (unsigned int, const unsigned char *, unsigned int); + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uInt crc_table_v2[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table_v2[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uInt ZEXPORT crc32_v2(crc, buf, len) + uInt crc; + const Byte *buf; + uInt len; +{ + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + + if (len) do { + DO1(buf); + } while (--len); + + return crc ^ 0xffffffffL; +} typedef struct _crc32_obj_t { mp_obj_base_t base; @@ -50,7 +143,7 @@ STATIC mp_obj_t crc32_update(mp_obj_t self, mp_obj_t crc32_init, mp_obj_t data) crc32_in = (unsigned long)mp_obj_get_int_truncated(crc32_init); mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); - crc32_out = crc32(crc32_in, bufinfo.buf, bufinfo.len); + crc32_out = crc32_v2(crc32_in, bufinfo.buf, bufinfo.len); return mp_obj_new_int_from_uint((int)crc32_out); } diff --git a/ports/quectel/core/umqtt.py b/ports/quectel/core/umqtt.py index e6f9afe..e2807d7 100644 --- a/ports/quectel/core/umqtt.py +++ b/ports/quectel/core/umqtt.py @@ -1,11 +1,11 @@ # 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. @@ -27,6 +27,11 @@ mqtt_log = log.getLogger("MQTT") class MQTTException(Exception): pass +def pid_gen(): + pid = 0 + while True: + pid = pid + 1 if pid < 65535 else 1 + yield pid class BaseMqtt: CONNECTEXCE = -1 @@ -45,6 +50,8 @@ class BaseMqtt: self.ssl = ssl self.ssl_params = ssl_params self.pid = 0 + self.__newpid = pid_gen() + self.__rcv_pids = set() # PUBACK and SUBACK pids awaiting ACK response self.cb = None self.user = user self.pswd = password @@ -65,10 +72,11 @@ class BaseMqtt: self.ping_outstanding = False self.pingmaxnum = pingmaxnum self.pingnum = 0 - self.mqttlock = _thread.allocate_lock() - self.mqttsendlock = _thread.allocate_lock() + self.mqttlock = None + self.mqttsendlock = None self.threadId = None - if keepalive !=0 and keepalive < 5: + self.__response_time = 5000 + if keepalive != 0 and keepalive < 5: raise ValueError("inport parameter error : keepalive >= 5S") def _send_str(self, s): @@ -97,12 +105,27 @@ class BaseMqtt: self.lw_retain = retain def connect(self, clean_session=True): - self.sock = socket.socket() - try: - addr = socket.getaddrinfo(self.server, self.port)[0][-1] - except Exception as e: - raise ValueError("DNS Parsing '{}'".format(self.server)) + if self.mqttlock is None: + self.mqttlock = _thread.allocate_lock() + if self.mqttsendlock is None: + self.mqttsendlock = _thread.allocate_lock() + j = 1 + while True: + if j > 5: + raise ValueError("DNS Parsing NULL") + try: + addrall = socket.getaddrinfo(self.server, self.port) + except Exception as e: + raise ValueError("DNS Parsing '{}'".format(self.server)) + if not addrall: + j += 1 + utime.sleep_ms(500) + continue + addr = addrall[0][-1] + break + + self.sock = socket.socket() self.sock.settimeout(20) self.sock.connect(addr) if self.ssl: @@ -128,7 +151,7 @@ class BaseMqtt: remaining_length = remaining_length + 2 + len(self.pswd) if self.lw_topic: connect_flags = connect_flags | 0x04 | ((self.lw_qos & 0x03) << 3) | ((self.lw_retain & 0x01) << 5) - remaining_length+= 2 + len(self.lw_topic) + 2 + len(self.lw_msg) + remaining_length += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) command = 0x10 packet = bytearray() @@ -139,16 +162,18 @@ class BaseMqtt: remaining_length = remaining_length // 128 if remaining_length > 0: byte = byte | 0x80 - + remaining_bytes.append(byte) packet.extend(struct.pack("!B", byte)) if remaining_length == 0: break if self.mqttversion == 3: - packet.extend(struct.pack("!H"+str(len(protocol))+"sBBH", len(protocol), protocol, 3, connect_flags, self.keepalive)) + packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 3, connect_flags, + self.keepalive)) else: - packet.extend(struct.pack("!H"+str(len(protocol))+"sBBH", len(protocol), protocol, 4, connect_flags, self.keepalive)) + packet.extend(struct.pack("!H" + str(len(protocol)) + "sBBH", len(protocol), protocol, 4, connect_flags, + self.keepalive)) if self.client_id: packet.extend(struct.pack("!H" + str(len(self.client_id)) + "s", len(self.client_id), self.client_id)) if self.lw_topic: @@ -187,6 +212,12 @@ class BaseMqtt: self.mqttsendlock.release() if self.mqttlock.locked(): self.mqttlock.release() + if self.mqttlock is not None: + _thread.delete_lock(self.mqttlock) + self.mqttlock = None + if self.mqttsendlock is not None: + _thread.delete_lock(self.mqttsendlock) + self.mqttsendlock = None # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 end except: mqtt_log.warning("Error requesting to close connection.") @@ -203,6 +234,7 @@ class BaseMqtt: def publish(self, topic, msg, retain=False, qos=0): pkt = bytearray(b"\x30\0\0\0") + pid = next(self.__newpid) pkt[0] |= qos << 1 | retain sz = 2 + len(topic) + len(msg) if qos > 0: @@ -217,40 +249,30 @@ class BaseMqtt: self.sock.write(pkt, i + 1) self._send_str(topic) if qos > 0: - self.pid += 1 - pid = self.pid + self.__rcv_pids.add(pid) struct.pack_into("!H", pkt, 0, pid) self.sock.write(pkt, 2) self.sock.write(msg) - #self.last_time = utime.mktime(utime.localtime()) - if qos == 1: - while 1: - op = self.wait_msg() - if op == 0x40: - sz = self.sock.read(1) - assert sz == b"\x02" - rcv_pid = self.sock.read(2) - rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] - if pid == rcv_pid: - return + # self.last_time = utime.mktime(utime.localtime()) + if qos == 0: + return + if not self._await_pid(pid): + mqtt_log.warning("publish QOS1 message was not received correctly") elif qos == 2: assert 0 def __subscribe(self, topic, qos): pkt = bytearray(b"\x82\0\0\0") self.pid += 1 + # self.__rcv_pids.add(pid) struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid) self.sock.write(pkt) self._send_str(topic) self.sock.write(qos.to_bytes(1, "little")) if self.ssl == False: self.sock.settimeout(5) - time = utime.mktime(utime.localtime()) while 1: op = self.wait_msg() - time_new = utime.mktime(utime.localtime()) - if time_new - time: - raise ValueError("subscribe timeout") if op == 0x90: resp = self.sock.read(4) # print(resp) @@ -260,8 +282,9 @@ class BaseMqtt: if self.ssl == False: self.sock.setblocking(True) return - elif op & 0xf0 == 0x30 or op == b"\xd0": - continue + elif op is not None: + if op & 0xf0 == 0x30 or op == b"\xd0": + continue else: break @@ -288,12 +311,27 @@ class BaseMqtt: # raise OSError(-1) # Pawn 2020/11/14 - WFZT mqttBUg -1 return None + if res == b"\xd0": # PINGRESP self.ping_outstanding = False sz = self.sock.read(1)[0] assert sz == 0 return res + if res == b'\x40': # PUBACK: save pid + sz = self.sock.read(1) + if sz != b"\x02": + mqtt_log.warning("Publish message does not return ACK correctly") + return + rcv_pid = self.sock.read(2) + pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid in self.__rcv_pids: + self.__rcv_pids.discard(pid) + return + else: + mqtt_log.warning("Publish message does not return ACK correctly") + return + op = res[0] if op & 0xf0 != 0x30: return op @@ -314,7 +352,7 @@ class BaseMqtt: struct.pack_into("!H", pkt, 2, pid) self.sock.write(pkt) return op - elif op & 6 == 4: + if op & 6 == 4: assert 0 # Checks whether a pending message from server is available. @@ -324,6 +362,19 @@ class BaseMqtt: self.sock.setblocking(False) return self.wait_msg() + def _timeout(self, t): + return utime.ticks_diff(utime.ticks_ms(), t) > self.__response_time + + def _await_pid(self, pid): + t = utime.ticks_ms() + while pid in self.__rcv_pids: # local copy + if self._timeout(t): + break # Must repub or bail out + utime.sleep_ms(1000) + else: + return True # PID received. All done. + return False + def get_mqttsta(self): ''' Get the MQTT connection status @@ -344,9 +395,11 @@ class BaseMqtt: else: return self.CONNECTEXCE + class MQTTClient(BaseMqtt): DELAY = 2 DEBUG = False + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.error_callback = None @@ -367,6 +420,10 @@ class MQTTClient(BaseMqtt): self.mqttsendlock.release() _thread.stop_thread(self.threadId) self.threadId = None + if self.reconn: + if self.error_callback is not None: + e = "reconnect_start" + self.error_callback(e)#start reconnect while 1: try: self.sock.close() @@ -379,13 +436,17 @@ class MQTTClient(BaseMqtt): "[%s] The network condition has been restored and an attempt will be made to reconnect" % time_info) self.pingFlag = False self.connect(self.clean_session) - if self.mqttlock.locked(): - self.mqttlock.release() mqtt_log.info("[%s] Reconnection successful!" % time_info) if self.topic_list: for topic_re in self.topic_list: super().subscribe(topic_re, self.qos) time_info = self.logTime() + if self.mqttlock.locked(): + self.mqttlock.release() + if self.reconn: + if self.error_callback is not None: + e = "reconnect_success" + self.error_callback(e)#reconnect success return else: time_info = self.logTime() @@ -401,8 +462,8 @@ class MQTTClient(BaseMqtt): i += 1 time_info = self.logTime() mqtt_log.warning( - "[%s] The connection attempt failed and will be tried again after %d seconds." % (time_info, 5+i)) - utime.sleep(5+i) + "[%s] The connection attempt failed and will be tried again after %d seconds." % (time_info, 5 + i)) + utime.sleep(5 + i) def publish(self, topic, msg, retain=False, qos=0): while True: @@ -445,16 +506,19 @@ class MQTTClient(BaseMqtt): super().connect(clean_session) except Exception as e: if str(e) == "104": - raise ValueError("MQTT Connect Error='{}' Server Actively RST Disconnected.Need Check addr&port".format(e)) + raise ValueError( + "MQTT Connect Error='{}' Server Actively RST Disconnected.Need Check addr&port".format(e)) elif str(e) == "107" or str(e) == "4": - raise ValueError("MQTT Connect Error='{}' Server Actively FIN Disconnected.Need Check Connection parameters".format(e)) + raise ValueError( + "MQTT Connect Error='{}' Server Actively FIN Disconnected.Need Check Connection parameters".format( + e)) elif str(e) == "110": raise ValueError("MQTT Connect Error='{}' Timeout.Need Check Network".format(e)) raise ValueError("MQTT Connect error='{}' FAIL".format(e)) if self.keepalive > 0 and not self.pingFlag: # Pawn.zhou 2021/1/12 for JIRA STASR3601-2523 begin - task_stacksize =_thread.stack_size() - _thread.stack_size(16*1024) + task_stacksize = _thread.stack_size() + _thread.stack_size(16 * 1024) self.threadId = _thread.start_new_thread(self.__loop_forever, ()) _thread.stack_size(task_stacksize) self.pingFlag = True @@ -466,10 +530,10 @@ class MQTTClient(BaseMqtt): def __loop_forever(self): while True: if self.keepalive >= 5: - keepalive = self.keepalive - 3 + keepalive = self.keepalive - 3 try: if not self.timerFlag: - if self.mqttsendlock.locked(): + if self.mqttsendlock is not None and self.mqttsendlock.locked(): self.mqttsendlock.release() self.threadId = None break @@ -481,24 +545,24 @@ class MQTTClient(BaseMqtt): if self.ping_outstanding == True: mqtt_log.warning("[%s] Send ping timeout. Trying to reconnect" % time) if not self.reconn: - if self.mqttsendlock.locked(): + if self.mqttsendlock is not None and self.mqttsendlock.locked(): self.mqttsendlock.release() self.threadId = None raise Exception("Send ping timeout.") else: if self.pingnum <= 0: - mqtt_log.warning("[%s] Send ping timeout. Trying to reconnect" % time) + mqtt_log.warning("[%s] Send ping timeout. Trying to reconnect" % time) self.sock.settimeout(3) self.pingFlag = False - if self.mqttsendlock.locked(): + if self.mqttsendlock is not None and self.mqttsendlock.locked(): self.mqttsendlock.release() self.threadId = None break else: - mqtt_log.warning("[%s] Trying to resend ping(%d)" % (time,self.pingnum)) + mqtt_log.warning("[%s] Trying to resend ping(%d)" % (time, self.pingnum)) self.pingnum = self.pingnum - 1 while True: - if self.mqttsendlock.locked(): + if self.mqttsendlock is not None and self.mqttsendlock.locked(): utime.sleep_ms(10) continue self.mqttsendlock.acquire() @@ -509,7 +573,7 @@ class MQTTClient(BaseMqtt): utime.sleep(5) continue except Exception as e: - if self.mqttsendlock.locked(): + if self.mqttsendlock is not None and self.mqttsendlock.locked(): self.mqttsendlock.release() if not self.timerFlag: self.threadId = None diff --git a/py/modthread.c b/py/modthread.c index 641a96c..5850b32 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -55,7 +55,7 @@ typedef struct _mp_obj_thread_lock_t { } mp_obj_thread_lock_t; STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) { - mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t); + mp_obj_thread_lock_t *self = m_new_obj_with_finaliser(mp_obj_thread_lock_t); self->base.type = &mp_type_thread_lock; mp_thread_mutex_init(&self->mutex); self->locked = false; @@ -108,7 +108,26 @@ STATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__); +//Added by Freddy@20210818 Allows an application to delete a lock, or the lock is deleted when GC reclaims resources +STATIC mp_obj_t mod_thread_delete_lock(mp_obj_t args_in) { + const mp_obj_type_t *type = mp_obj_get_type(args_in); + if(type->name != MP_QSTR_lock) + { + mp_raise_msg(&mp_type_TypeError, MP_ERROR_TEXT("The argument isn't a lock.")); + } + + mp_obj_thread_lock_t *lock = MP_OBJ_TO_PTR(args_in); + if((mp_thread_mutex_t)NULL != lock->mutex) { + mp_thread_mutex_del(&lock->mutex); + lock->locked = false; + lock->mutex = (mp_thread_mutex_t)NULL; + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_delete_lock_obj, mod_thread_delete_lock); + STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_thread_delete_lock_obj) }, { MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) }, { MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) }, { MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) }, @@ -137,6 +156,10 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { if (n_args != 0) { int stack_size = mp_obj_get_int(args[0]); + if (stack_size < 0) + { + return mp_obj_new_int(-1); + } if((stack_size * sizeof(uint32_t)) < MP_THREAD_MIN_STACK_SIZE) { return mp_obj_new_int(-1); @@ -271,7 +294,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) // spawn the thread! int thread_id = mp_thread_create(thread_entry, th_args, &th_args->stack_size); - return mp_obj_new_int(thread_id); + return mp_obj_new_int_from_uint((unsigned int)thread_id); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread); @@ -298,7 +321,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_heap_size_obj, mod_thread_get_he STATIC mp_obj_t mod_thread_stop_thread(mp_obj_t thread_id) { Helios_Thread_t curr_id = Helios_Thread_GetID(); - int th_id = mp_obj_get_int(thread_id); + int th_id = (int)mp_obj_get_int_truncated(thread_id); extern Helios_Thread_t ql_micropython_task_ref; @@ -348,6 +371,7 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) }, { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) }, { MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) }, + { MP_ROM_QSTR(MP_QSTR_delete_lock), MP_ROM_PTR(&mod_thread_delete_lock_obj) }, { MP_ROM_QSTR(MP_QSTR_get_heap_size), MP_ROM_PTR(&mod_thread_get_heap_size_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_thread), MP_ROM_PTR(&mod_thread_stop_thread_obj) }, }; diff --git a/py/obj.h b/py/obj.h index c082e9f..c40e3bc 100644 --- a/py/obj.h +++ b/py/obj.h @@ -46,6 +46,15 @@ typedef void *mp_obj_t; typedef const void *mp_const_obj_t; #endif + +typedef struct _c_callback_t { + bool is_method; + mp_obj_t method_self; + qstr method_name; + mp_obj_t cb; +}c_callback_t; + + // This mp_obj_type_t struct is a concrete MicroPython object which holds info // about a type. See below for actual definition of the struct. typedef struct _mp_obj_type_t mp_obj_type_t; diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 3319544..4df14a2 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -108,6 +108,22 @@ STATIC const mp_obj_type_t mp_type_bound_meth = { #endif }; +mp_obj_t mp_obj_bound_get_self(void *bound) +{ + if(NULL == bound) + return NULL; + + return ((mp_obj_bound_meth_t *)bound)->self; +} + +mp_obj_t mp_obj_bound_get_meth(void *bound) +{ + if(NULL == bound) + return NULL; + + return ((mp_obj_bound_meth_t *)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/objmodule.c b/py/objmodule.c index e2a204b..63782c2 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -33,6 +33,7 @@ #include "py/objmodule.h" #include "py/runtime.h" #include "py/builtin.h" +#include "mphalport.h" #include "genhdr/moduledefs.h" @@ -282,6 +283,27 @@ mp_obj_t mp_module_search_umodule(const char *module_str) { } #endif +//When the VM restarts, find all builtin modules that contain the qpy_module_deinit method and execute it. +void mp_module_deinit_all(void) +{ + mp_obj_t dest[2]; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + for(size_t i = 0;i < MP_ARRAY_SIZE(mp_builtin_module_table); i++) + { + mp_load_method_maybe(MP_OBJ_FROM_PTR(mp_builtin_module_table[i].value), MP_QSTR___qpy_module_deinit__, dest); + if (dest[0] != MP_OBJ_NULL) { + mp_call_function_0(dest[0]); + } + } + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + mp_printf(&mp_plat_print, "MPY: Modules deinit fail\r\n"); + } + +} + #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { // Look for __init__ and call it if it exists diff --git a/py/objmodule.h b/py/objmodule.h index 5140f6f..8be2851 100644 --- a/py/objmodule.h +++ b/py/objmodule.h @@ -36,6 +36,8 @@ void mp_module_register(qstr qstr, mp_obj_t module); mp_obj_t mp_module_search_umodule(const char *module_str); +void mp_module_deinit_all(void); + #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj); #else diff --git a/py/profile.c b/py/profile.c index 76b24fd..632b6a8 100644 --- a/py/profile.c +++ b/py/profile.c @@ -28,6 +28,7 @@ #include "py/profile.h" #include "py/bc0.h" #include "py/gc.h" +#include "lib/utils/interrupt_char.h" #if MICROPY_PY_SYS_SETTRACE @@ -299,9 +300,11 @@ 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) { + CHECK_MAINPY_KBD_INTERRUPT_ENTER() mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); + CHECK_MAINPY_KBD_INTERRUPT_EXIT() } return top; } diff --git a/py/runtime.h b/py/runtime.h index a8ffc46..9a84552 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -74,6 +74,9 @@ void mp_sched_lock(void); void mp_sched_unlock(void); #define mp_sched_num_pending() (MP_STATE_VM(sched_len)) bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg); +bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg); +bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj); + #endif // extra printing method specifically for mp_obj_t's which are integral type diff --git a/py/scheduler.c b/py/scheduler.c index 6536094..02e8b7e 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -26,11 +26,11 @@ */ #include +#include #include "py/runtime.h" -#if !defined(PLAT_RDA) #include "mphalport.h" -#endif + #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) { @@ -67,6 +67,7 @@ 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) { + CHECK_MAINPY_KBD_INTERRUPT_ENTER() MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; if (!mp_sched_num_pending()) { MP_STATE_VM(sched_state) = MP_SCHED_IDLE; @@ -75,6 +76,7 @@ void mp_handle_pending(bool raise_exc) { MICROPY_END_ATOMIC_SECTION(atomic_state); nlr_raise(obj); } + CHECK_MAINPY_KBD_INTERRUPT_EXIT() } mp_handle_pending_tail(atomic_state); } else { @@ -140,7 +142,7 @@ 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) +#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 @@ -153,6 +155,58 @@ bool MICROPY_WRAP_MP_SCHED_SCHEDULE(mp_sched_schedule)(mp_obj_t function, mp_obj return ret; } +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, +//load it first so that the recorded callback is not collected by the GC +bool mp_sched_schedule_ex(c_callback_t *callback, mp_obj_t arg) +{ + if(NULL == callback) + { + return false; + } + + if((false == callback->is_method) && mp_obj_is_callable(callback->cb))//function + { + return mp_sched_schedule(callback->cb, 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); + } + else + { + return false; + } +} + +//Register callback +bool mp_sched_schedule_callback_register(c_callback_t *callback, mp_obj_t func_obj) +{ + if(NULL == callback) { + return false; + } + memset(callback, 0 , sizeof(c_callback_t)); + if(mp_const_none != func_obj) + { + const mp_obj_type_t *type = mp_obj_get_type(func_obj); + if(type->name == MP_QSTR_bound_method)//is bound_meth. Records the object for this method, along with the bytecode for the name of this method + { + callback->is_method = true; + callback->method_self = mp_obj_bound_get_self(func_obj); + callback->method_name = mp_obj_fun_get_name(mp_obj_bound_get_meth(func_obj)); + callback->cb = func_obj; + return true; + } + } + + callback->is_method = false; + callback->cb = func_obj; + + return true; +} + #else // MICROPY_ENABLE_SCHEDULER // A variant of this is inlined in the VM at the pending exception check diff --git a/py/vm.c b/py/vm.c index e341d79..1df0699 100644 --- a/py/vm.c +++ b/py/vm.c @@ -36,6 +36,7 @@ #include "py/bc0.h" #include "py/bc.h" #include "py/profile.h" +#include "lib/utils/interrupt_char.h" // *FORMAT-OFF* @@ -1373,12 +1374,14 @@ pending_exception_check: MARK_EXC_IP_SELECTIVE(); mp_obj_t obj = MP_STATE_VM(mp_pending_exception); if (obj != MP_OBJ_NULL) { + CHECK_MAINPY_KBD_INTERRUPT_ENTER() 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); + CHECK_MAINPY_KBD_INTERRUPT_EXIT() } mp_handle_pending_tail(atomic_state); } else { @@ -1388,10 +1391,12 @@ pending_exception_check: #else // This is an inlined variant of mp_handle_pending if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { + CHECK_MAINPY_KBD_INTERRUPT_ENTER() 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); + CHECK_MAINPY_KBD_INTERRUPT_EXIT() } #endif -- Gitee