0911添加W9代码,增加fd230,w9编译选项
authorpenglei <1624952103@qq.com>
Sat, 7 Jun 2025 08:13:36 +0000 (16:13 +0800)
committerpenglei <1624952103@qq.com>
Sat, 7 Jun 2025 08:13:36 +0000 (16:13 +0800)
242 files changed:
autobuild.sh
code/sdk/application/brandy/brandy_standard/chip_init.c
code/sdk/application/brandy/brandy_standard/thread_pri_init.c
code/sdk/application/wearable/fd230app/CMakeLists.txt
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testGPS.h [new file with mode: 0644]
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testhrsenson.h
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testGPS.cpp [new file with mode: 0644]
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testPresenter.cpp
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testcat1.cpp
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testhrsenson.cpp
code/sdk/application/wearable/service/ble_service/blemoder/CMakeLists.txt
code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c
code/sdk/application/wearable/service/msg_center/brandy-native-js-fd230/libmsg_center.a
code/sdk/application/wearable/service/msg_center/brandy-native-js-w9/libmsg_center.a [new file with mode: 0644]
code/sdk/application/wearable/service/msg_center/src/msg_center_customer.cpp
code/sdk/application/wstp/at_service/app/app_at_process.c
code/sdk/bootloader/flashboot/brandy/main.c
code/sdk/bootloader/flashboot/brandy/nandflash/CMakeLists.txt
code/sdk/bootloader/flashboot/brandy/nandflash/include/nandflash_f35uqa001g.h [new file with mode: 0644]
code/sdk/bootloader/flashboot/brandy/nandflash/nandflash_config.c
code/sdk/bootloader/flashboot/brandy/nandflash/nandflash_f35uqa001g.c [new file with mode: 0644]
code/sdk/build/config/target_config/brandy/config.py
code/sdk/drivers/boards/brandy_evb/board_config/board_evb.h
code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h [new file with mode: 0644]
code/sdk/drivers/boards/brandy_evb/product/product_evb4_standard.h
code/sdk/drivers/chips/brandy/include/platform_core.h
code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c
code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c
code/sdk/drivers/drivers/driver/nand_flash/CMakeLists.txt
code/sdk/drivers/drivers/driver/nand_flash/nand/include/nandflash_f35uqa001g.h [new file with mode: 0644]
code/sdk/drivers/drivers/driver/nand_flash/nand/nandflash_config.c
code/sdk/drivers/drivers/driver/nand_flash/nand/nandflash_f35uqa001g.c [new file with mode: 0644]
code/sdk/drivers/peripheral/CMakeLists.txt
code/sdk/drivers/peripheral/gnss/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/controller/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller_helper.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_device_info.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware_utils.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/list/tiot_list.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/common/utils/tiot_types.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/Makefile [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg.bin [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg_h7s1.bin [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/gnss_board_port.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_log_port.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_misc_port.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_pin_port.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_uart_port.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/readme.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_autoconfig.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_defconfig [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/inc/NMEA0183.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/inc/gnss_ctl.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/inc/uart_gnss.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/agnss_sample/gnss_datatypes.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/gnss_sample/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/NMEA0183.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/decodenmea.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/gnss_config_array.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/nmealist.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gnss/src/uart_gnss.c [new file with mode: 0644]
code/sdk/drivers/peripheral/lcd/lcd_config.c
code/sdk/drivers/peripheral/lcd/lcd_private.c
code/sdk/drivers/peripheral/ppg/CMakeLists.txt
code/sdk/drivers/peripheral/ppg/hal/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/hx3695/hx3695.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695.h
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_check_touch.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_factory_test.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_factory_test.h
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.h
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hrs_agc.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hrs_custom.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hrv_agc.c
code/sdk/drivers/peripheral/ppg/hx3695/hx3695_spo2_agc.c
code/sdk/drivers/peripheral/ppg/pah8009/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/Interrupt_function.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/libv307009_4.a [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pah8009_testpattern_HRD.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxialg.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxivar.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/test_library_HRD.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/libv703_0_1.a [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pah8009_testpattern_SPO2.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pxialg_spo2.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/test_library_SPO2.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_stress/V6033/pxialg_hrv.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/factory/pah8009_factory_reg.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_unit.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/service/ppg_service.cpp
code/sdk/drivers/peripheral/ppg/service/ppg_service.h
code/sdk/drivers/peripheral/rotary_encoder/CMakeLists.txt
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.c
code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.h
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h [new file with mode: 0644]
code/sdk/drivers/peripheral/rotary_encoder/rotary_encoder_drv.c
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.h
code/sdk/drivers/peripheral/touch/CMakeLists.txt
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.c [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.h [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.c [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.h [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.c [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.h [new file with mode: 0644]
code/sdk/drivers/peripheral/touch/touch_screen_drv.c
code/sdk/drivers/peripheral/utils/custom_utils.c
code/sdk/drivers/peripheral/utils/custom_utils.h
code/sdk/drivers/peripheral/utils/custom_utils_at_cmd.c
code/sdk/middleware/chips/brandy/pm/service/pm_sleep.c
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230-r/libgfx_rm.a [new file with mode: 0644]
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230/libgfx_rm.a
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9-r/libgfx_rm.a [new file with mode: 0644]
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9/libgfx_rm.a [new file with mode: 0644]
code/sdk/middleware/services/gui/hal/display/brandy-native-js-fd230/libdisplay_gfx.a
code/sdk/middleware/services/gui/hal/display/brandy-native-js-w9/libdisplay_gfx.a [new file with mode: 0644]
code/sdk/middleware/services/gui/uikit/brandy-native-js-fd230/libuikit_ext.a
code/sdk/middleware/services/gui/uikit/brandy-native-js-w9/libuikit_ext.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230-r/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230/libx_vfs_private.a
code/sdk/middleware/utils/fs/vfs/brandy-native-js-r-w9/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9-r/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230-r/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230/libfs_yaffs2.a
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r-w9/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9-r/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-fd230/libams.a
code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-w9/libams.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-fd230/libace.a
code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-w9/libace.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-fd230/libbms.a
code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-w9/libbms.a [new file with mode: 0644]
code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-fd230/libjerryscript.a
code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-w9/libjerryscript.a [new file with mode: 0644]
code/sdk/tools/pkg/chip_packet/brandy/packet.py
tools/scripts/create_project.sh

index 2c364bb..ca66f94 100755 (executable)
@@ -112,6 +112,23 @@ APPLICATION_NAME=brandy-native-js-4part
 RECOVERY_NAME=brandy-native-js-r-4part
 BUILD_NAME=_4PART
 fi
+
+if [ "$1" == "w9" ]
+then
+TARGET_PACK_NAME=pack_brandy_native_js_w9
+APPLICATION_NAME=brandy-native-js-w9
+RECOVERY_NAME=brandy-native-js-w9-r
+DEFAULT_SSB_NAME=brandy-native-js-w9-ssb
+BUILD_NAME=_W9
+fi
+
+if [ "$1" == "fd230" ]
+then
+TARGET_PACK_NAME=pack_brandy_native_js_fd230
+APPLICATION_NAME=brandy-native-js-fd230
+BUILD_NAME=_FD230
+fi
+
 if [ "$1" == "leakcheck" ]
 then
 TARGET_PACK_NAME=pack_brandy_native_js_leakcheck
index 33b53e7..59abf9d 100755 (executable)
@@ -36,8 +36,9 @@
 #define XIP_CACHE_WRITE_DATA_DELAY_INTR_MASK    0x8\r
 #define XIP_CACHE_ENABLE_WRITE_INTR_MASK        0x1\r
 #define XIP_CACHE_2AHBM_INTR_MASK               0x2\r
+#ifdef BOARD_FD230\r
 #define ENABLE_CHARGE_BY_DEFAULT\r
-\r
+#endif\r
 #if ENABLE_LOW_POWER == YES\r
 extern uint32_t __sys_pm_start__;\r
 extern uint32_t __sys_pm_load__;\r
index 2fb86b3..6700e7a 100755 (executable)
@@ -35,6 +35,8 @@
 #include "ztw523_touch1.h"\r
 #elif defined(TPTYPE_FT6X46)\r
 #include "ft6x46_touch1.h"\r
+#elif defined(TPTYPE_CST86XX)\r
+#include "cst86xx_touch1.h"\r
 #else\r
 #include "ztw523_touch1.h"\r
 #endif\r
@@ -83,7 +85,7 @@
 #include "acc_service.h"\r
 #endif\r
 \r
-#ifdef ENABLE_CYWEE\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
 #include "cywee_service.h"\r
 #endif\r
 \r
 #include "service/a5133_service.h"\r
 #endif\r
 \r
+#ifdef ROTARYENCODER_MIXO\r
+#include "mixo_service.h"\r
+#endif\r
+\r
 #define EMMC_BASE_ADDR              0x52062000\r
 #define TASK_PRIORITY_APP           (osPriority_t)(17)\r
 #define TICK_TEN_MS                 (10U)\r
@@ -138,6 +144,8 @@ static void sample_gfx_init(void)
     ztw523_host_init_sample();\r
 #elif defined(TPTYPE_FT6X46)\r
     ft6x46_host_init_sample();\r
+#elif defined(TPTYPE_CST86XX)\r
+    cst86xx_host_init_sample();\r
 #else\r
     ztw523_host_init_sample();\r
 #endif\r
@@ -495,25 +503,24 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
     uapi_Ai_send_service_init();\r
     \r
 #ifdef ENABLE_CUSTOM_I2C\r
-    errcode_t result = custom_iic_init();\r
-    if(result != SUCC)\r
-        PRINT("custom_iic_init failed !!! \r\n");\r
-    else\r
-    {\r
-        PRINT("custom_iic_init succed !!! \r\n");\r
-        #ifdef MAG_MMC5603\r
-            uapi_mag_service_init();\r
-        #endif\r
 \r
-        #ifdef SUPPORT_PPG_SERVICE\r
-            uapi_ppg_service_init();\r
-        #endif\r
+    custom_iic_init();\r
 \r
-        #ifdef ENABLE_CYWEE\r
-            uapi_cywee_service_init();\r
-        #endif \r
+    #ifdef MAG_MMC5603\r
+        uapi_mag_service_init();\r
+    #endif\r
 \r
-    }\r
+    #ifdef SUPPORT_PPG_SERVICE\r
+        uapi_ppg_service_init();\r
+    #endif\r
+\r
+    #ifdef SUPPORT_CYWEE_SERVICE\r
+        uapi_cywee_service_init();\r
+    #endif \r
+\r
+    #ifdef ROTARYENCODER_MIXO\r
+        uapi_mixo_service_init();\r
+    #endif\r
 #endif\r
 \r
     /*启动蓝牙ble服务,cywee有重置 mac地址的操作,会需要把 蓝牙服务开启放在cywee服务之后*/\r
@@ -533,6 +540,10 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
     uapi_pin_set_ie(S_MGPIO34, HAL_PIO_IE_ENBALE);\r
 #endif\r
 \r
+#ifdef SUPPORT_GNSS_SERVICE\r
+    gnss_uart_init();\r
+#endif\r
+\r
 #ifdef SUPPORT_AT_OHOSFWK\r
     //开始播放开机动画,并启动ohos系统\r
     ohos_startup();\r
index 94660bd..ad9a292 100644 (file)
@@ -797,6 +797,7 @@ set(SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/producttest/src/testSEChipTest.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/producttest/src/testModel.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/producttest/src/testPing.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/producttest/src/testGPS.cpp
     
     #每日目标
     ${CMAKE_CURRENT_SOURCE_DIR}/nativeui/goal/src/goalmodel.cpp
diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testGPS.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testGPS.h
new file mode 100644 (file)
index 0000000..382013c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-06-06 15:56:46
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-06 15:57:04
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testGPS.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#ifndef TEST_GPS__VIEW_H
+#define TEST_GPS__VIEW_H
+
+#include "BaseView.h"
+#include "View.h"
+#include "components/ui_scroll_view.h"
+#include "components/ui_label.h"
+#include "components/ui_label_ext.h"
+#include "components/ui_button.h"
+#include "components/ui_image_view.h"
+#include "components/ui_label_button_ext.h"
+
+//#include "cmsis_os.h"
+#include <iostream>
+namespace OHOS
+{
+    #define GPS_CLOSE_CANCEL_BUTTON "gps_close"
+    #define GPS_OPEN_CONFIRM_BUTTON "gps_open"
+
+    class testGPSView
+    {
+
+    public:
+       struct ButtonConfig_ext_t
+        {
+            int x;
+            int y;
+            int w;
+            int h;
+            const char *str;
+            const char *ViewId;
+            const char *ImageSrc;
+
+            //label
+            int label_x;
+            int label_y;
+            uint8_t ALIGN;
+            int  Fontsize;
+        
+        };
+
+
+        
+        struct LabelConfig
+        {
+            int16_t left;
+            int16_t top;
+            int16_t width;
+            int16_t height;
+            int16_t fontSize;      // 字体大小
+            int16_t lineHeigh;     // 行高
+            char *text;      // 文本
+            uint8_t lineBreakMode; // 断行模式。
+        };
+
+
+       
+        
+        testGPSView();
+        virtual ~testGPSView();
+        static testGPSView *GetInstance(void);
+   
+        UIScrollView *testGPSInitIView(uint8_t);
+        void  gpsdataTimerCallBack(void);
+
+        void ClearAll(void);
+    private:
+        UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
+        UILabel *InitLabel(LabelConfig &labelConfig);
+        bool testGPSScrollViewcrollViewinit(uint8_t);
+        UIScrollView *testGPSScrollView{nullptr};
+        UILabel *label_1_GPS_MSG=NULL;
+        UILabel *label_1_GPS_on_or_off{nullptr};
+        UILabelButtonExt*  GPSbutton[2]{nullptr};
+
+        UILabelButtonExt* labelButton_next = nullptr;
+        bool initViewStatus{false};
+        UILabel *Title{nullptr};           // 标题
+
+    };
+}
+#endif
\ No newline at end of file
index 23af1b8..6f05b73 100644 (file)
@@ -2,8 +2,8 @@
  * @Author: penglei 1624952103@qq.com\r
  * @Date: 2024-08-23 10:50:37\r
  * @LastEditors: penglei 1624952103@qq.com\r
- * @LastEditTime: 2024-11-05 14:34:43\r
- * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h\r
+ * @LastEditTime: 2025-06-06 15:56:14\r
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230/nativeapp/nativeui/producttest/include/testPresenter.h\r
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
  */\r
 \r
@@ -34,10 +34,12 @@ namespace OHOS
         TP,\r
         MAGETIC,\r
         LUMINANCE,\r
-        CHAR,\r
+        CHARG,\r
         SPEAK,\r
         MOTOR,\r
+#ifdef SUPPORT_CAT1_SERVICE\r
         CAT1,\r
+#endif\r
         BUTTON,\r
         MICROPHONE,\r
         HRSENSON,\r
@@ -45,6 +47,15 @@ namespace OHOS
         BTTEST,\r
         SEChipTest,\r
         PingTest,\r
+#ifdef SUPPORT_GNSS\r
+        GPSTEST,\r
+#endif\r
+#ifdef ENABLE_LQBP002TA\r
+        PRESSURETEST,\r
+#endif\r
+#ifdef ENABLE_GYRO\r
+        GYROTEST,\r
+#endif\r
         OLDTEST,\r
         DEEPSLEEP,\r
         \r
index 73ac334..99c8777 100644 (file)
 #include "producttest/include/testbt.h"\r
 #include "producttest/include/testSEChipTest.h"\r
 #include "producttest/include/testPing.h"\r
+#include "producttest/include/testGPS.h"\r
 #ifdef SUPPORT_A5133_SERVICE\r
 #include "producttest/include/testA5133.h"\r
 #endif\r
+\r
 namespace OHOS\r
 {\r
     \r
@@ -96,6 +98,7 @@ namespace OHOS
         bool ChangeBTTESTView(int16_t thisView);\r
         bool ChangeSEChipTESTView(int16_t thisView);\r
         bool ChangePingTESTView(int16_t thisView);\r
+        bool ChangeGPSTESTView(int16_t thisView);\r
     #ifdef SUPPORT_A5133_SERVICE\r
         bool ChangeA5133TESTView(int16_t thisView);\r
     #endif\r
@@ -135,6 +138,7 @@ namespace OHOS
 \r
         testSEChipView *test_SEChip_view{nullptr};\r
         testPingView *test_Ping_view{nullptr};\r
+        testGPSView *test_GPS_view{nullptr};\r
         \r
     #ifdef SUPPORT_A5133_SERVICE\r
         testA5133View  *test_A5133_view{nullptr};\r
index 7acd8d1..80e351d 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-03 19:08:26
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-05 15:51:17
+ * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testhrsenson.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
 #ifndef TEST_HRSENSON_VIEW_H
 #define TEST_HRSENSON_VIEW_H
 
@@ -77,11 +85,11 @@ namespace OHOS
         UIScrollView *testhrsensonInitIView(uint8_t);
         void ClearAll(void);
         void setgrayvalue(int,int,int);
-        void setlightvalue(int g,int r,int ir);
+        void setlightvalue(void);
     private:
         UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
         UILabel *InitLabel(LabelConfig &labelConfig);
-        bool tesScat1ScrollViewcrollViewinit(uint8_t);
+        bool testhrsensonScrollViewcrollViewinit(uint8_t);
         UIScrollView *testhrsensonScrollView{nullptr};
         UILabel *label_1_cat1msg_1=NULL;
         // UILabel *label_1_cat1msg_oper{nullptr};
diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testGPS.cpp b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testGPS.cpp
new file mode 100644 (file)
index 0000000..4341286
--- /dev/null
@@ -0,0 +1,295 @@
+#include "wearable_log.h"
+#include "custom_utils.h"
+#include "producttest/include/testPresenter.h"
+// #include "producttest/include/testcat1.h" 
+#include "AlarmClockModel.h"
+#include "cmsis_os2.h"
+        
+#if defined(SUPPORT_GNSS)
+
+#include "NMEA0183.h"
+// code/sdk/zhihui/services/gnss/inc/.h
+
+#include "producttest/include/testView.h"
+#include "producttest/include/testGPS.h"
+#include "gnss_sample.h"
+#include "graphic_service.h"
+namespace OHOS
+{
+
+    static testGPSView *g_pSystemAboutTheWatchView{nullptr};
+
+    testGPSView::testGPSView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemAboutTheWatchView::SystemAboutTheWatchView");
+        g_pSystemAboutTheWatchView = this;
+    }
+
+    testGPSView::~testGPSView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "testGPSView::~testGPSView");
+        ClearAll();
+        //g_pSystemAboutTheWatchView = nullptr;
+    }
+
+    testGPSView *testGPSView::GetInstance()
+    {
+
+        return g_pSystemAboutTheWatchView;
+    }
+    static osTimerId_t  GPS_TEST_timer=NULL;
+
+    void testGPSView::ClearAll()
+    {
+        if(testGPSScrollView)
+        {
+            testGPSScrollView->RemoveAll();
+
+            if (GPS_TEST_timer != NULL) {
+                osTimerStop(GPS_TEST_timer);
+                osTimerDelete(GPS_TEST_timer);
+                GPS_TEST_timer = NULL;
+            }
+            if(labelButton_next)
+            {
+                delete labelButton_next;
+                labelButton_next=nullptr;
+            }
+            if(label_1_GPS_MSG)
+            {
+                delete label_1_GPS_MSG;
+                label_1_GPS_MSG=nullptr;
+            }
+
+            if(label_1_GPS_on_or_off)
+            {
+                delete label_1_GPS_on_or_off;
+                label_1_GPS_on_or_off=nullptr;
+            }
+
+            if(Title)
+            {
+                delete Title;
+                Title=nullptr;
+            }
+          
+              if(GPSbutton[0])
+            {
+                delete GPSbutton[0];
+                GPSbutton[0]=nullptr;
+            }
+
+            if(GPSbutton[1])
+            {
+                delete GPSbutton[1];
+                GPSbutton[1]=nullptr;
+            }
+          
+          
+
+            delete testGPSScrollView;
+            testGPSScrollView=nullptr;
+       }
+    }
+   
+    UILabelButtonExt *testGPSView::SetTheButton_ext(ButtonConfig_ext_t &buttonconfig)
+    {
+        UILabelButtonExt *button = new UILabelButtonExt();
+        if (button == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " SystemView::SetTheButton: button new  fail!");
+            return nullptr;
+        }
+        button->SetPosition(buttonconfig.x, buttonconfig.y, buttonconfig.w, buttonconfig.h);
+        button->SetViewId(buttonconfig.ViewId);
+        button->SetStyle(STYLE_BACKGROUND_COLOR, Color::Blue().full);
+        //button->SetStyle(STYLE_BORDER_RADIUS,0);
+        button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::Black().full, UIButton::PRESSED);
+        //button->SetStyleForState(STYLE_BORDER_RADIUS,0, UIButton::PRESSED);
+        button->SetTouchable(true);
+        button->SetStyle(STYLE_BACKGROUND_OPA, 0x80);
+        button->SetText(buttonconfig.str);
+        button->SetAlign(TEXT_ALIGNMENT_LEFT);
+        button->SetLabelPosition(buttonconfig.label_x,buttonconfig.label_y );
+        button->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, buttonconfig.Fontsize);
+        UIView:: OnClickListener *touchListener = static_cast<UIView::OnClickListener *>(testPresenter::GetInstance());
+        button->SetOnClickListener(touchListener);
+
+        return button;
+    }
+   
+     UILabel *testGPSView::InitLabel(LabelConfig &labelConfig)
+    {
+        UILabel *label = new UILabel();
+        if (label == nullptr)
+        {
+            return nullptr;
+        }
+        label->SetPosition(labelConfig.left, labelConfig.top, labelConfig.width, labelConfig.height); // 位置大小
+        label->SetStyle(STYLE_TEXT_FONT, labelConfig.fontSize);                                       // 字体大小
+        label->SetStyle(STYLE_LINE_HEIGHT, labelConfig.lineHeigh);                                    // 字体行高
+        label->SetText(labelConfig.text);                                                             // 内容
+        label->SetLineBreakMode(labelConfig.lineBreakMode);                                           // 断行模式。
+        label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_TOP);
+        label->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, labelConfig.fontSize);
+        label->SetAlign(TEXT_ALIGNMENT_LEFT);
+        return label;
+    }
+
+    static char msgtmp[1024]={0};
+
+    void testGPSView:: gpsdataTimerCallBack(void)
+    {
+        if (label_1_GPS_MSG != nullptr) {
+        
+            gps_data_t * gpsdata=getGPSGlobaldata();
+            gps_data_t gpsd={0};
+            if (gpsdata->last_gps_time_ms>0)
+            {
+                memcpy(&gpsd,gpsdata,sizeof(gps_data_t));
+            }
+            memset_s(msgtmp,sizeof(msgtmp),0,sizeof(msgtmp));        
+            dump_location_data_to_buf(&gpsd,msgtmp,sizeof(msgtmp));
+            label_1_GPS_MSG->SetText(msgtmp);
+
+            if (getGnssServerStat()==1)
+            {
+                label_1_GPS_on_or_off->SetText("GPS开");
+            }else{
+                label_1_GPS_on_or_off->SetText("GPS关");
+            }
+        }
+    }
+
+    void gpsdataTimerCallBackproc()
+    {
+         GraphicService::GetInstance()->PostGraphicEvent(std::bind(&testGPSView::gpsdataTimerCallBack,testGPSView::GetInstance()));
+    }
+
+    
+    bool testGPSView::testGPSScrollViewcrollViewinit(uint8_t id)
+    {
+
+        testGPSScrollView = new UIScrollView();
+        if (testGPSScrollView == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemAboutTheWatchView::testGPSScrollView new fail!");
+            return false;
+        }
+        testGPSScrollView->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());
+        testGPSScrollView->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
+        testGPSScrollView->SetStyle(STYLE_BORDER_RADIUS, 0);
+        testGPSScrollView->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
+        testGPSScrollView->SetStyle(STYLE_BORDER_COLOR, Color::Yellow().blue);
+
+        LabelConfig Config = {
+            .left = 50,
+            .top = 85,
+            .width = Screen::GetInstance().GetWidth()-80,
+            .height = 35,
+            .fontSize = 20,
+            .lineHeigh = 25,
+            .text = "",
+            .lineBreakMode = UILabel::LINE_BREAK_WRAP,
+        };
+        label_1_GPS_MSG= InitLabel(Config);
+        if (label_1_GPS_MSG == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::SystemAboutTheWatchTitle new fail!");
+            return false;
+        }
+        testGPSScrollView->Add(label_1_GPS_MSG);
+
+        Config = {
+            .left = 50,
+            .top = 50,
+            .width = 350,
+            .height = 30,
+            .fontSize = 25,
+            .lineHeigh = 35,
+            .text = "",
+            .lineBreakMode = UILabel::LINE_BREAK_WRAP,
+        };
+        label_1_GPS_on_or_off= InitLabel(Config);
+        if (label_1_GPS_on_or_off == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::SystemAboutTheWatchTitle new fail!");
+            return false;
+        }
+        testGPSScrollView->Add(label_1_GPS_on_or_off);
+       
+
+        ButtonConfig_ext_t buttonconfig;
+        buttonconfig.x = 20;
+        buttonconfig.y = 400;
+        buttonconfig.w = 180;
+        buttonconfig.h = 96;
+        buttonconfig.label_x=40;
+        buttonconfig.label_y=0;
+        buttonconfig.Fontsize=30;
+        buttonconfig.ViewId=GPS_OPEN_CONFIRM_BUTTON;
+        buttonconfig.str=GPS_OPEN_CONFIRM_BUTTON;
+        buttonconfig.ALIGN=TEXT_ALIGNMENT_LEFT;
+        GPSbutton[0]=SetTheButton_ext(buttonconfig);
+        testGPSScrollView->Add( GPSbutton[0]);
+        //testcat1ScrollView->Add(button);
+
+        buttonconfig.x = 220;
+        buttonconfig.y = 400;
+        buttonconfig.w = 180;
+        buttonconfig.h = 96;
+        buttonconfig.label_x=40;
+        buttonconfig.label_y=0;
+        buttonconfig.Fontsize=30;
+        buttonconfig.ViewId=GPS_CLOSE_CANCEL_BUTTON;
+        buttonconfig.str=GPS_CLOSE_CANCEL_BUTTON;
+        buttonconfig.ALIGN=TEXT_ALIGNMENT_LEFT;
+        GPSbutton[1]=SetTheButton_ext(buttonconfig);
+        testGPSScrollView->Add( GPSbutton[1]);
+        
+
+
+
+        UIView::OnDragListener *draglistener = static_cast<UIView::OnDragListener *>(testPresenter::GetInstance());
+        if (draglistener == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::draglistener can not be nullptr!");
+            return false;
+        }
+       testGPSScrollView->SetOnDragListener(draglistener);
+
+
+        labelButton_next= testAboutView::GetInstance()->init_button_next(267,320,Test_ViewMapper_t[id].viewid_str_next);
+        testGPSScrollView->Add(labelButton_next);
+        
+        Title= testAboutView::GetInstance()->init_title(165,45,"GPS_TEST");
+        testGPSScrollView->Add(Title);
+
+
+        testGPSScrollView->SetTouchable(true);
+        testGPSScrollView->SetDraggable(true);
+        uint32_t tick;
+        osStatus_t retTimer;
+        GPS_TEST_timer = osTimerNew((osTimerFunc_t)gpsdataTimerCallBackproc, osTimerPeriodic, NULL, NULL);
+        tick =2000;// osMs2Tick(1000);
+        retTimer = osTimerStart(GPS_TEST_timer, tick);
+        if (retTimer != osOK && GPS_TEST_timer != NULL) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"StartCallTimer osTimerStart failed, ret = %lx!!", retTimer);
+            osTimerDelete(GPS_TEST_timer);
+            GPS_TEST_timer = NULL;
+            return false;
+        }
+        return true;
+    }
+
+    UIScrollView *testGPSView::testGPSInitIView(uint8_t id)
+    {
+        if (!testGPSScrollViewcrollViewinit(id))
+        {
+            return nullptr;
+        }
+        return testGPSScrollView;
+    }
+}
+
+#endif
index 81fff92..aa56fc4 100644 (file)
@@ -1,22 +1,37 @@
 #include "AppViewIDs.h"\r
 #include "components/ui_label_ext.h"\r
-#include"ui_resource_string.h"\r
+#ifdef FD230\r
+    #include"ui_resource_string.h"\r
+#endif\r
+\r
 #include "NativeAbility.h"\r
 #include "graphic_math.h"\r
 #include "string.h"\r
 #include "producttest/include/testPresenter.h"\r
 #include "font/font_global_manager.h"\r
 #include "font/ui_font.h"\r
-#include "languagecode/LanguageInit.h"\r
-#include "../../../../../../drivers/peripheral/utils/custom_utils.h"\r
+#ifdef FD230\r
+    #include "languagecode/LanguageInit.h"\r
+#endif\r
+#include "custom_utils.h"\r
 #include "power_display_service.h"\r
 #include "components/ui_slider.h"\r
 \r
 #include "audio_capture_wrapper.h"\r
 #include "cywee_service.h"\r
-#include "factorytest_protocol.h"\r
+\r
+#ifdef FD230\r
+    #include "factorytest_protocol.h"\r
+#endif\r
+\r
+\r
+\r
 #include "custom_runtime.h"\r
 \r
+#if defined(SUPPORT_GNSS)\r
+#include "gnss_ctl.h"\r
+#endif\r
+\r
 namespace OHOS\r
 {\r
 \r
@@ -242,7 +257,9 @@ namespace OHOS
 \r
         if(strcmp(view.GetViewId(),"dial_112") == 0)\r
         { \r
+            #ifdef SUPPORT_CAT1_SERVICE\r
             testcat1View::GetInstance()->dial_112(true);\r
+            #endif\r
         } \r
 \r
         if(strcmp(view.GetViewId(),"gray_card") == 0)\r
@@ -271,15 +288,27 @@ namespace OHOS
         { \r
             if(uapi_dev_runtime_get_cat1_powerstat())\r
                 uapi_set4GCapability(false);\r
-            factorytest_start_aging_test();\r
+            #ifdef FD230\r
+                factorytest_start_aging_test();\r
+            #endif\r
         }\r
         if(strcmp(view.GetViewId(),"stop") == 0)\r
         { \r
-            factorytest_stop_aging_test();\r
+            #ifdef FD230\r
+                factorytest_stop_aging_test();\r
+            #endif\r
         }\r
         if(strcmp(view.GetViewId(),"exit") == 0)\r
         { \r
-            NativeAbility::GetInstance().ChangeSlice(VIEW_TEST);\r
+            for (int i = 1; i < MAX_TESTVIEWID; i++)\r
+            {\r
+                if (p_SystemView->GetSystemScrollView(i))\r
+                {\r
+                    p_SystemView->ChangeView(i, TESTVIEW);\r
+                    break;\r
+                }\r
+            }\r
+            return true;\r
         }\r
         if(strcmp(view.GetViewId(),"deep") == 0)\r
         { \r
@@ -312,6 +341,26 @@ namespace OHOS
 \r
             testA5133View::GetInstance()->a5133_receive_callback();\r
         }\r
+\r
+     \r
+\r
+\r
+        #endif\r
+\r
+        #if defined(SUPPORT_GNSS)\r
+        if (strcmp(view.GetViewId(), GPS_OPEN_CONFIRM_BUTTON) == 0)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GPS On OnClick");\r
+            gnss_start();\r
+           \r
+        }\r
+\r
+\r
+        if (strcmp(view.GetViewId(), GPS_CLOSE_CANCEL_BUTTON) == 0)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GPS On OnClick");\r
+            gnss_stop();\r
+        }\r
         #endif\r
         return false;\r
     }\r
@@ -326,25 +375,39 @@ namespace OHOS
     if(testbuttonView::GetInstance())\r
     {\r
         if (keyID == 41 )\r
-    {\r
+        {\r
+            if(keystate)\r
+            testbuttonView::GetInstance()-> Changbutton(0,true);\r
+            else\r
+            testbuttonView::GetInstance()-> Changbutton(0,false);\r
+        \r
+            // uint16_t preSlice = NativeAbility::GetInstance().GetPreSliceId();\r
+            // NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST);\r
+        }\r
+        if (keyID == 0)\r
+        {\r
         if(keystate)\r
-        testbuttonView::GetInstance()-> Changbutton(0,true);\r
-        else\r
-        testbuttonView::GetInstance()-> Changbutton(0,false);\r
-       \r
-        // uint16_t preSlice = NativeAbility::GetInstance().GetPreSliceId();\r
-        // NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST);\r
-    }\r
-    if (keyID == 0)\r
-    {\r
-       if(keystate)\r
-        testbuttonView::GetInstance()-> Changbutton(1,true);\r
-        else\r
-        testbuttonView::GetInstance()-> Changbutton(1,false);\r
-       \r
-        // uint16_t preSlice = NativeAbility::GetInstance().GetPreSliceId();\r
-        // NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST);\r
-    }\r
+            testbuttonView::GetInstance()-> Changbutton(1,true);\r
+            else\r
+            testbuttonView::GetInstance()-> Changbutton(1,false);\r
+        \r
+            // uint16_t preSlice = NativeAbility::GetInstance().GetPreSliceId();\r
+            // NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST);\r
+        }\r
+\r
+#ifdef BOARD_U8\r
+        if (keyID == 1)\r
+        {\r
+\r
+            if(keystate)\r
+                testbuttonView::GetInstance()-> Changbutton(2,true);\r
+            else\r
+                testbuttonView::GetInstance()-> Changbutton(2,false);\r
+            \r
+            // uint16_t preSlice = NativeAbility::GetInstance().GetPreSliceId();\r
+            // NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST);\r
+        }\r
+#endif\r
 \r
     }\r
  \r
@@ -396,15 +459,18 @@ extern "C"
 \r
     void factorytest_enter_test_tp_view(void)\r
     {\r
-        testView::GetInstance()->ChangeView(TESTVIEW,TP);\r
+        if(testView::GetInstance())\r
+            testView::GetInstance()->ChangeView(TESTVIEW,TP);\r
+        else\r
+            printf("xxxxxxxxxxxxxxxxxxxxx\r\n");\r
     }\r
 \r
     void factorytest_enter_test_lcd_view(void)\r
     {\r
         if( testView::GetInstance())\r
-        testView::GetInstance()->ChangeView(TESTVIEW,LCD);\r
+            testView::GetInstance()->ChangeView(TESTVIEW,LCD);\r
         else\r
-        printf("xxxxxxxxxxxxxxxxxxxxx\r\n");\r
+            printf("xxxxxxxxxxxxxxxxxxxxx\r\n");\r
     }\r
 \r
     void factorytest_enter_test_button_view(void)\r
index 9ad4774..2a886e7 100644 (file)
@@ -2,11 +2,20 @@
 #include "producttest/include/testPresenter.h"\r
 #include "power_display_service.h"\r
 #include "wearable_log.h"\r
+#ifdef SUPPORT_CAT1_SERVICE\r
 #include "cat1_server.h"\r
 #include "cat1_ctl.h"\r
 #include "cat1_server_hal.h"\r
+#endif\r
+\r
 #include "custom_utils.h"\r
 #include "custom_runtime.h"\r
+\r
+\r
+#ifdef FD230\r
+    #include "factorytest_protocol.h"\r
+#endif\r
+\r
 namespace OHOS\r
 {\r
 \r
@@ -20,10 +29,13 @@ namespace OHOS
         {TP,"TPButton","TP","TPButton_next", &testView::ChangeTPTESTView,true},\r
         {MAGETIC,"MAGETICButton","Magetic","MAGETICButton_next", &testView::ChangeMGTESTView,true},\r
         {LUMINANCE,"luminanceButton","luminance","luminanceButton_next", &testView::ChangLUMTESTView,true},\r
-        {CHAR,"chargingButton","bat&charger","chargingButton_next",&testView::ChangchargingTESTView,true},\r
+        {CHARG,"chargingButton","bat&charger","chargingButton_next",&testView::ChangchargingTESTView,true},\r
         {SPEAK,"speakButton","speak","speakButton_next" ,&testView::ChangspeakTESTView,true},\r
+\r
         {MOTOR,"motorButton","motor","motorButton_next" ,&testView::ChangmotorTESTView,true},\r
+    #ifdef SUPPORT_CAT1_SERVICE\r
         {CAT1,"cat1button","CAT1", "cat1button_next",&testView::ChangeCAT1TESTView,true},\r
+    #endif\r
         {BUTTON,"buttonbutton","button" ,"buttonbutton_next",&testView::ChangKEYTESTView,true},\r
         {MICROPHONE,"microphonebutton","microphone", "microphonebutton_next",&testView::ChangeMPTESTView,true},\r
         {HRSENSON,"hrsensonbutton","hrsensor", "hrsensonbutton_next",&testView::ChangeHRTESTView,true},\r
@@ -31,7 +43,19 @@ namespace OHOS
         {BTTEST,"BTbutton","BT" ,"BTbutton_next",&testView::ChangeBTTESTView,true},\r
         {SEChipTest,"SEChipTestbutton","SEChipTest","SEChipTestbutton_next" ,&testView::ChangeSEChipTESTView,true},\r
         {PingTest,"PingTestbutton","PingTest","PingTestbutton_next" ,&testView::ChangePingTESTView,true},\r
+\r
+#if defined(SUPPORT_GNSS)\r
+        {GPSTEST,"GPSTestbutton","GPSTest","GPSTestbutton_next" ,&testView::ChangeGPSTESTView,true},\r
+#endif\r
+#if defined(ENABLE_LQBP002TA)\r
+        {PRESSURETEST,"pressureTestbutton","pressureTest","pressureTestbutton_next" ,&testView::ChangepressureTestTESTView,true},\r
+#endif\r
+#if defined(ENABLE_GYRO)\r
+        {GYROTEST,"gyroTestbutton","gyroTest","gyroTestbutton_next" ,&testView::ChangegyroTestTESTView,true},\r
+#endif\r
+#ifdef AGINGTEST\r
         {OLDTEST,"oldtestbutton","aging" ,"oldtestexit",&testView::ChangeoldTESTView,true},\r
+#endif\r
         {DEEPSLEEP,"deepsleep","DeepSleepCurrent","xxxxxxxxx" ,&testView::ChangeoldTESTView,true},\r
         {shutdown,"shutdown","shutdown", "xxxxxxxxx",&testView::ChangeoldTESTView,true},\r
         {RESET,"reset","reset", "xxxxxxxxx",&testView::ChangeoldTESTView,true},\r
@@ -39,13 +63,7 @@ namespace OHOS
     #ifdef SUPPORT_A5133_SERVICE\r
         {RF5133,"RF5133","RF5133", "xxxxxxxxx",&testView::ChangeA5133TESTView,true},\r
     #endif\r
-        // {SYSTEMLUPGRADE,"systemupgread","系统升级",&testView::ChangeSystemAboutView},\r
-        // {TEST,"testButton","测试模式", &testView::ChangeSystemAboutView},\r
-        \r
-        // {ABOUTTHEWATCHVIEW, &SystemView::ChangeSystemAboutView},\r
-        // {SUPERVISEVIEW, &SystemView::ChangeSystemSuperviseView},\r
-        // {SYSTEMLANGUAGEVIEW, &SystemView::ChangeSystemLanguageView},\r
-        // {FACTORYRESETVIEW, &SystemView::ChangeSystemFactoryResetView},\r
+\r
     };\r
     \r
     testView::testView()\r
@@ -71,13 +89,6 @@ namespace OHOS
         if (initViewStatus == true)\r
         {\r
             SystemScrollView[TESTVIEW]->RemoveAll();\r
-            // UIView::OnDragListener *draglistener = SystemScrollView[SYSTEMVIEW]->GetOnDragListener();\r
-            // if (draglistener != nullptr)\r
-            // {\r
-            //     delete draglistener;\r
-            //     draglistener = nullptr;\r
-            // }\r
-\r
             int funcSize = sizeof(Test_ViewMapper_t) / sizeof(Test_ViewMapper_t[TESTVIEW]);\r
             for (int i = 0; i < funcSize; i++)\r
             {\r
@@ -123,11 +134,14 @@ namespace OHOS
             delete test_motor_view;//7\r
             test_motor_view = nullptr;\r
             }\r
+#ifdef SUPPORT_CAT1_SERVICE\r
             if(test_cat1_view)\r
             {\r
             delete test_cat1_view;//8\r
             test_cat1_view = nullptr;\r
             }\r
+#endif\r
+\r
             if(test_KEY_view)\r
             {\r
             delete test_KEY_view;//9\r
@@ -192,6 +206,8 @@ namespace OHOS
         }\r
         SystemScrollView[TESTVIEW]->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());\r
         SystemScrollView[TESTVIEW]->SetStyle(STYLE_BACKGROUND_OPA, 0xff);\r
+        SystemScrollView[TESTVIEW]->SetStyle(STYLE_BORDER_RADIUS, 0);\r
+        \r
         SystemScrollView[TESTVIEW]->SetScrollBlankSize(35);\r
         SystemScrollView[TESTVIEW]->SetReboundSize(50);\r
         SystemScrollView[TESTVIEW]->SetDirection(1);\r
@@ -457,6 +473,7 @@ namespace OHOS
 \r
      bool testView::ChangeCAT1TESTView(int16_t thisView)\r
     {\r
+        #ifdef SUPPORT_CAT1_SERVICE\r
         if (SystemScrollView[thisView] == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeCAT1TESTView");\r
@@ -469,6 +486,7 @@ namespace OHOS
             SystemScrollView[thisView] = test_cat1_view->testcat1InitIView(thisView);\r
             RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
         }\r
+        #endif\r
         return true;\r
     }\r
 \r
@@ -540,9 +558,11 @@ namespace OHOS
         }\r
         return true;\r
     }\r
+  \r
 \r
      bool testView::ChangeoldTESTView(int16_t thisView)\r
     {\r
+          #ifdef AGINGTEST\r
         if (SystemScrollView[thisView] == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeoldTESTView");\r
@@ -555,8 +575,11 @@ namespace OHOS
             SystemScrollView[thisView] = test_old_view->testoldInitIView(thisView);\r
             RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
         }\r
+          #endif\r
         return true;\r
+       \r
     }\r
+   \r
 \r
     bool testView::ChangeBTTESTView(int16_t thisView)\r
     {\r
@@ -610,6 +633,68 @@ namespace OHOS
         return true;\r
     }\r
 \r
+#if defined(SUPPORT_GNSS)\r
+    bool testView::ChangeGPSTESTView(int16_t thisView)\r
+    {\r
+\r
+        if (SystemScrollView[thisView] == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeSEChipTESTView");\r
+            test_GPS_view = new testGPSView();\r
+            if (test_GPS_view == nullptr)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView:: new scrollView[%d] fail", thisView);\r
+                return false;\r
+            }\r
+            SystemScrollView[thisView] = test_GPS_view->testGPSInitIView((uint8_t)thisView);\r
+            RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
+        }\r
+\r
+        return true;\r
+    }\r
+#endif\r
+#if defined(ENABLE_LQBP002TA)\r
+     bool testView::ChangepressureTestTESTView(int16_t thisView)\r
+    {\r
+\r
+        if (SystemScrollView[thisView] == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeSEChipTESTView");\r
+            test_pressure_view = new testpressureView();\r
+            if (test_pressure_view == nullptr)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView:: new scrollView[%d] fail", thisView);\r
+                return false;\r
+            }\r
+            SystemScrollView[thisView] = test_pressure_view->testpressureInitIView((uint8_t)thisView);\r
+            RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
+        }\r
+\r
+\r
+        return true;\r
+    }\r
+#endif\r
+#if defined(ENABLE_GYRO)\r
+    bool testView::ChangegyroTestTESTView(int16_t thisView)\r
+    {\r
+\r
+        if (SystemScrollView[thisView] == nullptr)\r
+        {\r
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeSEChipTESTView");\r
+            test_gyro_view = new testgyroView();\r
+            if (test_gyro_view == nullptr)\r
+            {\r
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView:: new scrollView[%d] fail", thisView);\r
+                return false;\r
+            }\r
+            SystemScrollView[thisView] = test_gyro_view->testgyroInitIView((uint8_t)thisView);\r
+            RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+#endif\r
 #ifdef SUPPORT_A5133_SERVICE\r
     bool testView::ChangeA5133TESTView(int16_t thisView)\r
     {\r
@@ -706,7 +791,7 @@ namespace OHOS
                 test_lum_view = nullptr;\r
                  SystemScrollView[hideView]=nullptr;\r
             break;\r
-            case CHAR:\r
+            case CHARG:\r
                 RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
                 delete test_charging_view;  \r
                 test_charging_view = nullptr;\r
@@ -725,12 +810,14 @@ namespace OHOS
                 test_motor_view = nullptr;\r
                  SystemScrollView[hideView]=nullptr;\r
             break;\r
+#ifdef SUPPORT_CAT1_SERVICE\r
              case CAT1:\r
                 RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
                 delete test_cat1_view;  \r
                 test_cat1_view = nullptr;\r
                  SystemScrollView[hideView]=nullptr;\r
             break;\r
+#endif\r
              case BUTTON:\r
                 RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
                 delete test_KEY_view;  \r
@@ -778,7 +865,15 @@ namespace OHOS
                 delete test_Ping_view;  \r
                 test_Ping_view = nullptr;\r
                 SystemScrollView[hideView]=nullptr;\r
+                break;\r
+#if defined(SUPPORT_GNSS)\r
+            case GPSTEST:\r
+                RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
+                delete test_GPS_view;  \r
+                test_GPS_view = nullptr;\r
+                SystemScrollView[hideView]=nullptr;\r
                 break; \r
+#endif\r
 #ifdef SUPPORT_A5133_SERVICE\r
             case RF5133:\r
                 RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
@@ -787,6 +882,23 @@ namespace OHOS
                 SystemScrollView[hideView]=nullptr;\r
                 break;\r
 #endif\r
+#if defined(ENABLE_LQBP002TA)\r
+             case PRESSURETEST:\r
+                RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
+                delete test_pressure_view;  \r
+                test_pressure_view = nullptr;\r
+                SystemScrollView[hideView]=nullptr;\r
+                break;\r
+#endif\r
+#if defined(ENABLE_GYRO)\r
+             case GYROTEST:\r
+                RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
+                delete test_gyro_view;  \r
+                test_gyro_view = nullptr;\r
+                SystemScrollView[hideView]=nullptr;\r
+                break;\r
+#endif\r
+\r
            default:\r
             break;\r
            }\r
index c1eb440..a0ff0cd 100644 (file)
@@ -4,6 +4,7 @@
 #include "producttest/include/testcat1.h" 
 #include "AlarmClockModel.h"
 #include "cmsis_os2.h"
+#ifdef SUPPORT_CAT1_SERVICE
 #include "cat1_server.h"
 #include "cat1_ctl.h"
 #include "cat1_server_hal.h"
@@ -192,14 +193,7 @@ namespace OHOS
         msgver.modem_version = uapi_dev_runtime_get_cat1_modemver();
        
         OHOS::testcat1View::cat1_msg msg={0};
-        if(get_imei_map_index()>=0)
-        {
-            msg.imei =get_map_index_str();
-        }
-        else
-        {
-            msg.imei =uapi_dev_runtime_get_cat1_imei();
-        }
+        msg.imei = uapi_dev_runtime_get_cat1_imei();
         msg.sim = uapi_dev_runtime_get_cat1_simstat();
         msg.signal = uapi_dev_runtime_get_cat1_signal();
         msg.oper = uapi_dev_runtime_get_cat1_operator();
@@ -367,4 +361,6 @@ namespace OHOS
         }
         return testcat1ScrollView;
     }
-}
\ No newline at end of file
+}
+
+#endif
index 0f0f510..bcde2a1 100644 (file)
@@ -4,10 +4,6 @@
 #include "producttest/include/testhrsenson.h" 
 #include "AlarmClockModel.h"
 #include "cmsis_os2.h"
-#include "cat1_server.h"
-#include "cat1_ctl.h"
-#include "cat1_server_hal.h"
-#include "ppg_service.h"
 #include "producttest/include/testView.h"
 #ifdef __cplusplus
 #if __cplusplus
@@ -17,6 +13,12 @@ extern "C"
 #endif
     #include "pm_veto.h"
     #include "pm.h"
+
+#ifdef SUPPORT_PPG_SERVICE
+#include "ppg_service.h"
+#include "ppg_hal.h"
+#endif
+
 #ifdef __cplusplus
 #if __cplusplus
 }
@@ -95,36 +97,27 @@ namespace OHOS
     static bool button_falg=true;
     void testhrsenson1View:: setgrayvalue(int g,int r,int ir)
     {
-        
-        if(label_hrsenson_value_vison!=NULL)
-        {
-
-            char buf[124]={0};
-            sprintf(buf,"gray:\n green:%d\nred:%d\nir:%d",g,r,ir);
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s",buf);
-            label_hrsenson_value_vison->SetText(buf);
-            RootView::GetInstance()->Invalidate();
-            int8_t md = PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST;
-            send_ppg_cmd_msg(md);
-            button_falg=true;
-        }
-        
     }
-    void testhrsenson1View:: setlightvalue(int g,int r,int ir)
+    void testhrsenson1View:: setlightvalue(void)
     {
-        
+        char buf[124]={0};
         if(label_hrsenson_value_vison!=nullptr)
         {
-            char buf[124]={0};
-            sprintf(buf,"leaklight:\ngreen:%d\nred:%d\nir:%d",g,r,ir);
+#ifdef SUPPORT_PPG_SERVICE   
+            send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_LEAKLIGHT_TEST); 
+            LOS_Msleep(1000);
+            uint32_t ch0 = 0;
+            uint32_t ch1 = 0;
+            uint32_t ch2 = 0;
+            ppg_get_leaklight_data(&ch0,&ch1,&ch2);
+            send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);
+            sprintf(buf,"leaklight:\ngreen:%d\nred:%d\nir:%d",ch0,ch1,ch2);
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s",buf);
             label_hrsenson_value_vison->SetText(buf);
             RootView::GetInstance()->Invalidate();
-            int8_t md = PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST;
-            send_ppg_cmd_msg(md);
-             button_falg=true;
-        }
-        
+            button_falg=true;
+#endif
+        }    
     }
 
     UILabelButtonExt *testhrsenson1View::SetTheButton_ext(ButtonConfig_ext_t &buttonconfig)
@@ -164,8 +157,9 @@ namespace OHOS
     {
         if(button_1!=NULL)
         {
-            int8_t md = PPG_SERVICE_CMD_TYPE_DO_GRAYCARD_TEST;
-            send_ppg_cmd_msg(md);
+#ifdef SUPPORT_PPG_SERVICE   
+            send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_GRAYCARD_TEST);
+#endif
             button_falg=false;
         }  
     }
@@ -174,9 +168,8 @@ namespace OHOS
     {
         if(button_2!=NULL)
         {
-            int8_t md = PPG_SERVICE_CMD_TYPE_DO_LEAKLIGHT_TEST;
-            send_ppg_cmd_msg(md);
-             button_falg=false;
+            button_falg=false;
+            testhrsenson1View::setlightvalue();
         }  
     }
 
@@ -202,7 +195,7 @@ namespace OHOS
 
 
     
-    bool testhrsenson1View::tesScat1ScrollViewcrollViewinit(uint8_t id)
+    bool testhrsenson1View::testhrsensonScrollViewcrollViewinit(uint8_t id)
     {
 
         testhrsensonScrollView = new UIScrollView();
@@ -315,7 +308,7 @@ namespace OHOS
 
     UIScrollView *testhrsenson1View::testhrsensonInitIView(uint8_t id)
     {
-        if (!tesScat1ScrollViewcrollViewinit(id))
+        if (!testhrsensonScrollViewcrollViewinit(id))
         {
             return nullptr;
         }
index df38eeb..5353981 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com\r
  * @Date: 2024-06-17 14:31:08\r
  * @LastEditors: penglei 1624952103@qq.com\r
- * @LastEditTime: 2025-01-10 11:19:35\r
+ * @LastEditTime: 2025-06-06 17:11:43\r
  * @FilePath: /FD230/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c\r
  * @Description: \r
  * \r
 #include "lcd_private.h"\r
 #include "app_at_process.h"\r
 #include "cywee_hal.h"\r
-#include "hx3695.h"\r
+\r
+#ifdef SUPPORT_PPG_SERVICE\r
 #include "ppg_service.h"\r
+#include "ppg_hal.h"\r
+#endif\r
+\r
 #include "button_porting.h"\r
+#ifdef SUPPORT_CAT1_SERVICE\r
 #include "cat1_ctl.h"\r
 #include "cat1_server.h"\r
+#endif\r
+#ifdef PPG_HX3695\r
+#include "hx3695.h"\r
 #include "hx3695_hrs_agc.h"\r
 #include "hx3695_spo2_agc.h"\r
 #include "hx3695_factory_test.h"\r
+#endif\r
 #include "power_display_service.h"\r
 #include "efuse.h"\r
 #include "mag_service.h"\r
 #include "nandflash_config.h"\r
 #include "string.h"\r
 #include "custom_runtime.h"\r
-#include "bletest.h"\r
+\r
+#ifdef BLE_INSTRUCT\r
+#include "bleInstruct.h"\r
+#endif\r
+\r
 #include "battery_service.h"\r
 #include "cywee_service.h"\r
 #include "broadcast_feature.h"\r
 #include "lwip/api_shell.h"\r
 #endif\r
 #include "input_app.h"\r
+#ifdef FD230\r
 #include "PhoneServiceC.h"\r
+#endif\r
+#ifdef ENABLE_LQBP002TA\r
+#include "lqbp_service.h"\r
+#include "lqbp002ta.h"\r
+#endif\r
+#ifdef ENABLE_HP4570\r
+#include "hp4570.h"\r
+#endif\r
+#ifdef PPG_VC9202\r
+#include "vc9202_user.h"\r
+#endif\r
+#ifdef SUPPORT_GNSS\r
+#include "gnss_ctl.h"\r
+#include "NMEA0183.h"\r
+static gps_data_t send_gps_data = {0};\r
+#endif\r
+\r
+#ifdef ENABLE_BN02\r
+#include "bp_ble_service.h"\r
+#endif\r
+\r
+#ifdef ENABLE_GYRO\r
+#include "gyro_service.h"\r
+#include "gyro_hal.h"\r
+#endif\r
+\r
 \r
 #pragma pack(1)\r
 typedef struct factorytest_cmd_header_t\r
@@ -256,7 +296,9 @@ void aging_task(void)
 // /*********************TP 老化测试*****************************/\r
         //读TP ID\r
         uint16_t tp_id;\r
+#ifdef TPTYPE_FT6X46\r
         touch_getid(&tp_id);\r
+#endif\r
         if(tp_id != 0x6456)\r
         {\r
             aging_t.tp_error++;\r
@@ -267,7 +309,9 @@ void aging_task(void)
 /*********************表冠 老化测试*****************************/\r
         //读crown ID\r
         uint8_t crown_id = 0;\r
+#ifdef ROTARYENCODER_HX3507\r
         crown_read_id(&crown_id);\r
+#endif\r
         if(crown_id != 0x30)\r
         {\r
             aging_t.crown_error++;\r
@@ -354,17 +398,24 @@ void aging_task(void)
                 return;\r
             }\r
             uapi_get_timestampe_ss(&current_time);\r
-            send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_SINGLE_CHECK_MODE_TEST);\r
+\r
+            uint32_t green = 0;\r
+            uint32_t red = 0;\r
+            uint32_t ir = 0;\r
+\r
+#ifdef SUPPORT_PPG_SERVICE\r
+            send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_LEAKLIGHT_TEST);\r
             LOS_Msleep(1000);\r
-            FT_RESULTS_t ft_result = hx3695_factroy_test(SINGLE_CHECK_TEST);\r
+            ppg_get_leaklight_data(&green,&red,&ir);\r
             send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);\r
-            PRINT("ft_result.gr_data_final : %d , ft_result.red_data_final : %d , ft_result.ir_data_final : %d\r\n",ft_result.gr_data_final,ft_result.red_data_final,ft_result.ir_data_final);\r
-            if(!(ft_result.gr_data_final && ft_result.red_data_final && ft_result.ir_data_final))\r
+#endif\r
+            PRINT("green : %d , red : %d , ir : %d\r\n",green,red,ir);\r
+            if(!green && !red && !ir)\r
             {\r
                 aging_t.ppg_error++;\r
                 aging_t.fail_num++;\r
             }\r
-            // PRINT("current_time - enter_time[%d]\n",current_time -  enter_time);\r
+            PRINT("current_time -  enter_time[%d]\n",current_time -  enter_time);\r
         }while(current_time - enter_time <= 2 * 60);\r
 \r
         PRINT("aging_t.ppg_error : %d \r\n",aging_t.ppg_error);\r
@@ -575,13 +626,15 @@ void factorytest_protocol_common_decode(uint8_t submode,uint8_t testitem,uint8_t
                 mmc5603_getid(&mmc_id);\r
                 if(mmc_id != 0x10)\r
                     send_data[1] |= 2 << 4;\r
-\r
+#ifdef TPTYPE_FT6X46\r
                 touch_getid(&tp_id);\r
+#endif\r
                 PRINT("touch_getid : %2X \r\n",tp_id);\r
                 if(tp_id != 0x6456)\r
                     send_data[1] |= 1 << 4;\r
-\r
-                uapi_ppg_get_id(&id);\r
+#ifdef SUPPORT_PPG_SERVICE\r
+                id = ppg_get_chip_id();\r
+#endif\r
                 if(id != 0x65)\r
                     send_data[1] |= 1 << 3;\r
 \r
@@ -810,7 +863,6 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 if(g_ble_vibrator_timer != NULL)\r
                 {\r
                     osTimerStop(g_ble_vibrator_timer);\r
-                    osTimerDelete(g_ble_vibrator_timer);\r
                 }\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_VIBRATOR,\r
@@ -826,6 +878,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 uint8_t send_data = 0;\r
 \r
+                pwr_button_result = 0;\r
+                func_button_result = 0;\r
+\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_KEY,\r
                         0x01,\r
@@ -1218,8 +1273,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 //获取TP_ID\r
                 uint16_t id = 0;\r
                 uint8_t tp_id[3];\r
+#ifdef TPTYPE_FT6X46\r
                 touch_getid(&id);\r
-\r
+#endif\r
                 tp_id[0] = 0;\r
                 tp_id[1] = id >> 8;\r
                 tp_id[2] = id;\r
@@ -1273,7 +1329,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //获取原始数据\r
                 int16_t x,y;\r
+#ifdef TPTYPE_FT6X46\r
                 get_tp_info(&x,&y);\r
+#endif\r
                 uint8_t databuf[5] = {0};\r
 \r
                 databuf[1] = (uint8_t)((x & 0XFF00) >> 8);\r
@@ -1363,12 +1421,10 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //获取 ppg_id\r
                 uint8_t ppg_id;\r
-                uapi_ppg_get_id(&ppg_id);\r
-                if(ppg_id != 0x65)\r
-                {\r
-                    hx3695_chip_check();\r
-                    uapi_ppg_get_id(&ppg_id);\r
-                }\r
+#ifdef SUPPORT_PPG_SERVICE\r
+                ppg_id = ppg_get_chip_id();\r
+#endif\r
+                PRINT("0x%x\n",ppg_id);\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_HRS,\r
                         0x01,\r
@@ -1379,7 +1435,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //关闭所有LED\r
                 uint8_t send_data = 0x00;\r
+#ifdef SUPPORT_PPG_SERVICE\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_LED_OFF_MODE_TEST);\r
+#endif\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_HRS,\r
                         0x02,\r
@@ -1388,6 +1446,7 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             } else if(testitem == 0x03)\r
             {\r
                 //打开心率检测\r
+#ifdef PPG_HX3695\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_SINGLE_CHECK_MODE_TEST);\r
                 LOS_Msleep(500);\r
                 FT_RESULTS_t ft_result = hx3695_factroy_test(SINGLE_CHECK_TEST);\r
@@ -1406,10 +1465,11 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                                     0x03,\r
                                     databuf,\r
                                     4);\r
-\r
+#endif\r
             } else if(testitem == 0x04)\r
             {\r
                 //打开血氧检测\r
+#ifdef PPG_HX3695\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_SINGLE_CHECK_MODE_TEST);\r
                 LOS_Msleep(500);\r
                 FT_RESULTS_t ft_result = hx3695_factroy_test(SINGLE_CHECK_TEST);\r
@@ -1428,16 +1488,15 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                                     0x04,\r
                                     databuf,\r
                                     4);\r
-\r
+#endif\r
             } else if(testitem == 0x05)\r
             {\r
+#ifdef PPG_HX3695\r
                 //灰卡测试\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_GRAYCARD_TEST);\r
-                LOS_Msleep(500);\r
-                FT_RESULTS_t ft_result = hx3695_factroy_test(GRAY_CARD_TEST);\r
-                send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);\r
+                LOS_Msleep(1000);\r
                 uint8_t databuf[12] = {0};\r
-\r
+                FT_RESULTS_t ft_result = hx3695_factroy_test(GRAY_CARD_TEST);\r
                 databuf[0] = (uint8_t)((ft_result.gr_data_final & 0xFF000000) >> 24);\r
                 databuf[1] = (uint8_t)((ft_result.gr_data_final & 0x00FF0000) >> 16);\r
                 databuf[2] = (uint8_t)((ft_result.gr_data_final & 0x0000FF00) >> 8);\r
@@ -1453,42 +1512,50 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 databuf[10] = (uint8_t)((ft_result.ir_data_final & 0x0000FF00) >> 8);\r
                 databuf[11] = (uint8_t)((ft_result.ir_data_final & 0x000000FF) >> 0);\r
 \r
-                PRINT("%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\r\n",\r
-                databuf[0],databuf[1],databuf[2],databuf[3],\r
-                databuf[4],databuf[5],databuf[6],databuf[7],\r
-                databuf[8],databuf[9],databuf[10],databuf[11]\r
-                );\r
-\r
-\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
-                                    BLE_TEST_CMD_SOFT_TEST_SUB_MODE_HRS,\r
-                                    0x05,\r
-                                    databuf,\r
-                                    12);\r
+                    BLE_TEST_CMD_SOFT_TEST_SUB_MODE_HRS,\r
+                    0x05,\r
+                    databuf,\r
+                    12);\r
+                send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);\r
+#endif\r
+                // PRINT("%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\r\n",\r
+                // databuf[0],databuf[1],databuf[2],databuf[3],\r
+                // databuf[4],databuf[5],databuf[6],databuf[7],\r
+                // databuf[8],databuf[9],databuf[10],databuf[11]\r
+                // );\r
+\r
 \r
             } else if(testitem == 0x06)\r
             {\r
                 //漏光测试\r
+                uint8_t databuf[12] = {0};\r
+\r
+                uint32_t green = 0;\r
+                uint32_t red = 0;\r
+                uint32_t ir = 0;\r
+\r
+#ifdef SUPPORT_PPG_SERVICE\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_LEAKLIGHT_TEST);\r
-                LOS_Msleep(500);\r
-                FT_RESULTS_t ft_result = hx3695_factroy_test(LEAK_LIGHT_TEST);\r
+                LOS_Msleep(1000);\r
+                ppg_get_leaklight_data(&green,&red,&ir);\r
                 send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);\r
-                uint8_t databuf[12] = {0};\r
+#endif\r
+                databuf[0] = (uint8_t)((green & 0xFF000000) >> 24);\r
+                databuf[1] = (uint8_t)((green & 0x00FF0000) >> 16);\r
+                databuf[2] = (uint8_t)((green & 0x0000FF00) >> 8);\r
+                databuf[3] = (uint8_t)((green & 0x000000FF) >> 0);\r
 \r
-                databuf[0] = (uint8_t)((ft_result.gr_data_final & 0xFF000000) >> 24);\r
-                databuf[1] = (uint8_t)((ft_result.gr_data_final & 0x00FF0000) >> 16);\r
-                databuf[2] = (uint8_t)((ft_result.gr_data_final & 0x0000FF00) >> 8);\r
-                databuf[3] = (uint8_t)((ft_result.gr_data_final & 0x000000FF) >> 0);\r
+                databuf[4] = (uint8_t)((red & 0xFF000000) >> 24);\r
+                databuf[5] = (uint8_t)((red & 0x00FF0000) >> 16);\r
+                databuf[6] = (uint8_t)((red & 0x0000FF00) >> 8);\r
+                databuf[7] = (uint8_t)((red & 0x000000FF) >> 0);\r
 \r
-                databuf[4] = (uint8_t)((ft_result.red_data_final & 0xFF000000) >> 24);\r
-                databuf[5] = (uint8_t)((ft_result.red_data_final & 0x00FF0000) >> 16);\r
-                databuf[6] = (uint8_t)((ft_result.red_data_final & 0x0000FF00) >> 8);\r
-                databuf[7] = (uint8_t)((ft_result.red_data_final & 0x000000FF) >> 0);\r
+                databuf[8] = (uint8_t)((ir & 0xFF000000) >> 24);\r
+                databuf[9] = (uint8_t)((ir & 0x00FF0000) >> 16);\r
+                databuf[10] = (uint8_t)((ir & 0x0000FF00) >> 8);\r
+                databuf[11] = (uint8_t)((ir & 0x000000FF) >> 0);\r
 \r
-                databuf[8] = (uint8_t)((ft_result.ir_data_final & 0xFF000000) >> 24);\r
-                databuf[9] = (uint8_t)((ft_result.ir_data_final & 0x00FF0000) >> 16);\r
-                databuf[10] = (uint8_t)((ft_result.ir_data_final & 0x0000FF00) >> 8);\r
-                databuf[11] = (uint8_t)((ft_result.ir_data_final & 0x000000FF) >> 0);\r
 \r
                 // PRINT("%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\r\n",\r
                 // databuf[0],databuf[1],databuf[2],databuf[3],\r
@@ -1732,6 +1799,13 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //查看iMei号\r
                 char* imei = uapi_dev_runtime_get_cat1_imei();\r
+                uint8_t retry = 0;\r
+                while(strlen(imei) == 0 && retry < 3)\r
+                {\r
+                    retry++;\r
+                    LOS_Msleep(2000);\r
+                    imei = uapi_dev_runtime_get_cat1_imei();\r
+                }\r
                 PRINT("imei : %s \r\n",imei);\r
         \r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
@@ -1748,8 +1822,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 for(int i = 0; i < 11; i++) \r
                     phone_number[i] = data[i] + '0';\r
                 phone_number[11] = '\0';\r
-\r
-                cat1_call_dial(phone_number);      \r
+#ifdef SUPPORT_CAT1_SERVICE\r
+                cat1_call_dial(phone_number);   \r
+#endif   \r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1,\r
                         0x07,\r
@@ -1761,8 +1836,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 //接听电话\r
                 uint8_t send_data = 0x00;\r
 \r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_call_answer();\r
-\r
+#endif\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1,\r
                         0x08,\r
@@ -1772,8 +1848,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //挂断电话\r
                 uint8_t send_data = 0x00;\r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_call_hungup();\r
-\r
+#endif\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1,\r
                         0x09,\r
@@ -1783,9 +1860,11 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //获取校准信息\r
                 uint8_t send_data = 0;\r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_at_cmd("at*mrd_cdf=Q,LteCalData.nvm");\r
-                LOS_Msleep(1000);\r
+                LOS_Msleep(500);\r
                 ble_get_cat1_at_msg((char *)&send_data,1);\r
+#endif\r
                 if(send_data == '1')\r
                     send_data = 1;\r
                 else\r
@@ -1799,9 +1878,11 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //设置强收模式\r
                 uint8_t send_data = 0;\r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_at_cmd("at+QRFTESTMODE=1");\r
-                LOS_Msleep(1000);\r
+                LOS_Msleep(500);\r
                 ble_get_cat1_at_msg((char *)&send_data,1);\r
+#endif\r
                 if(atol(send_data) == 0)\r
                     send_data = 1;\r
                 else\r
@@ -1816,9 +1897,11 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                 //查询信号值\r
                 char buf[20] = {0};\r
                 uint8_t send_data[2] = {0};\r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_at_cmd("AT+QRXFTM=\"LTE BAND1\",300,\"on\",75");\r
-                LOS_Msleep(1000);\r
+                LOS_Msleep(500);\r
                 ble_get_cat1_at_msg(buf,20);\r
+#endif\r
                 sscanf(buf, "+QRXFTM: -%d,-%d", (int *)&send_data[0], (int *)&send_data[1]);\r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1,\r
@@ -1829,9 +1912,11 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //关闭强接受\r
                 uint8_t send_data = 0;\r
+#ifdef SUPPORT_CAT1_SERVICE\r
                 cat1_at_cmd("AT+QRXFTM=\"LTE BAND1\",300,\"off\",75");\r
-                LOS_Msleep(1000);\r
+                LOS_Msleep(500);\r
                 ble_get_cat1_at_msg((char *)&send_data,1);\r
+#endif\r
                 if(atol(send_data) == 0)\r
                     send_data = 1;\r
                 else\r
@@ -1886,8 +1971,9 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
             {\r
                 //通讯录\r
                 uint8_t send_data = 0x00;\r
-\r
+            #ifdef BLE_INSTRUCT\r
                 add_addressbookToRead((char *)data);\r
+            #endif\r
                 \r
                 factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
                         BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CONTACTS,\r
index c802221..d541fd8 100644 (file)
Binary files a/code/sdk/application/wearable/service/msg_center/brandy-native-js-fd230/libmsg_center.a and b/code/sdk/application/wearable/service/msg_center/brandy-native-js-fd230/libmsg_center.a differ
diff --git a/code/sdk/application/wearable/service/msg_center/brandy-native-js-w9/libmsg_center.a b/code/sdk/application/wearable/service/msg_center/brandy-native-js-w9/libmsg_center.a
new file mode 100644 (file)
index 0000000..d541fd8
Binary files /dev/null and b/code/sdk/application/wearable/service/msg_center/brandy-native-js-w9/libmsg_center.a differ
index 4a7d10b..7921b8b 100644 (file)
@@ -928,41 +928,6 @@ void MsgCenterNotifyleaklightProc(const Topic topic, Request* req)
 {
     unused(topic);
     unused(req);
-    //req->data;
-    //green,red,ir
-    int green,red,ir;
-    char* str= (char *)req->data;
-    char *pchStrTmpIn = NULL;
-    
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%s",str);
-
-    char *tokbuf=NULL;
-    tokbuf=strtok_r(str,",",&pchStrTmpIn);
-    if(tokbuf!=NULL)
-    green=atoi(tokbuf);
-
-    tokbuf=strtok_r(NULL,",",&pchStrTmpIn);
-    if(tokbuf!=NULL)
-    red=atoi(tokbuf); 
-
-    tokbuf=strtok_r(NULL,"\0",&pchStrTmpIn);
-    if(tokbuf!=NULL)
-    ir=atoi(tokbuf);
-    
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%d,%d,%d",green,red,ir);
-#ifdef FD230
-    testhrsenson1View * t= testhrsenson1View::GetInstance();
-    if(t!=NULL)
-    {
-        t->setlightvalue(green,red,ir);
-    }
-
-    // testoldView * t_1= testoldView::GetInstance();
-    // if(t_1!=NULL)
-    // {
-    //     t_1->setlightvalue(green,red,ir);
-    // }
-#endif
 }
 
 //穿戴状态
index f045043..f6543ab 100755 (executable)
@@ -1928,6 +1928,105 @@ uint32_t at_nand_set_mode(uint8_t *data, uint32_t data_len)
     return ERRCODE_SUCC;\r
 }\r
 \r
+#if defined(SUPPORT_GNSS_SERVER)\r
+#include  "gnss_ctl.h"\r
+uint32_t gps_on(uint8_t *data, uint32_t data_len)\r
+{\r
+\r
+    char *ptr = (char *)data;\r
+    uint32_t mode = strtoul(ptr, NULL, 10);\r
+\r
+    wstp_print("gnss cmd: 0 switch to download , 1 switch to gnss , 2 load_cfg ,3 poweron ,4 poweroff, 5 start , 6 stop\r\n");\r
+    if (mode == 0) {\r
+        // osDelay(500);\r
+        wstp_print("0 switch to download\r\n");\r
+        download_gnss_switch(SWITCH_TO_DOWNLOAD);\r
+    }else if (mode == 1)  {\r
+        wstp_print("1 switch to gnss\r\n");\r
+        download_gnss_switch(SWITCH_TO_GNSS);\r
+    }else if (mode == 2)  {\r
+        const char* msg="2 gnss_load_cfg\r\n";\r
+        wstp_print(msg);\r
+        gnss_write_cmd(msg,strlen(msg));\r
+\r
+    }else if (mode == 3)  {\r
+        wstp_print("3 gnss_poweron\r\n");\r
+        gnss_power_on();\r
+    }else if (mode == 4)  {\r
+        wstp_print("4 gnss_poweroff\r\n");\r
+        gnss_power_off();\r
+    }else if (mode == 5)  {\r
+        wstp_print("5 gnss_start \r\n");\r
+        gnss_start();\r
+    \r
+    }else {\r
+        // osDelay(500);\r
+        wstp_print("6 gnss_stop\r\n");\r
+        gnss_stop();\r
+    }\r
+\r
+    return  ERRCODE_SUCC;\r
+}\r
+#else\r
+uint32_t gps_on(uint8_t *data, uint32_t data_len)\r
+{\r
+    return  ERRCODE_SUCC;\r
+}\r
+#endif\r
+/**\r
+ * \r
+ *     //    S_AGPIO_L23 CAT_1_PWR_ON ----- high power on\r
+    {   S_AGPIO_L23, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },\r
+   // S_AGPIO_L28   Cat1 reset  ---- low reset\r
+    {   S_AGPIO_L28, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },\r
+*/\r
+uint32_t cat1_on(uint8_t *data, uint32_t data_len)\r
+{\r
+\r
+\r
+    errcode_t ret=0;\r
+\r
+#if defined (BOARD_L22) || defined (BOARD_W9)\r
+    ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);\r
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);\r
+    // ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);\r
+    // if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L28,GPIO_DIRECTION_OUTPUT ret %d\n",ret);\r
+    ret=uapi_gpio_set_dir(S_AGPIO_L14,GPIO_DIRECTION_OUTPUT);\r
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L14,GPIO_DIRECTION_OUTPUT ret %d\n",ret);\r
+\r
+\r
+  \r
+    ret=uapi_gpio_set_val(S_AGPIO_L14, GPIO_LEVEL_LOW);   \r
+    PRINT("CAT1 VBAT OFF  set_value S_AGPIO_L14 GPIO_LEVEL_LOW  ret %d\n",ret);\r
+\r
+    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);   \r
+    PRINT("CAT1 poweroff  set_value S_AGPIO_L23 GPIO_LEVEL_HIGH  ret %d\n",ret);\r
+\r
+    // ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   \r
+    // PRINT("CAT1 reset set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);\r
+    \r
+    ret=uapi_gpio_set_val(S_AGPIO_L14, GPIO_LEVEL_HIGH);   \r
+    PRINT("CAT1 VBAT ON  set_value S_AGPIO_L14 GPIO_LEVEL_HIGH  ret %d\n",ret);\r
+  \r
+  \r
+    osDelay(1000);\r
+\r
+   \r
+    // ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   \r
+    // PRINT("CAT1 release-reset set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);\r
+\r
+    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_LOW);   \r
+    PRINT("CAT1 poweron  set_value S_AGPIO_L23 GPIO_LEVEL_LOW  ret %d\n",ret);\r
+\r
+    osDelay(1000);\r
+\r
+\r
+#endif\r
+    \r
+\r
+    return  ERRCODE_SUCC;\r
+}\r
+\r
 uint32_t lcd_fill(uint8_t *data, uint32_t data_len)\r
 {\r
     char *ptr = (char *)data;\r
index 647b9b2..34c9301 100755 (executable)
@@ -781,6 +781,10 @@ static void xip_and_save_ssb(void)
 
 static void fs_init(void)
 {
+#ifdef GPIO_POWERON_FLASH
+    uapi_gpio_set_dir(S_AGPIO_L18,GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(S_AGPIO_L18,GPIO_LEVEL_HIGH);
+#endif
 #ifdef CFG_DRIVERS_NANDFLASH
     nandflash_qspi_init();
 #endif
index 4051ee9..cef8d2b 100755 (executable)
@@ -6,6 +6,7 @@ set(COMPONENT_NAME "boot_nandflash")
 
 set(SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/nandflash_ds35x1g.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/nandflash_f35uqa001g.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nandflash_w25n01g.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nandflash_config.c
     ${CMAKE_CURRENT_SOURCE_DIR}/hal_nandflash.c
diff --git a/code/sdk/bootloader/flashboot/brandy/nandflash/include/nandflash_f35uqa001g.h b/code/sdk/bootloader/flashboot/brandy/nandflash/include/nandflash_f35uqa001g.h
new file mode 100644 (file)
index 0000000..29d0768
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+#ifndef NANDFLASH_F35UQA001G_H
+#define NANDFLASH_F35UQA001G_H
+
+#define F35UQA001G_BYTES_PER_PAGE  2048
+#define F35UQA001G_BYTES_PER_OOB   64
+#define F35UQA001G_PAGES_PER_BLOCK 64
+#define F35UQA001G_TOTAL_BLOCKS    1024
+#define F35UQA001G_CHIP_ID         0x6161
+#define F35UQA001G_OOB_TOTAL_LEN   4
+#define F35UQA001G_OOB_PER_SIZE    8
+#define F35UQA001G_OOB_1_OFFSET    0
+#define F35UQA001G_OOB_2_OFFSET    16
+#define F35UQA001G_OOB_3_OFFSET    32
+#define F35UQA001G_OOB_4_OFFSET    48
+
+extern struct nand_driver_struct g_f35uqa001g_driver;
+
+#endif /* End of #ifndef MC_NAND_F35UQA001G_H */
index ed49eb9..ea42c6d 100755 (executable)
@@ -15,6 +15,7 @@
 #include "hal_nandflash.h"\r
 #include "nandflash_ds35x1g.h"\r
 #include "nandflash_w25n01g.h"\r
+#include "nandflash_f35uqa001g.h"\r
 #include "nandflash_inner.h"\r
 #include "nandflash.h"\r
 #include "hal_nandflash.h"\r
@@ -28,7 +29,16 @@ uint32_t g_nandflash_init = 1;
 \r
 struct nand_driver_struct *get_nand_flash(void)\r
 {\r
-    return &g_ds35x1g_driver;\r
+    #if defined(NANDFLASH_DS35X) \r
+        // #warning "NANDFLASH_DS35X defined"\r
+        return &g_ds35x1g_driver;\r
+    #elif defined(NANDFLASH_F35UQA)\r
+        // #warning "NANDFLASH_F35UQA defined"\r
+        return &g_f35uqa001g_driver;\r
+    #else\r
+        // #warning "NANDFLASH_DS35X defined"\r
+        return &g_ds35x1g_driver;    \r
+    #endif\r
 }\r
 \r
 void nandflash_qspi_init(void)\r
diff --git a/code/sdk/bootloader/flashboot/brandy/nandflash/nandflash_f35uqa001g.c b/code/sdk/bootloader/flashboot/brandy/nandflash/nandflash_f35uqa001g.c
new file mode 100644 (file)
index 0000000..bcafeb0
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2018-2020. All rights reserved.
+ * Description:  NON-OS NANDFLASH DRIVER
+ * Author: @CompanyNameTag
+ * Create:  2020-10-15
+ */
+
+#include <stdint.h>
+#include "debug_print.h"
+#include "nandflash_inner.h"
+#include "nandflash.h"
+#include "hal_nandflash.h"
+#include "nandflash_config.h"
+#include "nandflash_f35uqa001g.h"
+
+#define F35UQA001G_GET_ECC_STATUS(x) ((0x30 & (x)) >> 4)
+#define F35UQA001G_ECC_CORRECTION 0x00
+#define F35UQA001G_ECC_1BIT_CORRET 0x01
+#define F35UQA001G_ECC_4BIT_CORRET 0x02
+#define F35UQA001G_ECC_ERROR 0x03
+#define NAND_ID_DATA_SIZE 0x2
+
+static qspi_data_type_def g_qspi_data = {0};
+
+static uint32_t mc_f35uqa001g_read_page(
+    uint32_t nand_page, uint8_t *data, uint32_t data_len, uint8_t *oob, uint32_t oob_len, const uint32_t *ecc_result)
+{
+    uint32_t ret;
+    uint8_t status_reg;
+
+    UNUSED(ecc_result);
+    ret = mc_flash_read_page(nand_page, data, data_len, oob, oob_len, &status_reg);
+    if (get_nand_flash()->enable_ecc == true) {
+        if (F35UQA001G_GET_ECC_STATUS(status_reg) >= F35UQA001G_ECC_ERROR) {
+            return MC_FAILURE;
+        } else {
+            return MC_SUCCESS;
+        }
+    }
+    return ret;
+}
+
+static uint32_t mc_f35uqa001g_init(void)
+{
+    nand_driver_init(SPEED_MID);
+    PRINT("f35uqa001g_init \r\n");
+    uint32_t ret;
+    mc_flash_write_cmd(CMD_FLASH_RESET); /* tRST 5us,no command will be accepted */
+    mc_flash_busy_wait();
+    write_cmd(CMD_FLASH_WREN);
+    ret = mc_flash_write_sr(CMD_FLASH_SR1_ADDR, 0x0); /* set SR1 0,Clear block protect bits */
+    if (get_nand_flash()->enable_ecc == true) {
+        ret = mc_flash_write_sr(CMD_FLASH_SR2_ADDR, 0x11); /* set SR1 0,Clear block protect bits */
+    } else {
+        ret = mc_flash_write_sr(CMD_FLASH_SR2_ADDR, 0x01); /* set SR1 0,Clear block protect bits */
+    }
+    PRINT("nandflash mc_flash_write_sr ret %d \r\n", ret);
+    uint8_t status_reg;
+    mc_flash_read_sr(CMD_FLASH_SR1_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash A0 Reg:0x%x \r\n", status_reg);
+    mc_flash_read_sr(CMD_FLASH_SR2_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash B0 Reg:0x%x \r\n", status_reg);
+    mc_flash_read_sr(CMD_FLASH_SR3_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash C0 Reg:0x%x \r\n", status_reg);
+    if (ret != MC_SUCCESS || status_reg != 0x2) {
+        return MC_FAILURE;
+    }
+    return MC_SUCCESS;
+}
+
+static uint16_t mc_f35uqa001g_check_id(void)
+{
+    g_qspi_data.instruction = CMD_FLASH_ID;
+    g_qspi_data.address_mode = MC_OSPI_ADDRESS_NONE;
+    g_qspi_data.address = 0;
+    g_qspi_data.address_size = 0;
+    g_qspi_data.dummy_cycles = MC_OSPI_CYCLES_8_BITS;
+    g_qspi_data.data_mode = MC_OSPI_DATA_1_LINE;
+    g_qspi_data.data_size = NAND_ID_DATA_SIZE;
+    uint16_t nand_flash_id = read_id(&g_qspi_data);
+    PRINT("nandflash id 0x%04X \r\n",nand_flash_id);
+    return nand_flash_id;
+}
+
+struct nand_driver_struct g_f35uqa001g_driver = {mc_f35uqa001g_init,
+    mc_f35uqa001g_check_id,
+    mc_f35uqa001g_read_page,
+    mc_flash_write_page,
+    mc_flash_erase_block,
+    mc_flash_mark_bad_block,
+    mc_flash_check_bad_block,
+    F35UQA001G_BYTES_PER_PAGE,
+    F35UQA001G_BYTES_PER_OOB,
+    F35UQA001G_PAGES_PER_BLOCK,
+    F35UQA001G_TOTAL_BLOCKS,
+    F35UQA001G_CHIP_ID,
+    F35UQA001G_OOB_TOTAL_LEN,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_1_OFFSET,
+    F35UQA001G_OOB_2_OFFSET,
+    F35UQA001G_OOB_3_OFFSET,
+    F35UQA001G_OOB_4_OFFSET,
+#ifdef ENABLE_ECC
+    true
+#else
+    false
+#endif
+    };
index 164486c..e2a25e6 100755 (executable)
@@ -123,7 +123,7 @@ target = {
                     'VIB_USE_PWM',
                     'CONFIG_PWM_SUPPORT',
                     # 'ACC_LIS2DOC',
-                    'ENABLE_CYWEE',
+                    'SUPPORT_CYWEE_SERVICE',
                     'ENABLE_CUSTOM_I2C',
                     'SUPPORT_AT_CYWEE',
                     'MAG_MMC5603',
@@ -189,7 +189,8 @@ target = {
                            "blemoder",
                            "transspecard",
                            "factorytest_service",
-                           "hid_service"
+                           "hid_service",
+                           'ppg_hal',
                                                  ],
         'ram_component_set': ['bgh', 'media', 'gpu', 'graphic_uikit', 'bgh_audio', 'dfx_set', 'ohos_set', 'wearable_set', 'alipay_set'],
         'dsp_version': 'max',
@@ -283,7 +284,7 @@ target = {
                      ,'A5133_DEMO_CLIENT'
                     ,'DISABLE_ENCODER'
                     ,'SUPPORT_A5133_SERVICE_BLE_PAIR'
-                    ,'-:ENABLE_CYWEE'
+                    ,'-:SUPPORT_CYWEE_SERVICE'
                     ,'-:SUPPORT_ALIPAY_SEC'
                     # 'WEARABLE_LOG_DEBUG',
                     # ,'A5133_USE_HW_SPI'
@@ -506,7 +507,73 @@ target = {
         'defines': [
             '-:CFG_FLASH_SIZE=8'
         ]
-    }
+    },
+    ################# FD230 ############################
+    'brandy-native-js-fd230': {
+        'base_target_name': 'brandy-native-js',
+        'defines': [
+                    'TPTYPE_FT6X46',
+                    'PPG_HX3695',
+                    'ROTARYENCODER_HX3507',
+                    'BOARD_FD230',
+                    'PPG_HX3695',
+                    ],
+               'image_analysis': False,
+               'fs_image_path':'fd230',
+               'fs_image': True
+    },
+
+    ################# w9 ############################
+    'brandy-native-js-w9': {
+        'base_target_name': 'brandy-native-js',
+        'defines': [
+                    '-:TPTYPE_FT6X46',
+                    '-:PPG_HX3695',
+                    '-:ROTARYENCODER_HX3507',
+                    '-:BOARD_FD230',
+                    'BOARD_W9',
+                    'SUPPORT_GNSS',
+                    'DISABLE_UART_LOG',
+                    'CONFIG_GNSS_UART_WITH_FLOWCTRL',
+                    'DOWNLOAD_GNSS_SWITCH',
+                    'TPTYPE_CST86XX',
+                    'NANDFLASH_F35UQA',
+                    #'PPG_GH3X2X',
+                    'GYRO_SH5001',
+                    'ROTARYENCODER_MIXO',
+                    ],
+               'ram_component': [
+                        "gnss",
+                        "gnss_sample",
+                        #"ppg_sensor_gh3x2x",
+                        "ppg_sensor_pah8009",
+                        #"bp_sensor",
+                        #'gyro',
+                        'ppg_hal',
+                           ],
+               'image_analysis': False,
+               'fs_image_path':'fd230',
+               'fs_image': True
+    },
+    'brandy-native-js-w9-r': {
+        'base_target_name': 'brandy-native-js-r',
+        #自定义配置项,选择硬件及功能参数
+        'defines': [
+            '-:TPTYPE_FT6X46',
+            'BOARD_W9',
+            'TPTYPE_CST86XX',
+            'NANDFLASH_F35UQA'
+        ],
+    },
+    'brandy-native-js-w9-ssb': {
+        'base_target_name': 'brandy-ssb',
+        #自定义配置项,选择硬件及功能参数
+        'defines': [
+            'BOARD_W9',
+            'GPIO_POWERON_FLASH',
+            'NANDFLASH_F35UQA'            
+        ]
+    },
 }
 
 target_group = {
@@ -527,6 +594,8 @@ target_group = {
     'pack_brandy_native_js_ct': ['brandy-ssb', 'brandy-native-js-r', 'brandy-native-js-ct'],
     'pack_brandy_native_js_cm': ['brandy-ssb', 'brandy-native-js-r', 'brandy-native-js-cm'],
     'pack_brandy_native_js_4part': ['brandy-ssb', 'brandy-native-js-r-4part', 'brandy-native-js-4part'],
+    'pack_brandy_native_js_w9': ['brandy-native-js-w9-ssb', 'brandy-native-js-w9-r', 'brandy-native-js-w9'],
+    'pack_brandy_native_js_fd230': ['brandy-ssb', 'brandy-native-js-r', 'brandy-native-js-fd230'],
     'pack_brandy_xts': ['brandy-ssb', 'brandy-xts-r', 'brandy-xts'],
     'pack_brandy_native_js_oob128': ['brandy-ssb-oob128', 'brandy-native-js-r', 'brandy-native-js-oob128'],
     'brandy_all': ['brandy-ssb',
index e36f8e8..de3c627 100755 (executable)
@@ -20,7 +20,7 @@
 //#include "service/a5133_service.h"
 #endif
 
-#ifdef ENABLE_CYWEE
+#ifdef SUPPORT_CYWEE_SERVICE
 extern void cywee_int_callback(pin_t pin, uintptr_t param);
 #endif
 /**
@@ -314,7 +314,7 @@ const hal_gpio_config_t g_gpio_function_config[PIN_MAX_NUMBER] = {
 //默认开启 EXT LDO V3.0 V1.8
     {   S_AGPIO_L18, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
 
-#ifdef ENABLE_CYWEE
+#ifdef SUPPORT_CYWEE_SERVICE
     /**G sensor G_INT1 S_AGPIO_L11 G_INT2 S_AGPIO_L19   采用timer 时这些中断要屏蔽*/
     {   S_AGPIO_L11, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_RISING_EDGE, cywee_int_callback },
     //{   S_AGPIO_L19, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_DEDGE, cywee_int_callback },
diff --git a/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h b/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h
new file mode 100644 (file)
index 0000000..a474299
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2018-2021. All rights reserved.
+ * Description:   brandy evb board config
+ * Author: @CompanyNameTag
+ * Create: 2020-02-19
+ */
+#ifndef BOARD_W9_CONFIG_H
+#define BOARD_W9_CONFIG_H
+
+#include "pinctrl_porting.h"
+#include "gpio_porting.h"
+#include "platform_types.h"
+
+#ifdef ENABLE_BN02
+extern void bp_int_callback(pin_t pin, uintptr_t param);
+#endif
+
+#ifdef SUPPORT_PPG_SERVICE
+extern void ppg_int_callback(pin_t pin, uintptr_t param);
+#endif
+
+#ifdef ENABLE_GYRO
+extern void gyro_int_callback(pin_t pin, uintptr_t param);
+#endif
+
+#ifdef ROTARYENCODER_MIXO
+// extern void mixo_int_callback(pin_t pin, uintptr_t param);
+#endif
+
+#ifdef SUPPORT_CYWEE_SERVICE
+extern void cywee_int_callback(pin_t pin, uintptr_t param);
+#endif
+
+/**
+ * @addtogroup connectivity_config_boards
+ * @{
+ */
+/**
+ * @brief  Global evb pio functions.
+ */
+const hal_pio_config_t g_pio_function_config[PIN_MAX_NUMBER] = {
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_EGPIO0
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },  // S_EGPIO1
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_EGPIO2
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_EGPIO3
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },  // S_EGPIO4 clk
+    { HAL_PIO_FUNC_QSPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },  // S_EGPIO5 cs
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_EGPIO6
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO7
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO8
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO9
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO10
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO11
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO12
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO13
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO14
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO15
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO16
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO17
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO18
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO19
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_EGPIO20
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN,  HAL_PIO_IE_ENBALE },   // S_EGPIO21
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX,  HAL_PIO_IE_DISABLE },   // S_EGPIO22 clk
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX,  HAL_PIO_IE_DISABLE },   // S_EGPIO23 ce
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN,  HAL_PIO_IE_ENBALE },    // S_EGPIO24
+    { HAL_PIO_FUNC_OPI, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN,  HAL_PIO_IE_ENBALE },    // S_EGPIO25
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO0 NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO1 NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO2 NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO3 NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO4 NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_HGPIO5 NC
+#if (defined CFG_DRIVERS_NANDFLASH)
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },   // S_HGPIO6
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },   // S_HGPIO7
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },   // S_HGPIO8
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },   // S_HGPIO9
+    { HAL_PIO_FUNC_GPIO,  HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_HGPIO10
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_HGPIO11 cs0
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },   // S_HGPIO12 cs1
+    { HAL_PIO_FUNC_GPIO,  HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_HGPIO13
+    { HAL_PIO_FUNC_GPIO,  HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_HGPIO14
+    { HAL_PIO_FUNC_QSPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_HGPIO15 clk
+#else
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO6
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO7
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO8
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO9
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO10  
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO11
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO12  
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO13  
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },     // S_HGPIO14  
+    { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_HGPIO15 emmc clk
+#endif
+    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO0   NC
+#ifdef BOARD_W9
+    { HAL_PIO_FUNC_I2C2_M3, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO1 I2C2 SCL Sensor 6轴 指南针 心率
+    { HAL_PIO_FUNC_I2C2_M3, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO2 I2C2 SDA Sensor
+#else
+    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO1   NC
+    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO2   NC
+#endif
+    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO3   NC
+
+// #if (defined BRANDY_PRODUCT_EVB4)
+    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO4   NC
+// #else
+    // { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_MGPIO4   NC
+// #endif
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },     // S_MGPIO5  NC
+    { HAL_PIO_FUNC_SPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },  // S_MGPIO6  SPI1 DI
+    { HAL_PIO_FUNC_SPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },  // S_MGPIO7 SPI1 DO
+    { HAL_PIO_FUNC_SPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },  // S_MGPIO8 SPI1 CLK
+    { HAL_PIO_FUNC_SPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_ENBALE },   // S_MGPIO9 SPI1 CS0
+    { HAL_PIO_FUNC_SPI1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_MGPIO10 SPI1 CS1 NC
+
+    { HAL_PIO_FUNC_I2C0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE }, // S_MGPIO11 i2c0 SCL NC
+    { HAL_PIO_FUNC_I2C0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE }, // S_MGPIO12 I2C0 SDA
+    { HAL_PIO_FUNC_I2C1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_MGPIO13 I2C1 SCL touch i2c
+    { HAL_PIO_FUNC_I2C1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_MGPIO14  I2C1 SDA
+#ifdef BOARD_W9
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },  // S_MGPIO15 I2C2 SCL Sensor 6轴 指南针 心率
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },  // S_MGPIO16 I2C2 SDA Sensor
+#else
+    { HAL_PIO_FUNC_I2C2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO15 I2C2 SCL Sensor 6轴 指南针 心率
+    { HAL_PIO_FUNC_I2C2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO16 I2C2 SDA Sensor
+#endif
+    { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO17 i2c3 SCL    smart pa\ 预留马达控制 \安全芯片
+    { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO18  I2C3 SDA
+    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },    // S_MGPIO19 uart1 tx
+    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },      // S_MGPIO20 uart1 rx
+    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_MGPIO21 uart1 rts
+    { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_MGPIO22 uart1 cts
+    { HAL_PIO_FUNC_SPI2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_MGPIO23 NC
+    { HAL_PIO_FUNC_SPI2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_MGPIO24 NC
+    { HAL_PIO_FUNC_SPI2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_MGPIO25 NC
+    { HAL_PIO_FUNC_SPI2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_MGPIO26 NC
+#if (defined QSPI_DISPLAY)
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO27
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO28
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO29
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO30
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO31
+    { HAL_PIO_FUNC_QSPI2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO32
+#else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO27
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO28
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO29
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO30
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO31
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_MGPIO32
+#endif
+    { HAL_PIO_FUNC_UART_HS_UART, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE }, // S_MGPIO33 huart tx
+    { HAL_PIO_FUNC_UART_HS_UART, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },   // S_MGPIO34 huart rx
+    { HAL_PIO_FUNC_UART_HS_UART, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },  // S_MGPIO35
+    { HAL_PIO_FUNC_UART_HS_UART, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },  // S_MGPIO36
+#if 0
+    { HAL_PIO_FUNC_UART2_M2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },     // S_MGPIO37 uart tx
+    { HAL_PIO_FUNC_UART2_M2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },       // S_MGPIO38 uart rx
+#else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },     // S_MGPIO37 uart tx  NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },       // S_MGPIO38 uart rx  NC
+#endif
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },     // S_AGPIO_L0  NC
+
+    { HAL_PIO_FUNC_I2S1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L1 i2s1
+    { HAL_PIO_FUNC_I2S1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L2
+    { HAL_PIO_FUNC_I2S1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L3
+    { HAL_PIO_FUNC_I2S1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L4
+
+    { HAL_PIO_FUNC_I2S0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L5
+    { HAL_PIO_FUNC_I2S0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_AGPIO_L6 i2s0
+    { HAL_PIO_FUNC_I2S0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_AGPIO_L7
+    { HAL_PIO_FUNC_I2S0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_AGPIO_L8
+
+#if (defined FT_BT_UART)
+    { HAL_PIO_FUNC_UART2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },  // S_AGPIO_L9 uart2 txd
+    { HAL_PIO_FUNC_UART2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },    // S_AGPIO_L10 uart2 rxd
+#else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_L9 dsp uart   TP35
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_L10 dsp uart   TP36
+#endif
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },    // S_AGPIO_L11 G_INT1
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_L12 i2c data HX3507_SDIO
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L13 i2c CLK HX3507_SCLK
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // S_AGPIO_L14   NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // S_AGPIO_L15   NC
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // S_AGPIO_L16   NC
+    
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_AGPIO_L17 HX3507_INT   not use
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },   // S_AGPIO_L18  VDDEN  //暂时无用,采用VDDIO 默认开启 EXt V3.0 EXt V1.8
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE },  // S_AGPIO_L19  G_INT2  //暂时不用 
+
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE }, // S_AGPIO_L20  0.2C_CHRG
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },    // S_AGPIO_L21  NTC_VDD_ON给低打开 NTC上拉电源
+#ifdef QSPI_DISPLAY
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_L22 QSPI TE
+#else
+    { HAL_PIO_FUNC_TE, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },      // S_AGPIO_L22 MIPI TE
+#endif
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L23 CAT_1_PWR_ON 控制CAT_1开机脚,或者控制 CAT1电源   拉高有效
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L24 LCM_EN
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L25  //////////// audio pa reset
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L26 心率复位 PPG reset
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L27    LCM reset
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L28    CAT_1复位 CAT1_RESET_N  拉低有效
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L29    charge done info 检测是否充满电
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_L30   KP_MKIN1 唤醒 CAT1 ,输出
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_L31    KP_MKOUIT1 唤醒 蓝牙 ,输入
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_AGPIO_L32    NC
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_R0   PRG_LED_POWER ON  心率等电源控制脚
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_R1   SE_REST 安全芯片复位唤醒脚
+//   #if VIB_USE_PWM
+    // { HAL_PIO_FUNC_PWMP1_M2, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_AGPIO_R2     VIBR_PWM 马达控制脚 兼容预留马达驱动复位脚
+    // { HAL_PIO_FUNC_PWMN1_M3, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_AGPIO_R2     VIBR_PWM 马达控制脚 兼容预留马达驱动复位脚
+//   #else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_AGPIO_R2     VIBR_PWM 马达控制脚 兼容预留马达驱动复位脚
+//   #endif
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE  },   // S_AGPIO_R3     NC   
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE  },    // S_AGPIO_R4     tp reset
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE  },   // S_AGPIO_R5     touch int
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_R6     PRG_INT 心率中断
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_R7     GYRO_INT2
+#ifdef ENABLE_GYRO
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_R8     GYRO_INT1
+#else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_R8     GYRO_INT1
+#endif
+
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_AGPIO_R9     BAT_CHARGE_OFF 关掉充电 温度高的时候
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_AGPIO_R10   Key2 ///////////////////HAL_PIO_IE_ENBALE input enable
+
+#if CORE == APPS
+    { HAL_PIO_FUNC_INVALID, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // ULP_GPIO0 mode not config
+    { HAL_PIO_FUNC_INVALID, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // ULP_GPIO1 mode not config
+    { HAL_PIO_FUNC_INVALID, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // ULP_GPIO2 mode not config
+    { HAL_PIO_FUNC_INVALID, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE }, // ULP_GPIO3 mode not config
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // ULP_GPIO4
+    { HAL_PIO_FUNC_SWD, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },       // ULP_GPIO5
+    { HAL_PIO_FUNC_SWD, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },       // ULP_GPIO6
+#endif
+};
+/**
+ * @}
+ */
+
+
+/**
+ * @addtogroup connectivity_config_boards
+ * @{
+ */
+/**
+ * @brief  Global evb gpio functions.
+ * 
+ * 
+ * typedef struct {
+    pin_t gpio;
+    hal_gpio_direction_t direction;
+    hal_gpio_level_t level;
+    uint32_t triger;
+    hal_gpio_callback_t callback;
+} hal_gpio_config_t;
+ */
+
+
+//默认开启Cat1 然后再根据配置决定是否关闭. 
+//默认不开启 ppg checkid失败,原因未知,暂时开机开启cat1
+#define DEFAULT_POWERON_CAT1 0
+
+//需要配置默认输出的,以及需要配置默认输入中断函数的。
+const hal_gpio_config_t g_gpio_function_config[PIN_MAX_NUMBER] = {
+
+#if DEFAULT_POWERON_CAT1
+    //    S_AGPIO_L23 CAT_1_PWR_ON ----- high power on
+    {   S_AGPIO_L23, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+   // S_AGPIO_L28   Cat1 reset  ---- low reset
+    {   S_AGPIO_L28, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+#else
+  //    S_AGPIO_L23 CAT_1_PWR_ON ----- high power on
+    {   S_AGPIO_L23, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+   // S_AGPIO_L28   Cat1 reset  ---- low reset
+    {   S_AGPIO_L28, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+#endif
+    // S_AGPIO_L17   HX3507_INT 
+    // {   S_AGPIO_L17, HAL_GPIO_DIRECTION_INPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+    // S_AGPIO_L12  SDIO_BT
+    {   S_AGPIO_L12, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+    // S_AGPIO_L13   SCLK_BT
+    {   S_AGPIO_L13, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+
+     // S_AGPIO_L26 心率复位 PPG reset
+    {   S_AGPIO_L26, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+    // S_AGPIO_R0 PRG_LED_POWER ON  心率等电源控制脚
+    {   S_AGPIO_R0, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+
+    //S_AGPIO_L21 NTC_VDD_ON 给低打开 NTC上拉电源 ,默认关闭
+    {   S_AGPIO_L21, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+#if 0  //默认正常充电 
+//    #define GPIO_PIN_ENABLE_CHARGE S_AGPIO_R9  //low enable
+// #define GPIO_PIN_ENABLE_CHARGE_0_2C S_AGPIO_L20   //low 0.2c 低电流充电
+    {   S_AGPIO_R9, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+    {   S_AGPIO_L20, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+#else
+    {   S_AGPIO_R9, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+    {   S_AGPIO_L20, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+#endif
+
+//默认关闭马达
+    {   S_AGPIO_R2, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+//默认开启 EXT LDO V3.0 V1.8
+    {   S_AGPIO_L18, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+
+#ifdef SUPPORT_CYWEE_SERVICE
+    /**G sensor G_INT1 S_AGPIO_L11 G_INT2 S_AGPIO_L19   采用timer 时这些中断要屏蔽*/
+    {   S_AGPIO_L11, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_RISING_EDGE, cywee_int_callback },
+    //{   S_AGPIO_L19, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_DEDGE, cywee_int_callback },
+#endif    
+    /**S_AGPIO_R1 GPO alipay默认resetpin*/
+    {   S_AGPIO_R1, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL },
+#ifdef SUPPORT_CAT1_SERVICE
+    /**cat1 ring input key*/
+    // {   S_AGPIO_L31, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_DEDGE,  cat1_ring_isr_callback},
+    // {   S_AGPIO_L31, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_RISING_EDGE,  cat1_ring_isr_callback},
+
+#endif
+#ifdef ENABLE_GYRO
+     {   S_AGPIO_R8, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_RISING_EDGE, gyro_int_callback },
+#else
+  /**S_AGPIO_L32 GPO gps reset*/
+    // {   S_AGPIO_L32, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL },
+#endif
+#ifdef ENABLE_BN02
+     {   S_AGPIO_R3, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_RISING_EDGE, bp_int_callback },
+#endif
+#ifdef SUPPORT_PPG_SERVICE
+    {   S_AGPIO_R6, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_FALLING_EDGE,  ppg_int_callback},
+#endif
+#ifdef ROTARYENCODER_MIXO
+    // {   S_AGPIO_L0, HAL_GPIO_DIRECTION_INPUT, NULL, GPIO_INTERRUPT_DEDGE,  mixo_int_callback},
+#endif
+};
+/**
+ * @}
+ */
+#endif
index 264e15c..c054b5e 100755 (executable)
 #define FT6X46_I2C_BUS                      I2C_BUS_1
 #define FT6X46_INT_GPIO                     S_AGPIO_R5
 #define FT6X46_RESET_GPIO                   S_AGPIO_R4
+#define CST86XX_I2C_BUS                      I2C_BUS_1
+#define CST86XX_INT_GPIO                     S_AGPIO_R5
+#define CST86XX_RESET_GPIO                   S_AGPIO_R4
 
 // TRACK MODE
 #define SND_TRACK_MODE_BT_MUSIC             0 // 参考 soc_uapi_sound.h 中 UAPI_SND_TRACK_STEREO 枚举
index 7479c76..ca609c5 100755 (executable)
  * Maximum UART buses
  * Defined here rather than in the uart_bus_t enum, due to needing to use it for conditional compilation
  */
+#ifdef DISABLE_UART_LOG
+#define UART_BUS_MAX_NUMBER 3  // !< Max number of UARTS available
+#else
 #define UART_BUS_MAX_NUMBER 2  // !< Max number of UARTS available
-
+#endif
 #define I2C_BUS_MAX_NUMBER  4  // !< Max number of I2C available
 #define I2C_4_IRQn I2C_0_IRQN
 #define I2C_5_IRQn I2C_0_IRQN
 #define CODELOADER_UART_TX_PIN S_MGPIO33
 #define CODELOADER_UART_RX_PIN S_MGPIO34
 
+#if 0
 #define LOG_UART_BUS    UART_BUS_1
 #define LOG_UART_TX_PIN     S_MGPIO33
 #define LOG_UART_RX_PIN     S_MGPIO34
 #define CHIP_FIXED_RX_PIN S_MGPIO34
 #endif
 #endif
+#endif
+#ifdef DISABLE_UART_LOG
+
+#define SW_DEBUG_UART_BUS UART_BUS_2
+#define CHIP_FIXED_TX_PIN PIN_NONE
+#define CHIP_FIXED_RX_PIN PIN_NONE
+
+#define LOG_UART_BUS UART_BUS_2
+#define LOG_UART_TX_PIN PIN_NONE
+#define LOG_UART_RX_PIN PIN_NONE
+#else
+
+#ifndef FT_SINGLE_UART
+#define SW_DEBUG_UART_BUS UART_BUS_0
+#define CHIP_FIXED_TX_PIN S_MGPIO19
+#define CHIP_FIXED_RX_PIN S_MGPIO20
+
+#define LOG_UART_BUS UART_BUS_0
+#define LOG_UART_TX_PIN S_MGPIO19
+#define LOG_UART_RX_PIN S_MGPIO20
+
+#else
+#define SW_DEBUG_UART_BUS UART_BUS_1
+#define CHIP_FIXED_TX_PIN S_MGPIO33
+#define CHIP_FIXED_RX_PIN S_MGPIO34
+
+#define LOG_UART_BUS UART_BUS_1
+#define LOG_UART_TX_PIN S_MGPIO33
+#define LOG_UART_RX_PIN S_MGPIO34
+
+#endif
+
+
+#endif
+
 #define CHIP_FIXED_UART_BUS UART_BUS_0
 
 #define QSPI_MAX_NUMBER    3
index 1497b01..aa54159 100755 (executable)
 #ifdef PRE_FPGA
 #include "board_fpga.h"
 #elif PRE_ASIC
+
+#if defined(BOARD_W9)
+#include "board_w9.h"
+#else
 #include "board_evb.h"
 #endif
+#endif
 #include "pinctrl.h"
 
 #ifndef BIT
index c172f7b..92a3077 100755 (executable)
@@ -96,6 +96,9 @@ uintptr_t uart_porting_base_addr_get(uart_bus_t bus)
 static bool g_sw_debug_uart_enabled = false;
 uint8_t g_uart0_rx_buffer[UART_RX_BUFFER_SIZE];
 uint8_t g_uart1_rx_buffer[UART_RX_BUFFER_SIZE];
+#ifdef DISABLE_UART_LOG
+uint8_t g_uart2_rx_buffer[UART_RX_BUFFER_SIZE];
+#endif
 #if defined(SUPPORT_AT_CMD)
 static void at_cmd_uart_rx_callback(const void *buf, uint16_t buf_len, bool remaining);
 #endif
@@ -243,6 +246,41 @@ static uart_config_t g_uart_config[UART_BUS_MAX_NUMBER] = {
         NULL,
         false
     }
+#ifdef DISABLE_UART_LOG
+    ,
+    /* UART_BUS_2 is used to hso uart */
+    {
+       
+        {
+            .tx_pin = PIN_NONE,
+            .rx_pin = PIN_NONE,
+            .cts_pin = PIN_NONE,
+            .rts_pin = PIN_NONE
+        },
+        {
+            .tx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
+            .rx_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
+            .cts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX,
+            .rts_pin_mode = (pin_mode_t)HAL_PIO_FUNC_MAX
+        },
+        RESERVED_80_IRQn,
+        NULL,
+        NULL,
+        {
+            .baud_rate = CUSTOM_UART_RATE,
+            .data_bits = UART_DATA_BIT_8,
+            .parity = UART_PARITY_NONE,
+            .stop_bits = UART_STOP_BIT_1,
+        },
+        {
+            .rx_buffer_size = UART_RX_BUFFER_SIZE,
+            .rx_buffer = g_uart2_rx_buffer,
+        },
+        NULL,
+        false
+    }
+
+#endif
 #endif
 };
 static uart_recovery_regs_t g_uart_recovery_reg[UART_BUS_MAX_NUMBER] = { 0 };
index 015f7a5..1b6e5a6 100755 (executable)
@@ -7,6 +7,7 @@ set(SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_ds35x1g.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_tc58cyg.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_w25n01g.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_f35uqa001g.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_config.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/hal_nandflash.c
     ${CMAKE_CURRENT_SOURCE_DIR}/nand/nandflash_to_os.c
diff --git a/code/sdk/drivers/drivers/driver/nand_flash/nand/include/nandflash_f35uqa001g.h b/code/sdk/drivers/drivers/driver/nand_flash/nand/include/nandflash_f35uqa001g.h
new file mode 100644 (file)
index 0000000..a6c6340
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef NANDFLASH_F35UQA001G_H
+#define NANDFLASH_F35UQA001G_H
+
+#define F35UQA001G_BYTES_PER_PAGE  2048
+#define F35UQA001G_BYTES_PER_OOB   64
+#define F35UQA001G_PAGES_PER_BLOCK 64
+#define F35UQA001G_TOTAL_BLOCKS    1024
+#define F35UQA001G_CHIP_ID         0x6161
+#define F35UQA001G_OOB_TOTAL_LEN   4
+#define F35UQA001G_OOB_PER_SIZE    8
+#define F35UQA001G_OOB_1_OFFSET    0
+#define F35UQA001G_OOB_2_OFFSET    16
+#define F35UQA001G_OOB_3_OFFSET    32
+#define F35UQA001G_OOB_4_OFFSET    48
+
+extern struct nand_driver_struct g_f35uqa001g_driver;
+
+#endif /* End of #ifndef MC_NAND_F35UQA001G_H */
index a56b6c3..e4f3566 100755 (executable)
@@ -25,6 +25,7 @@
 #include "nandflash_tc58cyg.h"
 #include "nandflash_ds35x1g.h"
 #include "nandflash_w25n01g.h"
+#include "nandflash_f35uqa001g.h"
 #include "nandflash_to_os.h"
 #include "nandflash_inner.h"
 #include "nandflash.h"
@@ -64,7 +65,16 @@ bool get_exception_status(void);
 
 struct nand_driver_struct *get_nand_flash(void)
 {
-    return &g_ds35x1g_driver;
+    #if defined(NANDFLASH_DS35X) 
+        // #warning "NANDFLASH_DS35X defined"
+        return &g_ds35x1g_driver;
+    #elif defined(NANDFLASH_F35UQA)
+        // #warning "NANDFLASH_F35UQA defined"
+        return &g_f35uqa001g_driver;
+    #else
+        // #warning "NANDFLASH_DS35X defined"
+        return &g_ds35x1g_driver;    
+    #endif
 }
 
 static int mount_partition_by_index(uint32_t index)
diff --git a/code/sdk/drivers/drivers/driver/nand_flash/nand/nandflash_f35uqa001g.c b/code/sdk/drivers/drivers/driver/nand_flash/nand/nandflash_f35uqa001g.c
new file mode 100644 (file)
index 0000000..e21b8db
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) @CompanyNameMagicTag 2018-2020. All rights reserved.
+ * Description:  NON-OS NANDFLASH DRIVER
+ * Author: @CompanyNameTag
+ * Create:  2020-10-15
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include "debug_print.h"
+#include "nandflash_inner.h"
+#include "nandflash.h"
+#include "hal_nandflash.h"
+#include "nandflash_config.h"
+#include "nandflash_f35uqa001g.h"
+
+#define F35UQA001G_GET_ECC_STATUS(x) ((0x30 & (x)) >> 4)
+#define F35UQA001G_ECC_CORRECTION 0x00
+#define F35UQA001G_ECC_1BIT_CORRET 0x01
+#define F35UQA001G_ECC_4BIT_CORRET 0x02
+#define F35UQA001G_ECC_ERROR 0x03
+#define NAND_ID_DATA_SIZE 0x2
+
+static qspi_data_type_def g_qspi_data = {0};
+
+static uint32_t mc_f35uqa001g_read_page(uint32_t nand_page, uint8_t *data, uint32_t data_len, uint8_t *oob,
+    uint32_t oob_len, const uint32_t *ecc_result, enum nandflash_trans_type type)
+{
+    unused(ecc_result);
+    uint32_t ret;
+    uint8_t status_reg;
+    ret = mc_flash_read_page(nand_page, data, data_len, oob, oob_len, &status_reg, type);
+    if (get_nand_flash()->enable_ecc == true) {
+        if (F35UQA001G_GET_ECC_STATUS(status_reg) >= F35UQA001G_ECC_ERROR) {
+            return MC_FAILURE;
+        } else {
+            return MC_SUCCESS;
+        }
+    }
+    return ret;
+}
+
+static uint32_t mc_f35uqa001g_init(void)
+{
+    nand_driver_init(SPEED_MID);
+    nand_driver_sem_init();
+    PRINT("f35uqa001g_init \r\n");
+    uint32_t ret;
+    mc_flash_write_cmd(CMD_FLASH_RESET); /* tRST 5us,no command will be accepted */
+    mc_flash_busy_wait();
+    write_cmd(CMD_FLASH_WREN);
+    ret = mc_flash_write_sr(CMD_FLASH_SR1_ADDR, 0x0); /* set SR1 0,Clear block protect bits */
+    if (get_nand_flash()->enable_ecc == true) {
+        ret = mc_flash_write_sr(CMD_FLASH_SR2_ADDR, 0x11); /* set SR1 0,Clear block protect bits */
+    } else {
+        ret = mc_flash_write_sr(CMD_FLASH_SR2_ADDR, 0x01); /* set SR1 0,Clear block protect bits */
+    }
+    uint8_t status_reg;
+    mc_flash_read_sr(CMD_FLASH_SR1_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash A0 Reg:0x%x \r\n", status_reg);
+    mc_flash_read_sr(CMD_FLASH_SR2_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash B0 Reg:0x%x \r\n", status_reg);
+    mc_flash_read_sr(CMD_FLASH_SR3_ADDR, (uint8_t *)&status_reg);
+    PRINT("nandflash C0 Reg:0x%x \r\n", status_reg);
+    if (ret != MC_SUCCESS || status_reg != 0x2) {
+        return MC_FAILURE;
+    }
+    return MC_SUCCESS;
+}
+
+static uint16_t mc_f35uqa001g_check_id(void)
+{
+    g_qspi_data.instruction = CMD_FLASH_ID;
+    g_qspi_data.address_mode = MC_OSPI_ADDRESS_NONE;
+    g_qspi_data.address = 0;
+    g_qspi_data.address_size = 0;
+    g_qspi_data.dummy_cycles = MC_OSPI_CYCLES_8_BITS;
+    g_qspi_data.data_mode = MC_OSPI_DATA_1_LINE;
+    g_qspi_data.data_size = NAND_ID_DATA_SIZE;
+    return read_id(&g_qspi_data);
+}
+
+struct nand_driver_struct g_f35uqa001g_driver = {mc_f35uqa001g_init,
+    mc_f35uqa001g_check_id,
+    mc_f35uqa001g_read_page,
+    mc_flash_write_page,
+    mc_flash_erase_block,
+    mc_flash_mark_bad_block,
+    mc_flash_check_bad_block,
+    F35UQA001G_BYTES_PER_PAGE,
+    F35UQA001G_BYTES_PER_OOB,
+    F35UQA001G_PAGES_PER_BLOCK,
+    F35UQA001G_TOTAL_BLOCKS,
+    F35UQA001G_CHIP_ID,
+    F35UQA001G_OOB_TOTAL_LEN,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_PER_SIZE,
+    F35UQA001G_OOB_1_OFFSET,
+    F35UQA001G_OOB_2_OFFSET,
+    F35UQA001G_OOB_3_OFFSET,
+    F35UQA001G_OOB_4_OFFSET,
+#ifdef ENABLE_ECC
+    true
+#else
+    false
+#endif
+    };
index 71a5095..76a9af1 100644 (file)
@@ -20,3 +20,4 @@ add_subdirectory_if_exist(vibrator/service)
 add_subdirectory_if_exist(cywee)
 add_subdirectory_if_exist(a5133)
 add_subdirectory_if_exist(entest)
+add_subdirectory_if_exist(gnss)
diff --git a/code/sdk/drivers/peripheral/gnss/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8516172
--- /dev/null
@@ -0,0 +1,76 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved.
+#===============================================================================
+
+add_subdirectory(driver)
+
+set(COMPONENT_NAME "gnss")
+# include(${CMAKE_CURRENT_SOURCE_DIR}/driver/CMakeLists.txt)
+set(SOURCES
+    # ${CMAKE_CURRENT_SOURCE_DIR}/gnss_config_array.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/uart_gnss.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gnss_ctl.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/NMEA0183.c
+    ${TIOT_SRC_LIST}
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/inc
+)
+set(PUBLIC_DEFINES
+    SUPPORT_GNSS_SERVER
+    CONFIG_DEV_GNSS=1
+    CONFIG_GNSS_DEV_NUM=1
+    CONFIG_GNSS_WAKEUP_TYPE_UART=1
+    CONFIG_GNSS_TCXO_FREQ_26M=1
+    CONFIG_GNSS_UART_BAUDRATE=115200
+    # CONFIG_GNSS_UART_WITH_FLOWCTRL
+    CONFIG_FILE_BY_ARRAY=1
+    CONFIG_FIRMWARE_CFG_HANDLE_PRIV=1
+    CONFIG_FIRMWARE_FILE_READ_BUF_LEN=1029
+    CONFIG_PM_WAKEUP_BY_UART=1
+    CONFIG_PM_MANAGE_LOWPOWER=1
+    CONFIG_XMIT_WITH_UART=1
+    CONFIG_UART_RX_MODE_BUFFED=1
+    CONFIG_XFER_PACKET_TIOT=1
+    CONFIG_XFER_DEFAULT_RX_BUFF=1
+    CONFIG_XFER_RX_BUFF_SIZE=512
+    CONFIG_OSAL_DEFINED=1
+    CONFIG_LIBBOUNDSCHECK_IMPLEMENTED=1
+    CONFIG_BOARD_DYNAMIC_ALLOC=1
+    CONFIG_GNSS_PACKET_BUFF_MAX=10000
+)
+
+set(PRIVATE_HEADER
+    ${TIOT_HEADER_LIST}
+)
+
+set(PRIVATE_DEFINES
+)
+
+# use this when you want to add ccflags like -include xxx
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+    -Wno-incompatible-function-pointer-types
+    -Wno-unused-function
+    # ${TIOT_CFLAGS}
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+message("TIOT_HEADER_LIST" ${TIOT_HEADER_LIST})
+message("TIOT_SRC_LIST" ${TIOT_SRC_LIST})
+
+build_component()
+
+
+
+add_subdirectory(sample/gnss_sample)
diff --git a/code/sdk/drivers/peripheral/gnss/driver/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2db3bc6
--- /dev/null
@@ -0,0 +1,73 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+# 此处为TIoT驱动顶层CMake
+
+# CMake读取Kconfig配置
+# function(KCONFIG_GET_PARAMS KCONFIG_PATH)
+#     file(STRINGS ${KCONFIG_PATH} TIOT_CONFIG_LIST ENCODING "UTF-8")
+
+#     foreach (CONFIG ${TIOT_CONFIG_LIST})
+#         # CONFIG maybe: CONFIG_CC_STACKPROTECTOR_STRONG=y
+
+#         # The first: variable name
+#         string(REGEX MATCH "[^=]+" CONFIG_VAR_NAME ${CONFIG})
+
+#         # The second: variable value
+#         string(REGEX MATCH "=(.+$)" CONFIG_VAR_VAL ${CONFIG})
+#         set(CONFIG_VAR_VAL ${CMAKE_MATCH_1})
+#         if(CONFIG_VAR_VAL MATCHES "^y$")
+#             set(${CONFIG_VAR_NAME} ${CONFIG_VAR_VAL} PARENT_SCOPE)
+#         endif()
+#     endforeach()
+# endfunction()
+
+# macro(add_subdirectory_if_exist _path)
+#     if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_path}/CMakeLists.txt)
+#         add_subdirectory(${_path})
+#     endif()
+# endmacro()
+
+# macro(list_sub_dirs result curdir)
+#   file(GLOB children RELATIVE ${curdir} ${curdir}/*)
+#   set(dirlist "")
+#   foreach(child ${children})
+#     if(IS_DIRECTORY ${curdir}/${child})
+#       list(APPEND dirlist ${child})
+#     endif()
+#   endforeach()
+#   set(${result} ${dirlist})
+# endmacro()
+
+if(NOT DEFINED TIOT_COMMON_DIR)
+    set(TIOT_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/common")
+endif()
+
+if(NOT DEFINED TIOT_PORTING_DIR)
+    set(TIOT_PORTING_DIR "${CMAKE_CURRENT_SOURCE_DIR}/product_porting")
+endif()
+
+if(NOT DEFINED TIOT_PORTING_CONFIG_DIR)
+    set(TIOT_PORTING_CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/product_porting")
+endif()
+
+# if(NOT DEFINED TIOT_DEVICE_LIST)
+#     list_sub_dirs(TIOT_DEVICE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/device)
+# endif()
+
+# 初始化CMake全局变量
+# set(TIOT_CFLAGS " -i ${TIOT_PORTING_CONFIG_DIR}/tiot_autoconfig.h" CACHE INTERNAL "tiot c flags" FORCE)
+# all header and files listed here
+set(TIOT_HEADER_LIST "${TIOT_PORTING_CONFIG_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "" CACHE INTERNAL "tiot src list" FORCE)
+
+# 获取Kconfig配置
+KCONFIG_GET_PARAMS(${TIOT_PORTING_CONFIG_DIR}/tiot_defconfig)
+
+add_subdirectory(device/gnss)
+
+# common
+add_subdirectory("${TIOT_COMMON_DIR}" common.out)
+# porting
+add_subdirectory("${TIOT_PORTING_DIR}" porting.out)
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a9f7cd3
--- /dev/null
@@ -0,0 +1,20 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+add_subdirectory(controller)
+add_subdirectory(fw_load)
+add_subdirectory(interface)
+add_subdirectory_if_exist(libboundscheck)
+add_subdirectory(pm)
+add_subdirectory(transfer)
+add_subdirectory(sys_msg_handler)
+add_subdirectory(utils)
+
+if(DEFINED CONFIG_COMMON_SUPPORT_DEBUG)
+add_subdirectory_if_exist(debug)
+endif()
+
+if(DEFINED CONFIG_COMMON_SUPPORT_DFR)
+add_subdirectory_if_exist(dfr)
+endif()
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/controller/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/controller/CMakeLists.txt
new file mode 100644 (file)
index 0000000..89ea3c5
--- /dev/null
@@ -0,0 +1,11 @@
+#===============================================================================\r
+# @brief    cmake make file\r
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+#===============================================================================\r
+set(\r
+    tiot_controller_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_controller.c\r
+)\r
+\r
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)\r
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_controller_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.c b/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.c
new file mode 100644 (file)
index 0000000..3fe85a0
--- /dev/null
@@ -0,0 +1,157 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: TIoT device controller. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-17, Create file. \n\r
+ */\r
+\r
+#include <stddef.h>\r
+#include "tiot_device_info.h"\r
+#include "tiot_controller.h"\r
+#include "tiot_board_log.h"\r
+\r
+#define CTRL_OPEN_COUNT_MAX  0xFFFFFFFFU\r
+\r
+int32_t tiot_controller_init(tiot_controller *ctrl, tiot_controller_info *info)\r
+{\r
+    int32_t ret;\r
+    tiot_board_info *board_info = info->board_info;\r
+    const tiot_device_info *device_info = info->dev_info;\r
+\r
+    if ((ctrl == NULL) || (ctrl->state == TIOT_CONTROLLER_INIT)) {\r
+        return -1;\r
+    }\r
+\r
+    /***** 软件初始化 *****/\r
+    /* 初始化open状态互斥锁. */\r
+    ret = osal_mutex_init(&ctrl->open_mutex);\r
+    if (ret != 0) {\r
+        goto mutex_init_fail;\r
+    }\r
+\r
+    /* 注册:1) PM状态机,如为NULL则使用默认状态机.\r
+             2)板级PM管脚信息,依据产品不同而不同. */\r
+    ret = tiot_pm_init(&ctrl->pm, board_info->hw_info.pm_info,\r
+                       device_info->pm_event_map, device_info->pm_event_map_size);\r
+    if (ret != 0) {\r
+        goto pm_init_fail;\r
+    }\r
+\r
+    /* 注册:1)固件加载回调,加载前 + 加载后,用于注册不同加载协议或设置波特率等,依据芯片不同而不同. */\r
+    ret = tiot_firmware_init(&ctrl->firmware, &device_info->exec_cbs);\r
+    if (ret != 0) {\r
+        goto fw_init_fail;\r
+    }\r
+\r
+    /* 注册:1) 接收回调 */\r
+    ret = tiot_xfer_init(&ctrl->transfer, board_info->hw_info.xmit_id, &device_info->xfer_info);\r
+    if (ret != 0) {\r
+        goto xfer_init_fail;\r
+    }\r
+\r
+    /* device info必须为静态分配变量. */\r
+    ctrl->dev_info = device_info;\r
+    ctrl->state = TIOT_CONTROLLER_INIT;\r
+    ctrl->dev_cus = (uintptr_t)info->dev_cus;\r
+\r
+    return 0;\r
+\r
+xfer_init_fail:\r
+    tiot_xfer_deinit(&ctrl->transfer);\r
+    memset_s((void *)&ctrl->transfer, sizeof(tiot_xfer_manager), 0, sizeof(tiot_xfer_manager));\r
+fw_init_fail:\r
+    memset_s((void *)&ctrl->firmware, sizeof(tiot_fw), 0, sizeof(tiot_fw));\r
+pm_init_fail:\r
+    memset_s((void *)&ctrl->pm, sizeof(tiot_pm), 0, sizeof(tiot_pm));\r
+    osal_mutex_destroy(&ctrl->open_mutex);\r
+mutex_init_fail:\r
+    return ret;\r
+}\r
+\r
+int32_t tiot_controller_open(tiot_controller *ctrl, void *param)\r
+{\r
+    int32_t ret = 0;\r
+    if (ctrl == NULL) {\r
+        tiot_print_dbg("[TIoT]device is null.\n");\r
+        return -1;\r
+    }\r
+    osal_mutex_lock(&ctrl->open_mutex);\r
+    if (ctrl->state == TIOT_CONTROLLER_UNINIT) {\r
+        tiot_print_err("[TIoT]dev state wrong %d.\r\n", ctrl->state);\r
+        ret = -1;\r
+        goto out;\r
+    }\r
+    if (ctrl->open_count == CTRL_OPEN_COUNT_MAX) {\r
+        tiot_print_err("[TIoT]reach max open count.\r\n");\r
+        ret = -1;\r
+        goto out;\r
+    }\r
+    ctrl->open_count++;\r
+    if (ctrl->state == TIOT_CONTROLLER_OPEN) {\r
+        /* 重复调用open仅添加计数. */\r
+        goto out;\r
+    }\r
+    ctrl->state = TIOT_CONTROLLER_OPENING; /* 中间状态,受mutex锁保护,不需要在open内判断. */\r
+    if (ctrl->ops.open(ctrl, param) != 0) {\r
+        ctrl->open_count--;\r
+        ctrl->state = TIOT_CONTROLLER_INIT;\r
+        ret = -1;\r
+        goto out;\r
+    }\r
+    ctrl->state = TIOT_CONTROLLER_OPEN;\r
+out:\r
+    osal_mutex_unlock(&ctrl->open_mutex);\r
+    return ret;\r
+}\r
+\r
+bool tiot_controller_check_opened(tiot_controller *ctrl)\r
+{\r
+    bool ret = true;\r
+    if (ctrl == NULL) {\r
+        tiot_print_dbg("[TIoT]device is null.\n");\r
+        return false;\r
+    }\r
+    osal_mutex_lock(&ctrl->open_mutex);\r
+    if (ctrl->state != TIOT_CONTROLLER_OPEN) {\r
+        tiot_print_dbg("[TIoT]device not opened.\n");\r
+        ret = false;\r
+    }\r
+    osal_mutex_unlock(&ctrl->open_mutex);\r
+    return ret;\r
+}\r
+\r
+void tiot_controller_close(tiot_controller *ctrl)\r
+{\r
+    if (ctrl == NULL) {\r
+        tiot_print_dbg("[TIoT]device is null.\n");\r
+        return;\r
+    }\r
+    osal_mutex_lock(&ctrl->open_mutex);\r
+    if ((ctrl->state != TIOT_CONTROLLER_OPEN) && (ctrl->state != TIOT_CONTROLLER_OPENING)) {\r
+        tiot_print_dbg("[TIoT]device is not opening or not opened.\n");\r
+        osal_mutex_unlock(&ctrl->open_mutex);\r
+        return;\r
+    }\r
+    /* 打开状态且open_count >=1时,减少open_count计数; 当open_count减少后变为0时,实际调用close操作. */\r
+    ctrl->open_count--;\r
+    if (ctrl->open_count == 0) {\r
+        ctrl->ops.close(ctrl);\r
+        ctrl->state = TIOT_CONTROLLER_INIT;\r
+    }\r
+    osal_mutex_unlock(&ctrl->open_mutex);\r
+}\r
+\r
+void tiot_controller_deinit(tiot_controller *ctrl)\r
+{\r
+    if ((ctrl == NULL) || (ctrl->state == TIOT_CONTROLLER_UNINIT)) {\r
+        return;\r
+    }\r
+\r
+    tiot_xfer_deinit(&ctrl->transfer);\r
+    tiot_pm_deinit(&ctrl->pm);\r
+    osal_mutex_destroy(&ctrl->open_mutex);\r
+    (void)memset_s((void *)ctrl, sizeof(tiot_controller), 0, sizeof(tiot_controller));\r
+    ctrl->state = TIOT_CONTROLLER_UNINIT;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.h b/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller.h
new file mode 100644 (file)
index 0000000..64a0dd3
--- /dev/null
@@ -0,0 +1,152 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: TIoT device controller header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-17, Create file. \n\r
+ */\r
+\r
+#ifndef TIOT_CONTROLLER_H\r
+#define TIOT_CONTROLLER_H\r
+\r
+#ifndef __KERNEL__\r
+#include <stdbool.h>\r
+#endif\r
+#include "tiot_board.h"\r
+#include "tiot_pm.h"\r
+#include "tiot_firmware.h"\r
+#include "tiot_xfer.h"\r
+#include "tiot_device_info.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_controller Controller\r
+ * @ingroup  tiot_common\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief TIoT controller state.\r
+ */\r
+typedef enum {\r
+    TIOT_CONTROLLER_UNINIT,\r
+    TIOT_CONTROLLER_INIT,\r
+    TIOT_CONTROLLER_OPENING,\r
+    TIOT_CONTROLLER_OPEN,\r
+} tiot_controller_state;\r
+\r
+/**\r
+ * @brief TIoT controller info provided outside.\r
+ */\r
+typedef struct {\r
+    tiot_board_info *board_info;       /*!< Board infomations. */\r
+    const tiot_device_info *dev_info;  /*!< Reserved device info, must be allocated staticly. */\r
+    const tiot_dev_customize *dev_cus; /*!< Reserved device customize. */\r
+} tiot_controller_info;\r
+\r
+struct _tiot_controller;\r
+\r
+/**\r
+ * @brief  TIoT controller ops.\r
+ */\r
+typedef struct {\r
+    int32_t (* open)(struct _tiot_controller *ctrl, void *param);\r
+    void (* close)(struct _tiot_controller *ctrl);\r
+    int32_t (* write)(struct _tiot_controller *ctrl, const uint8_t *data,\r
+                      uint32_t len, const tiot_xfer_tx_param *param);\r
+    int32_t (* read)(struct _tiot_controller *ctrl, uint8_t *buff, uint32_t buff_len, const tiot_xfer_rx_param *param);\r
+    int32_t (* pm_ctrl)(struct _tiot_controller *ctrl, uint8_t cmd);\r
+} tiot_controller_ops;\r
+\r
+/**\r
+ * @brief TIoT device controller.\r
+ */\r
+typedef struct _tiot_controller {\r
+    uint32_t state;                    /*!< Current state. */\r
+    tiot_pm pm;                        /*!< Power Manangement module. */\r
+    tiot_fw firmware;                  /*!< Firmware module. */\r
+    tiot_xfer_manager transfer;        /*!< Transfer manager modele. */\r
+    const tiot_device_info *dev_info;  /*!< Reserved device info, must be allocated staticly. */\r
+    tiot_controller_ops ops;           /*!< Controller ops, open, close, write, read. */\r
+    volatile uint32_t open_count;      /*!< open count. */\r
+    osal_mutex open_mutex;             /*!< open state mutex. */\r
+    uintptr_t dev_cus;                  /*!< device customize. */\r
+} tiot_controller;\r
+\r
+/**\r
+ * @brief  TIoT find controller by pin from controllers.\r
+ * @param  [in]  ctrls TIoT controller instances array.\r
+ * @param  [in]  ctrl_num TIoT controller instances num.\r
+ * @param  [in]  pin Pin number.\r
+ * @param  [in]  pin_type Pin type.\r
+ * @return if found controller, return controller pointer, else return NULL.\r
+ */\r
+static inline tiot_controller *tiot_find_controller_by_pin(tiot_controller *ctrls, uint8_t ctrl_num,\r
+                                                           uint32_t pin, uint32_t pin_type)\r
+{\r
+    const uint32_t *pm_info;\r
+    uint8_t i;\r
+    for (i = 0; i < ctrl_num; i++) {\r
+        pm_info = ctrls[i].pm.pm_info;\r
+        if (pm_info[pin_type] == pin) {\r
+            return &ctrls[i];\r
+        }\r
+    }\r
+    return NULL;\r
+}\r
+\r
+/**\r
+ * @brief  TIoT controller init.\r
+ * @param  [in]  ctrl TIoT controller instance.\r
+ * @param  [in]  info TIoT controller information.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_controller_init(tiot_controller *ctrl, tiot_controller_info *info);\r
+\r
+/**\r
+ * @brief  TIoT controller open, if already opened, add open count only.\r
+ * @param  [in]  ctrl TIoT controller instance.\r
+ * @param  [in]  param TIoT controller open param.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_controller_open(tiot_controller *ctrl, void *param);\r
+\r
+/**\r
+ * @brief  TIoT controller check opened or not, must be used after init.\r
+ * @param  [in]  ctrl TIoT controller instance.\r
+ * @return true if Opened;\r
+ *         false if not opened.\r
+ */\r
+bool tiot_controller_check_opened(tiot_controller *ctrl);\r
+\r
+/**\r
+ * @brief  TIoT controller close, if opened multiple times, only remove open count.\r
+ * @param  [in]  ctrl TIoT controller instance.\r
+ */\r
+void tiot_controller_close(tiot_controller *ctrl);\r
+\r
+/**\r
+ * @brief  TIoT controller deinit.\r
+ * @param  [in]  ctrl TIoT controller instance.\r
+ */\r
+void tiot_controller_deinit(tiot_controller *ctrl);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller_helper.h b/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_controller_helper.h
new file mode 100644 (file)
index 0000000..e0e02e1
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description: TIoT Controllrt helper. \n
+ *
+ * History: \n
+ * 2024-03-05, Create file. \n
+ */
+#ifndef TIOT_CONTROLLER_HELPER_H
+#define TIOT_CONTROLLER_HELPER_H
+
+#include "tiot_board_pin_port.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_controller_helper Controller Helper
+ * @ingroup  tiot_common_controllrt
+ * @{
+ */
+
+static inline void tiot_pin_int_request(uint32_t pin, tiot_pin_int_callback cb)
+{
+    if (pin != TIOT_PIN_NONE) {
+        (void)tiot_board_pin_register_int_callback(pin, cb);
+        (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_ENABLE);
+    }
+}
+
+static inline void tiot_pin_int_release(uint32_t pin)
+{
+    if (pin != TIOT_PIN_NONE) {
+        (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_DISABLE);
+        (void)tiot_board_pin_register_int_callback(pin, NULL);
+    }
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_device_info.h b/code/sdk/drivers/peripheral/gnss/driver/common/controller/tiot_device_info.h
new file mode 100644 (file)
index 0000000..cd4f54f
--- /dev/null
@@ -0,0 +1,78 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Device info header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-25, Create file. \n\r
+ */\r
+#ifndef TIOT_DEVICE_INFO_H\r
+#define TIOT_DEVICE_INFO_H\r
+\r
+#include "tiot_pm.h"\r
+#include "tiot_firmware.h"\r
+#include "tiot_xfer.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_device Device Interface\r
+ * @ingroup  tiot_common_interface\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief  Device common timing specs.\r
+ */\r
+typedef struct {\r
+    const uint32_t power_on_wait_ms;       /*!< Before power on wait time. */\r
+    const uint32_t boot_time_ms;           /*!< Boot wait time. */\r
+    const uint32_t init_time_ms;           /*!< Init time wait time. */\r
+    const uint32_t wakeup_pulse_ms;        /*!< Wakeup pin pulse time. */\r
+    const uint32_t wakeup_wait_ms;         /*!< Wakeup wait time. */\r
+    const uint32_t baud_change_wait_us;    /*!< Baudrate change wait time. */\r
+} tiot_device_timings;\r
+\r
+struct _tiot_controller;\r
+\r
+/**\r
+ * @brief  Device infomations to be registed in driver.\r
+ */\r
+typedef struct {\r
+    /*!< Power management event map, set NULL if use default event map. */\r
+    tiot_pm_event_entry *pm_event_map;\r
+    uint8_t pm_event_map_size;\r
+    /*!< Firmware callback called before and after commands execute. */\r
+    const tiot_fw_ops exec_cbs;\r
+\r
+    /*!< Transfer */\r
+    tiot_xfer_device_info xfer_info;\r
+\r
+    /*!< Tiot packet sys msg handle. */\r
+    void (*pkt_sys_msg_handle)(struct _tiot_controller *ctrl, uint8_t code);\r
+\r
+    tiot_device_timings timings;\r
+} tiot_device_info;\r
+\r
+typedef struct {\r
+    uintptr_t start_data;\r
+    uintptr_t curr_data;\r
+    uintptr_t end_data;\r
+    uint32_t unit_data_len;\r
+} tiot_dev_customize;\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4f6793e
--- /dev/null
@@ -0,0 +1,46 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+set(
+    tiot_firmware_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_firmware.c
+)
+
+set(
+    tiot_firmware_header_list
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+if(CONFIG_FIRMWARE_CFG_HANDLE_PRIV)
+list(APPEND
+     tiot_firmware_src_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_priv/tiot_cfg_handle_priv.c)
+
+list(APPEND
+     tiot_firmware_header_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_priv)
+endif()
+
+if(CONFIG_FIRMWARE_CFG_HANDLE_XCI)
+list(APPEND
+     tiot_firmware_src_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_xci/tiot_cfg_handle_xci.c)
+
+list(APPEND
+     tiot_firmware_header_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_xci)
+endif()
+
+if(CONFIG_FIRMWARE_CFG_HANDLE_HIBURN)
+list(APPEND
+     tiot_firmware_src_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_hiburn/tiot_cfg_handle_hiburn.c)
+
+list(APPEND
+     tiot_firmware_header_list
+     ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_hiburn)
+endif()
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_firmware_header_list}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_firmware_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c
new file mode 100644 (file)
index 0000000..b69bf1d
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-12-05, Create file. \n
+ */
+
+#include "tiot_misc.h"
+#include "tiot_firmware.h"
+#include "tiot_firmware_utils.h"
+#include "tiot_board_log.h"
+#include "tiot_cfg_handle_priv.h"
+
+#define TIOT_FW_FILE_STA        0x43
+#define TIOT_FW_FILE_ACK        0x06
+#define TIOT_FW_FILE_NAK        0x15
+#define TIOT_FW_PRIV_CMD_OK     'G'
+
+#define TIOT_FW_PRIV_ACK_MAX    128
+#define TIOT_FW_CUS_STR_LEN     12
+
+typedef enum {
+    TIOT_FW_EXTCMD_ACK = 0x0,
+    TIOT_FW_EXTCMD_ACK_EXT = 0x1,
+    TIOT_FW_EXTCMD_CUSTOMIZE = 0x2,
+    TIOT_FW_EXTCMD_NUM
+} tiot_fw_ext_cmd_priv;
+
+typedef int32_t (*priv_ext_cmd_handle_func)(tiot_fw *fw, const uint8_t *cmd, uint16_t len);
+typedef int32_t (*pre_priv_ext_cmd_handle_func)(tiot_fw *fw, uint8_t *cmd, uint16_t *len);
+
+static int32_t tiot_fw_ack_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len);
+static int32_t tiot_fw_ack_ext_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len);
+static int32_t tiot_fw_customize_ext_cmd_handle_priv(tiot_fw *fw, uint8_t *cmd, uint16_t *len);
+
+static const priv_ext_cmd_handle_func tiot_fw_priv_ext_cmd_table[TIOT_FW_EXTCMD_NUM] = {
+    tiot_fw_ack_handle_priv,
+    tiot_fw_ack_ext_handle_priv,
+    tiot_fw_ack_handle_priv,
+};
+
+static const pre_priv_ext_cmd_handle_func tiot_fw_pre_priv_ext_cmd_table[TIOT_FW_EXTCMD_NUM] = {
+    NULL,
+    NULL,
+    tiot_fw_customize_ext_cmd_handle_priv,
+};
+
+static int32_t tiot_fw_customize_para_replace(uint8_t *cmd, uint16_t *len, uint32_t cus_data)
+{
+    char *tmp = NULL;
+    size_t str_len;
+    char cus_data_str[TIOT_FW_CUS_STR_LEN] = { 0 };
+
+    if (*len == 0 || (cmd[*len - 1] != ' ')) {
+        tiot_print_err("[TIoT:priv] customize cmd not space-terminated.\r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    if (tiot_num_to_hex(cus_data, cus_data_str, TIOT_FW_CUS_STR_LEN) != TIOT_FW_LOAD_RET_OK) {
+        tiot_print_err("[TIoT:priv] tiot_num_to_hex failed.\r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    // cmd如下格式"WRITEM 4 0x3ff08 0x1e8480 "; tmp指向子串"0x1e8480"的起始地址.
+    cmd[*len - 1] = '\0';
+    tmp = strrchr((const char *)cmd, ' ');
+    if (tmp == NULL) {
+        tiot_print_err("[TIoT:priv] customize cmd string does not have space.\r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+    tmp++;
+
+    // 把tmp指向的字符串替换为tiot驱动配置的参数
+    int ret = strcpy_s((char *)tmp, strlen(tmp) + 1, cus_data_str);
+    if (ret != 0) {
+        tiot_print_err("[TIoT:priv] customize para replace failed. \r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    // cmd最后的'\0'替换为空格
+    str_len = strlen((const char *)cmd);
+    cmd[str_len] = ' ';
+
+    // 更新cmd的长度
+    *len = str_len + 1;
+    return TIOT_FW_LOAD_RET_OK;
+}
+
+static int32_t tiot_fw_ack_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len)
+{
+    int32_t ret = 0;
+    uint8_t ack = 0;
+    const uint8_t quit_cmd[] = "QUIT ";
+    // QUIT命令特殊处理
+    if ((len == (sizeof(quit_cmd) - 1)) && (memcmp(quit_cmd, cmd, len) == 0)) {
+        return 0;
+    }
+    ret = tiot_firmware_read(fw, &ack, sizeof(uint8_t));
+    if (ret != sizeof(uint8_t)) {
+        return -1;
+    }
+
+    tiot_print_dbg("[TIoT:priv]ack 0x%x\r\n", ack);
+    if ((ack == TIOT_FW_PRIV_CMD_OK) || (ack == TIOT_FW_FILE_STA) || (ack == TIOT_FW_FILE_ACK)) {
+        return TIOT_FW_LOAD_RET_OK;
+    } else if (ack == TIOT_FW_FILE_NAK) {
+        return TIOT_FW_LOAD_RET_RETRY;
+    }
+    return TIOT_FW_LOAD_RET_ERR;
+}
+
+static int32_t tiot_fw_ack_ext_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len)
+{
+    tiot_unused(cmd);
+    tiot_unused(len);
+    int32_t ret = 0;
+    uint8_t ack_buff[TIOT_FW_PRIV_ACK_MAX] = { 0 };
+    ret = tiot_firmware_read(fw, ack_buff, sizeof(ack_buff));
+    if ((ret <= 0) || ((uint32_t)ret > sizeof(ack_buff))) {
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+    tiot_print_info("[TIoT:fw]ack ext: ");
+    for (uint32_t i = 0; i < (uint32_t)ret; i++) {
+        tiot_print_info("0x%x ", ack_buff[i]);
+    }
+    tiot_print_info("\r\n");
+    return TIOT_FW_LOAD_RET_OK;
+}
+
+static int32_t tiot_fw_customize_ext_cmd_handle_priv(tiot_fw *fw, uint8_t *cmd, uint16_t *len)
+{
+    uint32_t cus_data;
+
+    tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware);
+    if (ctrl->dev_cus == 0) {
+        tiot_print_info("[TIoT:priv] customize is NULL.\r\n");
+        return TIOT_FW_LOAD_RET_OK;
+    }
+
+    if (tiot_firmware_customize_value_get(fw, &cus_data) != TIOT_FW_LOAD_RET_OK) {
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    return tiot_fw_customize_para_replace(cmd, len, cus_data);
+}
+
+int32_t tiot_fw_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t len)
+{
+    if (ext_cmd >= TIOT_FW_EXTCMD_NUM) {
+        tiot_print_err("[TIoT:fw]priv ext cmd exceed max!\r\n");
+        return -1;
+    }
+    return tiot_fw_priv_ext_cmd_table[ext_cmd](fw, cmd, len);
+}
+
+int32_t tiot_fw_pre_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *len)
+{
+    if (ext_cmd >= TIOT_FW_EXTCMD_NUM) {
+        tiot_print_err("[TIoT:fw]pre priv ext cmd exceed max!\r\n");
+        return -1;
+    }
+
+    if (tiot_fw_pre_priv_ext_cmd_table[ext_cmd] == NULL) {
+        return TIOT_FW_LOAD_RET_OK;
+    }
+
+    return tiot_fw_pre_priv_ext_cmd_table[ext_cmd](fw, cmd, len);
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h
new file mode 100644 (file)
index 0000000..23a4069
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT firmware load module private cfg handle. \n
+ *
+ * History: \n
+ * 2023-12-05, Create file. \n
+ */
+#ifndef TIOT_CFG_HANDLE_PRIV_H
+#define TIOT_CFG_HANDLE_PRIV_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_firmware_cfg_handle_priv CFG HANDLE PRIVATE
+ * @ingroup  tiot_common_firmware
+ * @{
+ */
+
+/**
+ * @brief  TIoT firmware private extend command handle.
+ * @param  [in]  fw TIoT firmware object.
+ * @param  [in]  ext_cmd Extend command.
+ * @param  [in]  cmd Firmware Command.
+ * @param  [in]  len Firmware Command length.
+ * @return if OK, return 0, if need retry ,return 1, else return -1.
+ */
+int32_t tiot_fw_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t len);
+
+/**
+ * @brief  TIoT firmware before private extend command handle.
+ * @param  [in]  fw TIoT firmware object.
+ * @param  [in]  ext_cmd Extend command.
+ * @param  [in]  cmd Firmware Command.
+ * @param  [in]  len Firmware Command length.
+ * @return if OK, return 0, if need retry ,return 1, else return -1.
+ */
+int32_t tiot_fw_pre_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *len);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.c b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.c
new file mode 100644 (file)
index 0000000..0219376
--- /dev/null
@@ -0,0 +1,277 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT firmware load module. \n
+ *
+ * History: \n
+ * 2023-03-30, Create file. \n
+ */
+#include "tiot_firmware.h"
+#include <stdbool.h>
+#include "tiot_firmware_utils.h"
+#include "securec.h"
+#include "tiot_board_log.h"
+
+#define FW_LEN_PER_SEND   64
+
+#define TIOT_FW_LOAD_FINISH    0
+#define TIOT_FW_LOAD_NEXT      1
+
+#define TIOT_FW_LOAD_RETRY_CNT 3
+
+#define TIOT_FW_EXT_VERSION1 0x1
+
+static inline uint32_t little_endian_to_u32(const uint8_t *data)
+{
+    uint32_t val;
+    val = data[0x3];
+    val <<= 0x8;
+    val |= data[0x2];
+    val <<= 0x8;
+    val |= data[0x1];
+    val <<= 0x8;
+    val |= data[0x0];
+    return val;
+}
+
+int32_t tiot_firmware_init(tiot_fw *fw, const tiot_fw_ops *ops)
+{
+    if ((fw == NULL) || (ops == NULL) || (ops->ext_cmd_handle == NULL)) {
+        tiot_print_dbg("[TIoT][fw]param invalid!\n");
+        return -1;
+    }
+    fw->ops = ops;
+    fw->fw_file = NULL;
+    return 0;
+}
+
+static int32_t tiot_firmware_pre_ext_cmd_write(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *cmd_len)
+{
+    int32_t ret = 0;
+
+    if (fw->ops->pre_ext_cmd_handle != NULL) {
+        ret = fw->ops->pre_ext_cmd_handle(fw, ext_cmd, cmd, cmd_len);
+    }
+    return ret;
+}
+
+static int32_t firmware_send_cmd(tiot_fw *fw, uint16_t ext_cmd, uint16_t cmd_len)
+{
+    uint16_t send_len;
+    uint16_t tmp_len;
+    // 加载时uart等接口每次最多发送64字节数据, 避免资源受限的场景申请大块内存
+    uint8_t cmd[FW_LEN_PER_SEND] = { 0 };
+    int32_t ret = 0;
+    uint16_t remain_len = cmd_len;
+
+    // 一个完整的命令分多次发送,每次发送FW_LEN_PER_SEND字节
+    do {
+        // 1, Get cmd data from file, maximum of 64 bytes each time.
+        send_len = (remain_len > FW_LEN_PER_SEND) ? FW_LEN_PER_SEND : remain_len;
+        ret = tiot_file_read(fw->fw_file, (char *)cmd, send_len, fw->cur_offset);
+        if (ret != send_len) {
+            tiot_print_err("[TIoT:fw]cmd content read fail\r\n");
+            return TIOT_FW_LOAD_RET_ERR;
+        }
+        fw->cur_offset += send_len;
+
+        // 2, Callback function before sending data.
+        tmp_len = send_len;
+        // 要确保需要处理的扩展命令长度都小于FW_LEN_PER_SEND字节(customize当前已保证),否则需要调整当前的分包发送逻辑
+        if (tiot_firmware_pre_ext_cmd_write(fw, ext_cmd, cmd, &tmp_len) != TIOT_FW_LOAD_RET_OK) {
+            tiot_print_err("[TIoT:fw]pre ext cmd handle failed.\r\n");
+            return TIOT_FW_LOAD_RET_ERR;
+        }
+
+        // 3, send data
+        ret = tiot_firmware_write(fw, cmd, tmp_len);
+        if (ret != tmp_len) {
+            tiot_print_err("[TIoT:fw]cmd content send fail\r\n");
+            return TIOT_FW_LOAD_RET_ERR;
+        }
+
+        remain_len -= send_len;
+    } while (remain_len > 0);
+
+    // 4, after the whole cmd data send, handle the cmd ack (注意: ext_cmd_handle只能使用最后一包cmd)
+    ret = fw->ops->ext_cmd_handle(fw, ext_cmd, cmd, tmp_len);
+    if (ret == TIOT_FW_LOAD_RET_RETRY) {
+        // 如果命令要重试,需复位文件指针, 以及customize数据指针(当前不实现,customize对应的命令不会返回RETRY)
+        fw->cur_offset -= cmd_len;
+    }
+
+    return ret;
+}
+
+static int32_t tiot_firmware_send_cmd_retry(tiot_fw *fw, uint16_t ext_cmd, uint16_t cmd_len)
+{
+    uint8_t retry_cnt;
+    int32_t ret = -1;
+
+    for (retry_cnt = 0; retry_cnt < TIOT_FW_LOAD_RETRY_CNT; retry_cnt++) {
+        ret = firmware_send_cmd(fw, ext_cmd, cmd_len);
+        if (ret != TIOT_FW_LOAD_RET_RETRY) {
+            break;
+        }
+        tiot_print_warning("[TIoT:fw]single cmd retry %d\r\n", retry_cnt);
+    }
+
+    if (ret == TIOT_FW_LOAD_RET_QUIT) {
+        tiot_print_info("[TIoT:fw]version matches, no need to upgrade firmware.\r\n");
+    } else if ((ret != TIOT_FW_LOAD_RET_OK) || (retry_cnt == TIOT_FW_LOAD_RETRY_CNT)) {
+        tiot_print_err("[TIoT:fw]cmd handle retry fail.\r\n");
+        ret = -1;
+    }
+
+    return ret;
+}
+
+static int32_t tiot_firmware_customize_index_init(tiot_fw *fw)
+{
+    tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware);
+    if (ctrl->dev_cus == 0) {
+        tiot_print_info("[TIoT:fw]tiot firmware no customize. \r\n");
+        return TIOT_FW_LOAD_RET_OK;
+    }
+
+    tiot_dev_customize *cus_ptr = (tiot_dev_customize *)ctrl->dev_cus;
+    cus_ptr->curr_data = cus_ptr->start_data;
+
+    return TIOT_FW_LOAD_RET_OK;
+}
+
+static int32_t tiot_firmware_load_cmds(tiot_fw *fw)
+{
+    int32_t ret;
+    uint16_t cmd_len, ext_cmd;
+
+    if (tiot_firmware_customize_index_init(fw) != TIOT_FW_LOAD_RET_OK) {
+        return -1;
+    }
+
+    do {
+        ret = tiot_file_read(fw->fw_file, (char *)&cmd_len, sizeof(uint16_t), fw->cur_offset);
+        // 处于文件末尾,读文件结束
+        if (ret == 0) {
+            break;
+        }
+        if (ret != sizeof(uint16_t)) {
+            tiot_print_err("[TIoT:fw]cmd len read fail\r\n");
+            ret = -1;
+            break;
+        }
+        ext_cmd = cmd_len >> 12;   // 拓展命令高4位, 右移12位
+        cmd_len = cmd_len & 0xFFF; // 长度为低12位
+
+        // 更新offset
+        fw->cur_offset += sizeof(uint16_t);
+
+        ret = tiot_firmware_send_cmd_retry(fw, ext_cmd, cmd_len);
+        if (ret != 0) {
+            break;
+        }
+    } while (true);
+
+    return ret == TIOT_FW_LOAD_RET_QUIT ? 0 : ret;
+}
+
+static inline int32_t firmware_read_u32(tiot_fw *fw, uint32_t *val)
+{
+    uint8_t data[4];
+    int32_t ret = tiot_file_read(fw->fw_file, (char *)data, sizeof(uint32_t), fw->cur_offset);
+    if (ret != sizeof(uint32_t)) {
+        return -1;
+    }
+    fw->cur_offset += sizeof(uint32_t);
+    *val = little_endian_to_u32(data);
+    return 0;
+}
+
+static int32_t firmware_load_ext_version1(tiot_fw *fw, tiot_fw_ext_version1 *ext)
+{
+    if (firmware_read_u32(fw, &ext->file_len) != 0) {
+        tiot_print_err("[TIoT:fw]read img file size fail.\n");
+        return -1;
+    }
+    tiot_print_info("[TIoT:fw]img file size = %d\n", ext->file_len);
+    return 0;
+}
+
+static int32_t tiot_firmware_load_file(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name)
+{
+    uint32_t version;
+    int32_t ret = -1;
+    tiot_fw_ext_version1 ext = { 0 };
+
+    /* 初始化时保证cfg_path不为null */
+    fw->fw_file = tiot_file_open(file_path, file_name, OSAL_O_RDONLY, 0);
+    if (fw->fw_file == NULL) {
+        tiot_print_err("open file %s fail\n", file_name);
+        return ret;
+    }
+    /* 读取镜像格式版本号 */
+    fw->cur_offset = 0;  /* 从偏移量为0开始读取镜像格式版本号 */
+    if (firmware_read_u32(fw, &version) != 0) {
+        goto file_close;
+    }
+    tiot_print_info("[TIoT:fw]cfg img version: 0x%x\n", version);
+    if (version == TIOT_FW_EXT_VERSION1) { /* 存在拓展区 */
+        if (firmware_load_ext_version1(fw, &ext) != 0) {
+            goto file_close;
+        }
+#ifdef CONFIG_FILE_BY_ARRAY
+        fw->fw_file->len = ext.file_len;
+#else
+        tiot_print_warning("[TIoT:fw]non file-array should not use ext version1.\n");
+#endif
+    }
+    // 读取发送命令
+    ret = tiot_firmware_load_cmds(fw);
+file_close:
+    tiot_file_close(fw->fw_file);
+    fw->fw_file = NULL;
+    return ret;
+}
+
+int32_t tiot_firmware_load(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name)
+{
+    if (fw == NULL || file_name == NULL) {
+        tiot_print_dbg("[TIoT][fw]fw object or file_name is NULL.\n");
+        return -1;
+    }
+    if (fw->ops->pre_cmd_execute != NULL) {
+        tiot_print_info("[TIoT][fw]Pre command execute\n");
+        fw->ops->pre_cmd_execute(fw);
+    }
+    /* 执行cfg镜像内命令 */
+    if (tiot_firmware_load_file(fw, file_path, file_name) != 0) {
+        tiot_print_err("[TIoT][fw]command execute err!\n");
+        return -1;
+    }
+    if (fw->ops->after_cmd_execute != NULL) {
+        tiot_print_info("[TIoT][fw]After command execute\n");
+        fw->ops->after_cmd_execute(fw);
+    }
+    return 0;
+}
+
+int32_t tiot_firmware_customize_value_get(tiot_fw *fw, uint32_t *cus_data)
+{
+    tiot_dev_customize *cus_ptr;
+
+    tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware);
+    if (ctrl->dev_cus == 0) {
+        tiot_print_err("[TIoT:fw]customize dev_cus is NULL.\r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    cus_ptr = (tiot_dev_customize *)ctrl->dev_cus;
+    if (cus_ptr->curr_data > cus_ptr->end_data) {
+        tiot_print_err("[TIoT:fw] firmware customize get overflow.\r\n");
+        return TIOT_FW_LOAD_RET_ERR;
+    }
+
+    *cus_data = *(uint32_t *)(cus_ptr->curr_data);
+    cus_ptr->curr_data += cus_ptr->unit_data_len;
+    return TIOT_FW_LOAD_RET_OK;
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.h b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware.h
new file mode 100644 (file)
index 0000000..37d184d
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT firmware load module. \n
+ *
+ * History: \n
+ * 2023-12-05, Create file. \n
+ */
+#ifndef TIOT_FIRMWARE_H
+#define TIOT_FIRMWARE_H
+
+#include "tiot_types.h"
+#include "tiot_board.h"
+#include "tiot_fileops.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_firmware_load Firmware Load
+ * @ingroup  tiot_common
+ * @{
+ */
+
+#ifdef CONFIG_FILE_BY_ARRAY
+#define TIOT_FW_FILE_ARRAY_CFG_NAME   "cfg"
+#endif
+
+typedef enum {
+    TIOT_FW_LOAD_RET_ERR = -1,
+    TIOT_FW_LOAD_RET_OK = 0,
+    TIOT_FW_LOAD_RET_RETRY = 1,
+    TIOT_FW_LOAD_RET_QUIT = 2,
+} tiot_fw_ret;
+
+/*
+    固件文件格式:
+        | Version | Extended Info | Command1 | Command2 | ... | CommandN |
+        |---------|---------------|----------|----------|-----|----------|
+        | 4bytes  |      --       |     -    |     -    |     |     -    |
+    单条命令格式:
+        | ext_cmd | cmd_len |  cmd   |
+        |---------|---------|--------|
+        |       2bytes      | Nbytes |
+        | [12:15] | [0:11]  |        |
+*/
+
+/**
+ * @brief  TIoT firmware extended infos.
+ */
+typedef struct {
+    uint32_t file_len; /*!< img file size */
+} tiot_fw_ext_version1;
+
+struct _tiot_fw;
+
+/**
+ * @brief  TIoT firmware command execute callbacks.
+ */
+typedef struct {
+    void (* pre_cmd_execute)(struct _tiot_fw *fw);   /*!< Before command execute. */
+    void (* after_cmd_execute)(struct _tiot_fw *fw); /*!< After command execute. */
+     /*!< After single command execute. */
+    int32_t (* ext_cmd_handle)(struct _tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t cmd_len);
+    /*!< Before single command execute. */
+    int32_t (* pre_ext_cmd_handle)(struct _tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *cmd_len);
+} tiot_fw_ops;
+
+/**
+ * @brief  TIoT firmware object.
+ */
+typedef struct _tiot_fw {
+    const tiot_fw_ops *ops;        /*!< Firmware ops. */
+    tiot_file *fw_file;            /*!< Firmware file pointer. */
+    uint32_t cur_offset;           /*!< Firmware file offset. */
+} tiot_fw;
+
+/**
+ * @brief  TIoT firmware object init.
+ * @param  [in]  fw           TIoT firmware object.
+ * @param  [in]  ops     Firmware command execute callbacks.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_firmware_init(tiot_fw *fw, const tiot_fw_ops *ops);
+
+/**
+ * @brief  TIoT firmware start load process.
+ * @param  [in]  fw TIoT firmware object.
+ * @param  [in]  file_path TIoT firmware load file path.
+ * @param  [in]  file_name TIoT firmware load file name.
+ * @param  [in/out] fw_cmd_info TIoT firmware load command info.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_firmware_load(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name);
+
+
+/**
+ * @brief  TIoT firmware obtaining customized parameters.
+ * @param  [in]  fw TIoT firmware object.
+ * @param  [out] cus_data customized parameter.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_firmware_customize_value_get(tiot_fw *fw, uint32_t *cus_data);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware_utils.h b/code/sdk/drivers/peripheral/gnss/driver/common/fw_load/tiot_firmware_utils.h
new file mode 100644 (file)
index 0000000..a4b7e0f
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT firmware load module utils. \n
+ *
+ * History: \n
+ * 2023-12-05, Create file. \n
+ */
+#ifndef TIOT_FIRMWARE_UTILS_H
+#define TIOT_FIRMWARE_UTILS_H
+
+#include "tiot_firmware.h"
+#include "tiot_controller.h"
+#include "tiot_xfer.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_firmware_utils Firmware Utils
+ * @ingroup  tiot_common_firmware
+ * @{
+ */
+
+static inline int32_t tiot_firmware_write(tiot_fw *fw, const uint8_t *data, uint32_t len)
+{
+    tiot_controller *controller = tiot_container_of(fw, tiot_controller, firmware);
+    return tiot_xfer_send(&controller->transfer, data, len, NULL);
+}
+
+static inline int32_t tiot_firmware_read_timeout(tiot_fw *fw, uint8_t *data, uint32_t len, uint32_t timeout_ms)
+{
+    tiot_xfer_rx_param rx_param = { 0 };
+    tiot_controller *controller = tiot_container_of(fw, tiot_controller, firmware);
+    rx_param.timeout = timeout_ms;
+    rx_param.subsys  = 0;
+    return tiot_xfer_recv(&controller->transfer, data, len, &rx_param);
+}
+
+static inline int32_t tiot_firmware_read(tiot_fw *fw, uint8_t *data, uint32_t len)
+{
+    return tiot_firmware_read_timeout(fw, data, len, TIOT_XFER_RECV_WAIT_FOREVER);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/interface/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fc47d89
--- /dev/null
@@ -0,0 +1,20 @@
+#===============================================================================\r
+# @brief    cmake make file\r
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+#===============================================================================\r
+set(\r
+    tiot_interface_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_internal/tiot_board_xmit_ops.c\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/device_interface/tiot_service_interface.c\r
+)\r
+\r
+set(\r
+    interface_header_lists\r
+    "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_internal"\r
+    "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_porting"\r
+    "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/osal_porting"\r
+    "${CMAKE_CURRENT_SOURCE_DIR}/device_interface"\r
+)\r
+\r
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${interface_header_lists}" CACHE INTERNAL "tiot header list" FORCE)\r
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_interface_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h
new file mode 100644 (file)
index 0000000..cae119b
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-07-04, Create file. \n
+ */
+#ifndef TIOT_BOARD_H
+#define TIOT_BOARD_H
+
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_board_internal_base Board
+ * @ingroup  tiot_common_interface_board_internal
+ * @{
+ */
+
+/**
+ * @brief  TIoT common board pins.
+ */
+typedef enum {
+    TIOT_PIN_POWER_CTRL,
+    TIOT_PIN_HOST_WAKEUP_DEVICE,
+    TIOT_PIN_DEVICE_WAKEUP_HOST,
+    TIOT_PIN_MAX
+} tiot_board_pin;
+
+/**
+ * @brief  Board hardware infomations.
+ */
+typedef struct {
+    uintptr_t xmit_id;         /*!< Transmit(UART/I2C/SPI/...) port index. */
+    const uint32_t *pm_info;   /*!< Power manager related infomations. */
+} tiot_board_hw_info;
+
+/**
+ * @brief  Board infomations, includes hardware infos and firmware info.
+ */
+typedef struct {
+    tiot_board_hw_info hw_info;       /*!< Power manager related infomations. */
+} tiot_board_info;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h
new file mode 100644 (file)
index 0000000..b5a9b92
--- /dev/null
@@ -0,0 +1,81 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board log header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-24, Create file. \n\r
+ */\r
+#ifndef TIOT_BOARD_LOG_H\r
+#define TIOT_BOARD_LOG_H\r
+\r
+#include "tiot_board_log_port.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_board_internal_log Board Log\r
+ * @ingroup  tiot_common_interface_board_internal\r
+ * @{\r
+ */\r
+\r
+#define TIOT_LOG_ALERT    0   /*!< Log level alert. */\r
+#define TIOT_LOG_ERR      1   /*!< Log level error. */\r
+#define TIOT_LOG_WARNING  2   /*!< Log level warning. */\r
+#define TIOT_LOG_INFO     3   /*!< Log level info. */\r
+#define TIOT_LOG_DEBUG    4   /*!< Log level debug. */\r
+\r
+#ifndef TIOT_BOARD_LOG_LEVEL\r
+#define TIOT_BOARD_LOG_LEVEL  TIOT_LOG_DEBUG\r
+#endif\r
+\r
+/* 宏定义 */\r
+#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_DEBUG\r
+#define TIOT_PRINT_FUNCTION_NAME    BOARD_PRINT_FUNCTION_NAME\r
+#define tiot_print_dbg(s, ...)  board_print_dbg(s, ##__VA_ARGS__)\r
+#else\r
+#define TIOT_PRINT_FUNCTION_NAME\r
+#define tiot_print_dbg(s, ...)\r
+#endif\r
+\r
+#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_INFO\r
+#define tiot_print_info(s, ...)  board_print_info(s, ##__VA_ARGS__)\r
+#define tiot_print_suc(s, ...)   board_print_suc(s, ##__VA_ARGS__)\r
+#else\r
+#define tiot_print_info(s, ...)\r
+#define tiot_print_suc(s, ...)\r
+#endif\r
+\r
+#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_WARNING\r
+#define tiot_print_warning(s, ...)  board_print_warning(s, ##__VA_ARGS__)\r
+#else\r
+#define tiot_print_warning(s, ...)\r
+#endif\r
+\r
+#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_ERR\r
+#define tiot_print_err(s, ...)      board_print_err(s, ##__VA_ARGS__)\r
+#else\r
+#define tiot_print_err(s, ...)\r
+#endif\r
+\r
+#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_ALERT\r
+#define tiot_print_alert(s, ...)      board_print_alter(s, ##__VA_ARGS__)\r
+#else\r
+#define tiot_print_alert(s, ...)\r
+#endif\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h
new file mode 100644 (file)
index 0000000..6a23acb
--- /dev/null
@@ -0,0 +1,64 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board transmit io common header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-25, Create file. \n\r
+ */\r
+#ifndef TIOT_BOARD_XMIT_H\r
+#define TIOT_BOARD_XMIT_H\r
+\r
+#include "tiot_types.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_board_internal_xmit Board Transmit\r
+ * @ingroup  tiot_common_interface_board_internal\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief  Transmit handle, compatible for board transmit handle.\r
+ */\r
+typedef void *tiot_xmit_handle;\r
+\r
+/**\r
+ * @brief  Universal transmit config, compatible for all types of transmit io.\r
+ */\r
+struct tiot_xmit_config;\r
+\r
+/**\r
+ * @brief  Transmit object.\r
+ */\r
+typedef struct {\r
+    uintptr_t id;               /*!< Transmit io id.\r
+                                     If board io operations use index, set this id in port open interface. */\r
+    tiot_xmit_handle handle;    /*!< Transmit handle compatible for board io handle.\r
+                                     If board io operations use handle, set this handle in port open interface. */\r
+} tiot_xmit;\r
+\r
+/**\r
+ * @brief  Transmit callbacks, registed in port open interface.\r
+ */\r
+typedef struct {\r
+    /*!< Rx data receive notify callback when use asynchronous board interface to read data. */\r
+    void (*rx_notify)(tiot_xmit *xmit, uint8_t *data, uint32_t len);\r
+} tiot_xmit_callbacks;\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c
new file mode 100644 (file)
index 0000000..32741b1
--- /dev/null
@@ -0,0 +1,62 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board Transmit select. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-27, Create file. \n\r
+ */\r
+#include "tiot_board_xmit_ops.h"\r
+\r
+const tiot_xmit_ops g_tiot_xmit_ops_map[TIOT_XMIT_TYPE_BUTT] = {\r
+#ifdef CONFIG_XMIT_WITH_UART\r
+    {\r
+        .open = tiot_board_uart_open,\r
+        .close = tiot_board_uart_close,\r
+        .write = tiot_board_uart_write,\r
+        .read = tiot_board_uart_read,\r
+        .set_config = tiot_board_uart_set_config,\r
+#ifdef CONFIG_UART_RX_MODE_BUFFED\r
+        .rx_mode = TIOT_XMIT_RX_MODE_BUFFED,\r
+#else\r
+        .rx_mode = TIOT_XMIT_RX_MODE_POLL,\r
+#endif\r
+    },\r
+#endif\r
+#ifdef CONFIG_XMIT_WITH_SPI\r
+    {\r
+        .open = tiot_board_spi_open,\r
+        .close = tiot_board_spi_close,\r
+        .write = tiot_board_spi_write,\r
+        .read = tiot_board_spi_read,\r
+        .set_config = tiot_board_spi_set_config,\r
+#ifdef CONFIG_SPI_RX_MODE_BUFFED\r
+        .rx_mode = TIOT_XMIT_RX_MODE_BUFFED,\r
+#else\r
+        .rx_mode = TIOT_XMIT_RX_MODE_POLL,\r
+#endif\r
+    },\r
+#endif\r
+#ifdef CONFIG_XMIT_WITH_I2C\r
+    {\r
+        .open = tiot_board_i2c_open,\r
+        .close = tiot_board_i2c_close,\r
+        .write = tiot_board_i2c_write,\r
+        .read = tiot_board_i2c_read,\r
+        .set_config = tiot_board_i2c_set_config,\r
+#ifdef CONFIG_I2C_RX_MODE_BUFFED\r
+        .rx_mode = TIOT_XMIT_RX_MODE_BUFFED,\r
+#else\r
+        .rx_mode = TIOT_XMIT_RX_MODE_POLL,\r
+#endif\r
+    },\r
+#endif\r
+};\r
+\r
+const tiot_xmit_ops *tiot_xmit_get_ops(tiot_xmit_type type)\r
+{\r
+    if (type >= TIOT_XMIT_TYPE_BUTT) {\r
+        return NULL;\r
+    }\r
+    return &g_tiot_xmit_ops_map[type];\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h
new file mode 100644 (file)
index 0000000..fa8bca9
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Board transmit io common ops. \n
+ *
+ * History: \n
+ * 2023-06-13, Create file. \n
+ */
+#ifndef TIOT_BOARD_XMIT_OPS_H
+#define TIOT_BOARD_XMIT_OPS_H
+
+#include "tiot_board_xmit.h"
+#ifdef CONFIG_XMIT_WITH_UART
+#include "tiot_board_uart_port.h"
+#endif
+#ifdef CONFIG_XMIT_WITH_SPI
+#include "tiot_board_spi_port.h"
+#endif
+#ifdef CONFIG_XMIT_WITH_I2C
+#include "tiot_board_i2c_port.h"
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_board_internal_xmit Board Transmit Ops
+ * @ingroup  tiot_common_interface_board_internal
+ * @{
+ */
+
+/**
+ * @brief  TIoT support transmit type.
+ */
+typedef enum {
+#ifdef CONFIG_XMIT_WITH_UART
+    TIOT_XMIT_TYPE_UART,
+#endif
+#ifdef CONFIG_XMIT_WITH_SPI
+    TIOT_XMIT_TYPE_SPI,
+#endif
+#ifdef CONFIG_XMIT_WITH_I2C
+    TIOT_XMIT_TYPE_I2C,
+#endif
+    TIOT_XMIT_TYPE_BUTT
+} tiot_xmit_type;
+
+/**
+ * @brief  TIoT Transmit rx mode.
+ */
+typedef enum {
+    TIOT_XMIT_RX_MODE_BUFFED,  /* TIoT Transmit rx mode with circular buffer. */
+    TIOT_XMIT_RX_MODE_POLL,    /* TIoT Transmit rx mode without buffer, read data direct from io. */
+} tiot_xmit_rx_mode;
+
+/**
+ * @brief  Transmit operations.
+ */
+typedef struct {
+    int32_t (*open)(tiot_xmit *xmit, tiot_xmit_callbacks *cbs);                 /*!< Port open interface. */
+    void (*close)(tiot_xmit *xmit);                                             /*!< Port close interface. */
+    int32_t (*write)(tiot_xmit *xmit, const uint8_t *buff, uint32_t len);       /*!< Port write interface. */
+    int32_t (*read)(tiot_xmit *xmit, uint8_t *buff, uint32_t len);              /*!< Port read interface. */
+    int32_t (*set_config)(tiot_xmit *xmit, struct tiot_xmit_config *config);    /*!< Port config interface. */
+    const uint16_t rx_mode;
+} tiot_xmit_ops;
+
+/**
+ * @brief  Get selected transmit operations.
+ * @return const tiot_xmit_ops* Selected transmit operations.
+ */
+const tiot_xmit_ops *tiot_xmit_get_ops(tiot_xmit_type type);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h
new file mode 100644 (file)
index 0000000..3667f94
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: GNSS board port head. \n
+ *
+ * History: \n
+ * 2023-06-13, Create file. \n
+ */
+#ifndef GNSS_BOARD_PORT_H
+#define GNSS_BOARD_PORT_H
+
+#include "tiot_types.h"
+#include "tiot_board_pin_port.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_device_gnss_board_port  GNSS Board Port
+ * @ingroup  tiot_device_gnss
+ * @{
+ */
+
+/**
+ * @brief  GNSS pm pins.
+ */
+typedef enum {
+    GNSS_PIN_POWER_CTRL,            /*!< GNSS power control pin. */
+    GNSS_PIN_HOST_WAKEUP_DEVICE,    /*!< GNSS host wakeup device pin. */
+    GNSS_PIN_DEVICE_WAKEUP_HOST,    /*!< GNSS device wakeup host pin. */
+    GNSS_PIN_NUM,                   /*!< GNSS pin max. */
+    GNSS_PIN_NONE = TIOT_PIN_NONE   /*!< GNSS pin none. */
+} gnss_pm_pins;
+
+/**
+ * @brief  GNSS board hardware info.
+ */
+typedef struct {
+    uintptr_t xmit_id;
+    uint32_t pm_info[GNSS_PIN_NUM];
+} gnss_board_hw_info;
+
+/**
+ * @brief  GNSS board info.
+ */
+typedef struct {
+    const char *cfg_path;            /*!< cfg file path, NULL for file array. */
+    gnss_board_hw_info *hw_infos;    /*!< Pointer to array of GNSS hardware infos. */
+} gnss_board_info;
+
+/**
+ * @brief  Board provides resource informations, including pin indexs, ids, file paths, etc.
+ * @return Provided resource information.
+ */
+const gnss_board_info *gnss_board_get_info(void);
+
+/**
+ * @brief  Board porting init, request board resources, including hardware io, interrupt,etc.
+ * @param  param user customsize parameters, like device num.
+ * @return zero if OK;
+ *         non-zero if FAIL.
+ */
+int32_t gnss_board_init(void *param);
+
+/**
+ * @brief  Board porting deinit, release board resources, including hardware io, interrupt,etc.
+ * @param  param user customsize parameters, like device num.
+ */
+void gnss_board_deinit(void *param);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h
new file mode 100644 (file)
index 0000000..55f976c
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Board misc porting header. \n
+ *
+ * History: \n
+ * 2023-03-24, Create file. \n
+ */
+#ifndef TIOT_BOARD_MISC_PORT_H
+#define TIOT_BOARD_MISC_PORT_H
+
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_board_porting_misc Board Misc Port
+ * @ingroup  tiot_common_interface_board_porting
+ * @{
+ */
+
+/**
+ * @if Eng
+ * @brief Board wake lock struct.
+ * @else
+ * @brief 板级唤醒锁结构体。
+ * @endif
+ */
+typedef struct {
+    void *lock;
+} tiot_board_wakelock;
+
+/**
+ * @if Eng
+ * @brief Board wake lock initialization interface.
+ * @param  [out] lock wake lock to be initialized.
+ * @return if OK return 0, else return -1.
+ * @note if board has no sleep or just enter wfi, implement as empty function.
+ * @else
+ * @brief 板级唤醒锁初始化接口。
+ * @param  [out] lock 待初始化的唤醒锁。
+ * @return 初始化成功返回0,否则返回-1。
+ * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。
+ * @endif
+ */
+int32_t tiot_board_wake_lock_init(tiot_board_wakelock *lock);
+
+/**
+ * @if Eng
+ * @brief Board wake lock interface.
+ * @param  [in] lock wake lock to be locked.
+ * @note if board has no sleep or just enter wfi, implement as empty function.
+ * @else
+ * @brief 板级唤醒锁接口。
+ * @param  [in] lock 待上锁的唤醒锁。
+ * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。
+ * @endif
+ */
+void tiot_board_wake_lock(tiot_board_wakelock *lock);
+
+/**
+ * @if Eng
+ * @brief Board wake unlock interface.
+ * @param  [in]  lock wake lock to be unlocked.
+ * @note if board has no sleep or just enter wfi, implement as empty function.
+ * @else
+ * @brief 板级唤醒解锁接口。
+ * @param  [in]  lock 待解锁的唤醒锁。
+ * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。
+ * @endif
+ */
+void tiot_board_wake_unlock(tiot_board_wakelock *lock);
+
+/**
+ * @if Eng
+ * @brief Board wake lock destroy interface.
+ * @param  [in]  lock wake lock to be destroyed.
+ * @note if board has no sleep or just enter wfi, implement as empty function.
+ * @else
+ * @brief 板级唤醒锁销毁接口。
+ * @param  [in]  lock 待销毁的唤醒锁.
+ * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。
+ * @endif
+ */
+void tiot_board_wake_lock_destroy(tiot_board_wakelock *lock);
+
+/**
+ * @if Eng
+ * @brief  Board μs level delay.
+ * @param  [in]  us μs count.
+ * @else
+ * @brief  板级微秒级delay接口。
+ * @param  [in]  us 微秒。
+ * @endif
+ */
+void tiot_board_udelay(uint32_t us);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h
new file mode 100644 (file)
index 0000000..1a35706
--- /dev/null
@@ -0,0 +1,137 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board pin porting header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-24, Create file. \n\r
+ */\r
+#ifndef TIOT_BOARD_PIN_PORT_H\r
+#define TIOT_BOARD_PIN_PORT_H\r
+\r
+#include "tiot_types.h"\r
+#include "gpio.h"\r
+#include "uart.h"\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_board_porting_pin Board Pin Port\r
+ * @ingroup  tiot_common_interface_board_porting\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief  Pin none, board port should use this macro if pin is not connected.\r
+ */\r
+#define TIOT_PIN_NONE        0xFFFFFFFFU\r
+\r
+#ifdef BOARD_U8\r
+#define TIOT_UART_PORT  UART_BUS_0\r
+#define TIOT_PIN_WAKEUP_HOST_NUM    S_AGPIO_L31    /* 用于唤醒HOST. */\r
+#define TIOT_PIN_WAKEUP_GNSS_NUM    TIOT_PIN_NONE    /* 用于 唤醒GNSS. */\r
+#define TIOT_PIN_POWER      S_AGPIO_L30     /* 用于开启GNSS. */\r
+\r
+#define TIOT_PIN_UART_TX    S_MGPIO19\r
+#define TIOT_PIN_UART_RX    S_MGPIO20\r
+#define TIOT_PIN_UART_CTS   S_MGPIO22\r
+#define TIOT_PIN_UART_RTS   S_MGPIO21\r
+#define TIOT_PINMUX HAL_PIO_FUNC_UART1\r
+\r
+#elif defined(BOARD_L22) || defined(BOARD_W9)\r
+#define TIOT_UART_PORT  UART_BUS_1\r
+#define TIOT_PIN_WAKEUP_HOST_NUM    S_AGPIO_L15    /* 用于唤醒HOST. */\r
+#define TIOT_PIN_WAKEUP_GNSS_NUM    S_HGPIO0    /* 用于 唤醒GNSS. */\r
+#define TIOT_PIN_POWER      S_AGPIO_L32     /* 用于开启GNSS. */\r
+\r
+#define TIOT_PIN_UART_TX    S_MGPIO33\r
+#define TIOT_PIN_UART_RX    S_MGPIO34\r
+#define TIOT_PIN_UART_CTS   S_MGPIO36\r
+#define TIOT_PIN_UART_RTS   S_MGPIO35\r
+#define TIOT_PINMUX HAL_PIO_FUNC_UART_HS_UART\r
+\r
+#else\r
+#define TIOT_PIN_WAKEUP_HOST_NUM    TIOT_PIN_NONE    /* 用于唤醒HOST. */\r
+#define TIOT_PIN_WAKEUP_GNSS_NUM    TIOT_PIN_NONE    /* 用于 唤醒GNSS. */\r
+#define TIOT_PIN_POWER      TIOT_PIN_NONE     /* 用于开启GNSS. */\r
+#define TIOT_UART_PORT  UART_BUS_0\r
+#define TIOT_PIN_UART_TX    S_MGPIO19\r
+#define TIOT_PIN_UART_RX    S_MGPIO20\r
+#define TIOT_PIN_UART_CTS   S_MGPIO22\r
+#define TIOT_PIN_UART_RTS   S_MGPIO21\r
+#define TIOT_PINMUX HAL_PIO_FUNC_UART1\r
+\r
+#endif\r
+#define TIOT_PIN_UART_WAKEUP_NUM    0x80000000U    /* 用于uart rx唤醒. */\r
+/**\r
+ * @brief  Pin level enum.\r
+ */\r
+typedef enum {\r
+    TIOT_PIN_LEVEL_LOW,     /*!< 0: Pin level low. */\r
+    TIOT_PIN_LEVEL_HIGH     /*!< 1: Pin level high. */\r
+} tiot_pin_level;\r
+\r
+/**\r
+ * @brief  Pin interrupt enable enum.\r
+ */\r
+typedef enum {\r
+    TIOT_PIN_INT_DISABLE,   /*!< 0: Pin interrupt disable. */\r
+    TIOT_PIN_INT_ENABLE     /*!< 1: Pin interrupt enable. */\r
+} tiot_pin_int_enable;\r
+\r
+/**\r
+ * @brief  Pin interrupt callback type, need input corresponding pin.\r
+ */\r
+typedef void (* tiot_pin_int_callback)(uint32_t pin);\r
+\r
+/**\r
+ * @brief  Board set pin level interface.\r
+ * @param  [in] pin   Pin id.\r
+ * @param  [in] level Pin level, see @ref tiot_pin_level.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_set_level(uint32_t pin, uint8_t level);\r
+\r
+/**\r
+ * @brief  Board get current pin level interface.\r
+ * @param  [in]  pin   Pin id.\r
+ * @param  [out] level Current pin level, see @ref tiot_pin_level.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_get_level(uint32_t pin, uint8_t *level);\r
+\r
+/**\r
+ * @brief  Board pin interrupt enable interface.\r
+ * @param  [in] pin         Pin id.\r
+ * @param  [in] int_enable  Interrupt enable or disable, see @ref tiot_pin_int_enable.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_enable_int(uint32_t pin, uint8_t int_enable);\r
+\r
+/**\r
+ * @brief  Board pin interrupt callback register interface.\r
+ * @note   Porting should ensure this callback is called when enters pin irq if interrupt enabled.\r
+ * @param  [in] pin     Pin id.\r
+ * @param  [in] int_cb  Registed interrupt callback, see @ref tiot_pin_int_callback.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_register_int_callback(uint32_t pin, tiot_pin_int_callback int_cb);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h
new file mode 100644 (file)
index 0000000..406cb48
--- /dev/null
@@ -0,0 +1,122 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board UART porting header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-24, Create file. \n\r
+ */\r
+#ifndef TIOT_BOARD_UART_PORT_H\r
+#define TIOT_BOARD_UART_PORT_H\r
+\r
+#include "tiot_board_xmit.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_board_porting_uart Board UART Port\r
+ * @ingroup  tiot_common_interface_board_porting\r
+ * @{\r
+ */\r
+\r
+#define TIOT_UART_ATTR_DATABIT_8    0 /*!< UART word length is 8 data bits per frame. */\r
+#define TIOT_UART_ATTR_DATABIT_7    1 /*!< UART word length is 7 data bits per frame. */\r
+#define TIOT_UART_ATTR_DATABIT_6    2 /*!< UART word length is 6 data bits per frame. */\r
+#define TIOT_UART_ATTR_DATABIT_5    3 /*!< UART word length is 5 data bits per frame. */\r
+#define TIOT_UART_ATTR_DATABIT_BUTT 4 /*!< UART word length butt. */\r
+\r
+#define TIOT_UART_ATTR_PARITY_NONE  0 /*!< no UART parity bit. */\r
+#define TIOT_UART_ATTR_PARITY_ODD   1 /*!< odd UART parity bit. */\r
+#define TIOT_UART_ATTR_PARITY_EVEN  2 /*!< even UART parity bit. */\r
+#define TIOT_UART_ATTR_PARITY_MARK  3 /*!< UART parity bit is always 1. */\r
+#define TIOT_UART_ATTR_PARITY_SPACE 4 /*!< UART parity bit is always 0. */\r
+#define TIOT_UART_ATTR_PARITY_BUTT  5 /*!< UART parity bit butt. */\r
+\r
+#define TIOT_UART_ATTR_STOPBIT_1    0 /*!< UART has 1 stop bit. */\r
+#define TIOT_UART_ATTR_STOPBIT_1P5  1 /*!< UART has 1.5 stop bits. */\r
+#define TIOT_UART_ATTR_STOPBIT_2    2 /*!< UART has 2 stop bits. */\r
+#define TIOT_UART_ATTR_STOPBIT_BUTT 3 /*!< UART stop bits butt. */\r
+\r
+#define TIOT_UART_ATTR_FLOW_CTRL_DISABLE  0 /*!< UART flow control is disabled. */\r
+#define TIOT_UART_ATTR_FLOW_CTRL_ENABLE   1 /*!< UART flow control enabled. */\r
+\r
+/**\r
+ * @brief Uart attribute.\r
+ *\r
+ */\r
+typedef struct {\r
+    uint16_t data_bits : 4;\r
+    uint16_t parity    : 4;\r
+    uint16_t stop_bits : 4;\r
+    uint16_t flow_ctrl : 4;\r
+    uint16_t reserved  : 16;\r
+} tiot_uart_attr;\r
+\r
+/**\r
+ * @brief Uart config.\r
+ *\r
+ */\r
+typedef struct tiot_xmit_config {\r
+    uint32_t baudrate;   /*!< UART baudrate. */\r
+    tiot_uart_attr attr; /*!< UART attribute. */\r
+} tiot_uart_config;\r
+\r
+/**\r
+ * @brief  Board UART open interface.\r
+ * @param  [in]  xmit Transmit object.\r
+ * @param  [in]  cb   Transmit callbacks.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_uart_open(tiot_xmit *xmit, tiot_xmit_callbacks *cb);\r
+\r
+/**\r
+ * @brief  Board UART close interface.\r
+ * @param  [in]  xmit Transmit object.\r
+ */\r
+void    tiot_board_uart_close(tiot_xmit *xmit);\r
+\r
+/**\r
+ * @brief  Board UART write interface.\r
+ * @param  [in] xmit Transmit object.\r
+ * @param  [in] buff Data buff.\r
+ * @param  [in] len  Data length.\r
+ * @return zero or postive for writen OK length;\r
+ *         negtive if write FAIL.\r
+ */\r
+int32_t tiot_board_uart_write(tiot_xmit *xmit, const uint8_t *buff, uint32_t len);\r
+\r
+/**\r
+ * @brief  Board UART blocking read interface.\r
+ * @param  [in] xmit Transmit object.\r
+ * @param  [in] buff Read buff.\r
+ * @param  [in] len  Expected read length.\r
+ * @return zero or postive for read OK length;\r
+ *         negtive if read FAIL or cannot implemented.\r
+ */\r
+int32_t tiot_board_uart_read(tiot_xmit *xmit, uint8_t *buff, uint32_t len);\r
+\r
+/**\r
+ * @brief  Board UART config interface.\r
+ * @param  [in] xmit   Transmit object.\r
+ * @param  [in] config UART config, see @ref tiot_uart_config.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_uart_set_config(tiot_xmit *xmit, tiot_uart_config *config);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h
new file mode 100644 (file)
index 0000000..0a78cb1
--- /dev/null
@@ -0,0 +1,436 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT osal interface. \n
+ *
+ * History: \n
+ * 2023-05-31, Create file. \n
+ */
+#ifndef TIOT_OSAL_H
+#define TIOT_OSAL_H
+
+#ifdef CONFIG_OSAL_DEFINED
+#include "soc_osal.h"
+#else
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_osal TIoT Osal Interface
+ * @ingroup  tiot_common_interface
+ * @{
+ */
+
+#define OSAL_SUCCESS 0
+#define OSAL_FAILURE (-1)
+#define OSAL_EOVERFLOW (-75)
+
+#define OSAL_WAIT_FOREVER 0xFFFFFFFF
+#define OSAL_WAIT_CONDITION_TRUE 1
+
+#define OSAL_GFP_ZERO (0x1)
+#define OSAL_GFP_ATOMIC (0x1 << 1)
+#define OSAL_GFP_DMA (0x1 << 2)
+#define OSAL_GFP_KERNEL (0x1 << 3)
+
+#define OSAL_O_RDONLY 00000000
+#define OSAL_O_WRONLY 00000001
+#define OSAL_O_RDWR 00000002
+#define OSAL_O_ACCMODE 00000003
+
+#define OSAL_O_CREAT 00000100
+#define OSAL_O_EXCL 00000200
+#define OSAL_O_TRUNC 00001000
+#define OSAL_O_APPEND 00002000
+#define OSAL_O_CLOEXEC 02000000
+
+#define OSAL_SEEK_SET 0
+#define OSAL_SEEK_CUR 1
+#define OSAL_SEEK_END 2
+
+/* Osal string. */
+#ifdef __KERNEL__
+#define osal_strtol(cp, endp, base)    simple_strtol(cp, endp, base)
+#else
+#define osal_strtol(cp, endp, base)    strtol(cp, endp, base)
+#endif
+
+typedef struct {
+    void *lock;
+} osal_spinlock;
+
+typedef struct {
+    void *mutex;
+} osal_mutex;
+
+typedef struct {
+    void *wait;
+} osal_wait;
+
+typedef struct {
+    void *task;
+} osal_task;
+
+typedef int (*osal_kthread_handler)(void *data);
+
+/* return value is a bool type */
+typedef int (*osal_wait_condition_func)(const void *param);
+
+/**
+ * @ingroup osal_timer
+ * @brief sleep waiting for signals.
+ *
+ * @par Description:
+ * sleep waiting for signals.
+ *
+ * @param msecs [in] Time in milliseconds to sleep for.
+ *
+ * @return Returns 0 when the timer has expired otherwise the remaining time in ms will be returned.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+unsigned long osal_msleep(unsigned int msecs);
+
+/**
+ * @ingroup osal_addr
+ * @brief Alloc dynamic memory.
+ *
+ * @par Description:
+ * This API is used to alloc a memory block of which the size is specified.
+ *
+ * @param size [in] How many bytes of memory are required.
+ * @param osal_gfp_flag [in] The type of memory to alloc. This parameter is not used in liteos and freertos.
+ * In linux, it must include one of the following access modes: OSAL_GFP_ATOMIC, OSAL_GFP_DMA, OSAL_GFP_KERNEL.
+ * OSAL_GFP_ZERO can be bitwise-or'd in flags, Then, the memory is set to zero.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void *osal_kmalloc(unsigned long size, unsigned int osal_gfp_flag);
+
+/**
+ * @ingroup osal_addr
+ * @brief Free dynamic memory.
+ *
+ * @par Description:
+ * This API is used to free specified dynamic memory that has been allocd and update module mem used.
+ *
+ * @param addr [in] Starting address of the memory block to be freed.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_kfree(void *addr);
+
+/**
+ * @ingroup osal_spinlock
+ * @brief Initialize a spin lock.
+ *
+ * @par Description:
+ * This API is used to initialization of spin_lock.
+ *
+ * @param lock [out] the lock to be initialized.
+ *
+ * @attention
+ * must be free with osal_spin_lock_destroy, other wise will lead to memory leak;
+ *
+ * @return OSAL_SUCCESS/OSAL_FAILURE
+ *
+ * @par Support System:
+ * linux liteos.
+ */
+int osal_spin_lock_init(osal_spinlock *lock);
+
+/**
+ * @ingroup osal_spinlock
+ * @brief acquire the spin_lock.
+ *
+ * @par Description:
+ * Saves the current IRQ status of the CPU, obtains the specified spin_lock, and disables the interrupts of the CPU.
+ *
+ * @param lock [in] the lock to be acquired.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_spin_lock_irqsave(osal_spinlock *lock, unsigned long *flags);
+
+/**
+ * @ingroup osal_spinlock
+ * @brief release the spin_lock.
+ *
+ * @par Description:
+ * Releases the specified spin_lock and restores the interrupt status of the CPU, and enables the interrupts of the CPU.
+ *
+ * @param lock [in] the lock to be released.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_spin_unlock_irqrestore(osal_spinlock *lock, unsigned long *flags);
+
+/**
+ * @ingroup osal_spinlock
+ * @brief Destroy the spin_lock.
+ *
+ * @par Description:
+ * Destroy the spin_lock.
+ *
+ * @param lock [in] The lock to be destroyed.
+ *
+ * @attention
+ * must be called when kmod exit, other wise will lead to memory leak;
+ * this API will free memory, lock must be from osal_spin_lock_init returns
+ *
+ * @par Support System:
+ * linux liteos.
+ */
+void osal_spin_lock_destroy(osal_spinlock *lock);
+
+/**
+ * @ingroup osal_mutex
+ * @brief Initialize the mutex.
+ *
+ * @par Description:
+ * This API is used to initialize the mutex.
+ *
+ * @param mutex [in] the mutex to be initialized.
+ *
+ * @return OSAL_FAILURE/OSAL_SUCCESS
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+int osal_mutex_init(osal_mutex *mutex);
+
+/**
+ * @ingroup osal_mutex
+ * @brief Acquire the mutex.
+ *
+ * @par Description:
+ * Acquire the mutex. Lock the mutex exclusively for this task.
+ * If the mutex is not available right now, it will sleep until it can get it.
+ *
+ * @param mutex [in] the mutex to be initialized.
+ *
+ * @return OSAL_FAILURE/OSAL_SUCCESS
+ *
+ * @note
+ * The mutex must later on be released by the same task that acquired it. Recursive locking is not allowed.
+ * The task may not exit without first unlocking the mutex.
+ * Also, kernel memory where the mutex resides must not be freed with the mutex still locked.
+ * The mutex must first be initialized (or statically defined) before it can be locked.
+ * memset()-ing the mutex to 0 is not allowed.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ * @par System Differ: Only LiteOS supports the nested lock feature.
+ */
+int osal_mutex_lock(osal_mutex *mutex);
+
+/**
+ * @ingroup osal_mutex
+ * @brief Release the mutex.
+ *
+ * @par Description:
+ * Release the mutex. Unlock a mutex that has been locked by this task previously.
+ * This function must not be used in interrupt context. Unlocking of a not locked mutex is not allowed.
+ *
+ * @param mutex [in] the mutex to be released.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_mutex_unlock(osal_mutex *mutex);
+
+/**
+ * @ingroup osal_mutex
+ * @brief Destroy the mutex.
+ *
+ * @par Description:
+ * This API is used to destroy the mutex.
+ *
+ * @param mutex [in] The mutex to be destroyed.
+ *
+ * @attention
+ * must be called when kmod exit, otherwise will lead to memory leak; osal_mutex_destroy will free memory,
+ * caller should clear pointer to be NULL after called.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_mutex_destroy(osal_mutex *mutex);
+
+/**
+ * @ingroup osal_wait
+ * @brief Initialize a waiting queue.
+ *
+ * @par Description:
+ * This API is used to Initialize a waiting queue.
+ *
+ * @param wait [out] The wait queue to be initialized.
+ *
+ * @par Support System:
+ * linux liteos.
+ */
+int osal_wait_init(osal_wait *wait);
+
+/**
+ * @ingroup osal_wait
+ * @brief sleep until a condition gets true or a timeout elapses.
+ *
+ * @par Description:
+ * sleep until a condition gets true or a timeout elapses.
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the @func returned true or a signal is received.
+ * Return value of the @func is checked each time the waitqueue @wait is woken up.
+ *
+ * @param wait [in] the waitqueue to wait on.
+ * @param wait [in] a C expression for the event to wait for.
+ * @param wait [in] timeout, in ms.
+ *
+ * @par Support System:
+ * linux liteos.
+ */
+int osal_wait_timeout_interruptible(osal_wait *wait, osal_wait_condition_func func, const void *param,
+    unsigned long ms);
+
+/**
+ * @ingroup osal_wait
+ * @brief wake up threads blocked on a waitqueue.
+ *
+ * @par Description:
+ * Wake-up wait queue,pair to @wait_event_interruptible.
+ *
+ * @param wait [in] The wait to be wake up.
+ *
+ * @par Support System:
+ * linux liteos.
+ */
+void osal_wait_wakeup_interruptible(osal_wait *wait); // same as osal_wait_wakeup on liteos
+
+/**
+ * @ingroup osal_wait
+ * @brief to destroy the wait.
+ *
+ * @par Description:
+ * This API is used to destroy the wait.
+ *
+ * @param wait [in] The wait to be destroyed.
+ *
+ * @attention this api may free memory, wait should be from osal_complete_init.
+ * @par Support System:
+ * linux liteos.
+ */
+void osal_wait_destroy(osal_wait *wait);
+
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+/**
+ * @ingroup osal_task
+ *
+ * @brief Provides an interface for creating a thread and invokes kthread_run for creating a kernel thread.
+ *
+ * @par Description:
+ * Provides an interface for creating a thread and invokes kthread_run for creating a kernel thread.
+ *
+ * @param stack_size [in] Size of the stack space of the thread. 0 means default.
+ * @param handler [in] Functions to be processed by the thread
+ * @param data [in] Function handler data.
+ * @param name [in] Thread name displayed.
+ *
+ * @retval   osal_task*  If the thread is successfully created, the pointer of the thread is returned.
+ * @retval   NULL        If the thread fails to be created, NULL is returned.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+osal_task *osal_kthread_create(osal_kthread_handler handler, void *data, const char *name, unsigned int stack_size);
+
+/**
+ * @ingroup osal_task
+ *
+ * @brief Used to destroy the threads you created.
+ *
+ * @par Description:
+ * Stops a specified kernel thread.
+ *
+ * @attention osal_kthread_destroy will free memory of task, caller should clear pointer to be NULL.
+ * Note that if you want to destroy a thread, the thread cannot end before calling this function,
+ * Or something terrible will happen.
+ * When you call the Kthread_stop function, the thread function cannot be finished, otherwise it will oops.
+ * @task may be free in api, @task should be from osal_kthread_create.
+ *
+ * @param task  [in] Threads you want to destroy.
+ * @param stop_flag [in] Indicates whether the current thread exits. If the value of stop_flag is 0,
+ * The current thread does not exit. The stop flag is not 0.
+ *
+ * @par Support System:
+ * linux liteos freertos.
+ */
+void osal_kthread_destroy(osal_task *task, unsigned int stop_flag);
+#endif
+
+#ifndef CONFIG_FILE_BY_ARRAY
+/**
+ * @ingroup osal_fileops
+ * @brief open file and return file pointer.
+ * @param file [in] the filename of file
+ * @param flag [in] the opreation flag example: OSAL_O_CREAT
+ * @param mode [in] the mode example: OSAL_O_RDONLY
+ * @return void* / null
+ *
+ * @par Support System:
+ * linux liteos seliteos freertos.
+ */
+void *osal_klib_fopen(const char *file, int flags, int mode);
+
+/**
+ * @ingroup osal_fileops
+ * @brief close file.
+ * @param filp [in] the result of osal_klib_fopen
+ * @par Support System:
+ * linux liteos seliteos freertos.
+ */
+void osal_klib_fclose(void *filp);
+
+/**
+ * @ingroup osal_fileops
+ * @brief Kernel read function.
+ * @param buf [out] the buffer you want to read in
+ * @param size [in] the size of buffer
+ * @param filp [in] the result of osal_klib_fopen
+ * @return The length that has been read.
+ *
+ * @par Support System:
+ * linux liteos seliteos freertos.
+ */
+int osal_klib_fread(char *buf, unsigned long size, void *filp);
+
+/**
+ * @ingroup osal_fileops
+ * @brief Kernel file seek function.
+ * @param offset [in] the new position of file
+ * @param whence [in] the method of lseek,example:OSAL_SEEK_SET
+ * @param filp [in] the result of osal_klib_fopen
+ * @par Support System:
+ * linux liteos seliteos.
+ */
+int osal_klib_fseek(long long offset, int whence, void *filp);
+#endif
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif /* CONFIG_OSAL_DEFINED */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.c b/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.c
new file mode 100644 (file)
index 0000000..b0434eb
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-10-28, Create file. \n
+ */
+
+#include "tiot_service_interface.h"
+#include "tiot_service_interface_ext.h"
+#include "tiot_controller.h"
+#include "tiot_pm_wakelock.h"
+#include "tiot_board_log.h"
+#ifdef CONFIG_DEV_GNSS
+#include "gnss_service.h"
+#endif
+#ifdef CONFIG_DEV_W33
+#include "w33_service.h"
+#endif
+#ifdef CONFIG_DEV_CAXX
+#include "caxx_service.h"
+#endif
+#ifdef CONFIG_DEV_BSXX
+#include "bsxx_service.h"
+#endif
+#ifdef CONFIG_DEV_TIOT_SLAVE
+#include "tiot_slave_service.h"
+#endif
+
+typedef struct {
+    int32_t (* init)(void);
+    void (* deinit)(void);
+} tiot_service_entry;
+
+typedef struct {
+    const char *name;
+    uint8_t dev_max;
+    uintptr_t (* get_ctrl)(uint8_t dev_id);
+} tiot_service_desc;
+
+static const tiot_service_entry tiot_service_list[] = {
+#ifdef CONFIG_DEV_GNSS
+    { gnss_service_init, gnss_service_deinit },
+#endif
+#ifdef CONFIG_DEV_W33
+    { w33_service_init, w33_service_deinit },
+#endif
+#ifdef CONFIG_DEV_CAXX
+    { caxx_service_init, caxx_service_deinit },
+#endif
+#ifdef CONFIG_DEV_BSXX
+    { bsxx_service_init, bsxx_service_deinit },
+#endif
+#ifdef CONFIG_DEV_TIOT_SLAVE
+    { tiot_slave_service_init, tiot_slave_service_deinit },
+#endif
+};
+
+static const tiot_service_desc tiot_service_desc_list[] = {
+#ifdef CONFIG_DEV_GNSS
+    { "gn71", CONFIG_GNSS_DEV_NUM, gnss_service_get_ctrl },
+    { "gnss01", CONFIG_GNSS_DEV_NUM, gnss_service_get_ctrl },
+#endif
+#ifdef CONFIG_DEV_W33
+    { "w33", CONFIG_W33_DEV_NUM, w33_service_get_ctrl },
+#endif
+#ifdef CONFIG_DEV_CAXX
+    { "ca01", CONFIG_CAXX_DEV_NUM, caxx_service_get_ctrl },
+#endif
+#ifdef CONFIG_DEV_BSXX
+    { "bs21", CONFIG_BSXX_DEV_NUM, bsxx_service_get_ctrl },
+    { "bs25", CONFIG_BSXX_DEV_NUM, bsxx_service_get_ctrl },
+#endif
+#ifdef CONFIG_DEV_TIOT_SLAVE
+    { "tiot_slave", CONFIG_TIOT_SLAVE_DEV_NUM, tiot_slave_service_get_ctrl },
+#endif
+};
+
+static const tiot_service_desc *tiot_service_get_description(const char *device_name, uint8_t *dev_id)
+{
+    uint32_t i;
+    uint32_t len = strlen(device_name);
+    uint32_t name_len = 0;
+    for (i = 0; i < (sizeof(tiot_service_desc_list) / sizeof(tiot_service_desc)); i++) {
+        name_len = strlen(tiot_service_desc_list[i].name);
+        /* devcie_name长度小于描述名时不可能匹配,避免memcmp对device_name访问溢出. */
+        if (len < name_len) {
+            continue;
+        }
+        if (memcmp(device_name, tiot_service_desc_list[i].name, name_len) == 0) {
+            break;
+        }
+    }
+    if (i == (sizeof(tiot_service_desc_list) / sizeof(tiot_service_desc))) {
+        tiot_print_err("[TIoT]invalid device_name string %s.\r\n", device_name);
+        return NULL;
+    }
+    /* device_name格式 */
+    /* "xxxx" 其中xxxx为对应device名字, dev_id默认为0 */
+    /* "xxxx,n" 其中n为单个数字字符,n < 10,dev_id设为n */
+    if (len > name_len) {
+        if (len - name_len != 2) { // n为单个字符,加上分隔符,长度固定为2
+            tiot_print_err("[TIoT]device_name length %d invalid.\r\n", len);
+            return NULL;
+        }
+        if (device_name[name_len] != ',') {
+            tiot_print_err("[TIoT]device_name seprator invalid %c.\r\n", device_name[name_len]);
+            return NULL;
+        }
+        if ((device_name[name_len + 1] < '0') || (device_name[name_len + 1] > '9')) {
+            tiot_print_err("[TIoT]dev id invalid %c.\r\n", device_name[name_len + 1]);
+            return NULL;
+        }
+        *dev_id = device_name[name_len + 1] - '0';
+    }
+    if (*dev_id >= tiot_service_desc_list[i].dev_max) {
+        tiot_print_err("[TIoT]device_name dev id exceed max %c.\r\n", device_name[name_len + 1]);
+        return NULL;
+    }
+    return &tiot_service_desc_list[i];
+}
+
+int32_t tiot_service_init(void)
+{
+    int32_t ret;
+    uint32_t i;
+    uint32_t j;
+    if (tiot_pm_wake_lock_init() != 0) {
+        return -1;
+    }
+    for (i = 0; i < (sizeof(tiot_service_list) / sizeof(tiot_service_entry)); i++) {
+        ret = tiot_service_list[i].init();
+        if (ret != 0) {
+            tiot_print_err("[TIoT]service init fail @%d\n", i);
+            goto fail;
+        }
+    }
+    return 0;
+fail:
+    for (j = 0; j < i; j++) {
+        tiot_service_list[j].deinit();
+    }
+    tiot_pm_wake_lock_destroy();
+    return ret;
+}
+
+void tiot_service_deinit(void)
+{
+    uint32_t i;
+    for (i = 0; i < (sizeof(tiot_service_list) / sizeof(tiot_service_entry)); i++) {
+        tiot_service_list[i].deinit();
+    }
+    tiot_pm_wake_lock_destroy();
+}
+
+tiot_handle tiot_service_open(const char *device_name, void *param)
+{
+    tiot_controller *ctrl = NULL;
+    uint8_t dev_id = 0;
+    const tiot_service_desc *desc;
+    if (device_name == NULL) {
+        tiot_print_err("[TIoT]device_name is NULL.\r\n");
+        return 0;
+    }
+    desc = tiot_service_get_description(device_name, &dev_id);
+    if (desc == NULL) {
+        return 0;
+    }
+    ctrl = (tiot_controller *)desc->get_ctrl(dev_id);
+    if (tiot_controller_open(ctrl, param) != 0) {
+        ctrl = NULL;
+    }
+    return (tiot_handle)ctrl;
+}
+
+void tiot_service_close(tiot_handle handle)
+{
+    tiot_controller *ctrl = (tiot_controller *)handle;
+    tiot_controller_close(ctrl);
+}
+
+int32_t tiot_service_write_ext(tiot_handle handle, const uint8_t *data,
+                               uint32_t len, const tiot_service_tx_param *param)
+{
+    tiot_controller *ctrl = (tiot_controller *)handle;
+    if ((data == NULL) || (len == 0)) {
+        tiot_print_dbg("[TIoT]send data invalid.\n");
+        return -1;
+    }
+    if (tiot_controller_check_opened(ctrl) != true) {
+        return -1;
+    }
+    return ctrl->ops.write(ctrl, data, len, (const tiot_xfer_tx_param *)param);
+}
+
+int32_t tiot_service_write(tiot_handle handle, const uint8_t *data, uint32_t len)
+{
+    /* 默认发送subsys为0的数据 */
+    const tiot_service_tx_param param = { 0 };
+       #if 0
+    printf("tiot_service_write 0x");
+    for( int i =0;i < len;i++)
+    {
+        printf("%01X",data[i]);
+    }
+    printf("\r\n");
+    printf("tiot_service_write %s \r\n",data);
+       #endif
+    return tiot_service_write_ext(handle, data, len, &param);
+}
+
+int32_t tiot_service_read_ext(tiot_handle handle, uint8_t *buff, uint32_t buff_len, const tiot_service_rx_param *param)
+{
+    int32_t buff_invalid;
+    tiot_controller *ctrl = (tiot_controller *)handle;
+    if (param == NULL) {
+        tiot_print_dbg("[TIoT]rx param invalid.\n");
+        return -1;
+    }
+    buff_invalid = (buff == NULL) || (buff_len == 0);
+#ifdef __KERNEL__
+    /* 用作poll接口时,buff & buff_len可以为空. */
+    if (((param->filp == NULL) || (param->poll_wait == NULL)) && (buff_invalid != 0)) {
+#else
+    if (buff_invalid != 0) {
+#endif
+        tiot_print_dbg("[TIoT]read buff invalid.\n");
+        return -1;
+    }
+    if (tiot_controller_check_opened(ctrl) != true) {
+        return -1;
+    }
+    return ctrl->ops.read(ctrl, buff, buff_len, (const tiot_xfer_rx_param *)param);
+}
+
+int32_t tiot_service_read(tiot_handle handle, uint8_t *buff, uint32_t buff_len, uint32_t timeout_ms)
+{
+    /* 默认接收queueID为0的数据 */
+    /* tiot_service_rx_para结构体有kernel编译宏区分, 不能列表初始化, 否则参数未知. */
+    tiot_service_rx_param param = { 0 };
+    param.timeout_ms = timeout_ms;
+    return tiot_service_read_ext(handle, buff, buff_len, &param);
+}
+
+int32_t tiot_service_pm_ctrl(tiot_handle handle, tiot_service_pm_ctrl_cmd cmd)
+{
+    tiot_controller *ctrl = (tiot_controller *)handle;
+    if (tiot_controller_check_opened(ctrl) != true) {
+        return -1;
+    }
+    if (ctrl->ops.pm_ctrl == NULL) {
+        tiot_print_err("[TIoT]not support pm_ctrl.\n");
+        return -1;
+    }
+    return ctrl->ops.pm_ctrl(ctrl, (uint8_t)cmd);
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface.h
new file mode 100644 (file)
index 0000000..506a0f5
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-10-24, Create file. \n
+ */
+#ifndef TIOT_SERVICE_INTERFACE_H
+#define TIOT_SERVICE_INTERFACE_H
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/poll.h>
+#else
+#include <stdint.h>
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_service Service Interface
+ * @ingroup  tiot_common_interface
+ * @{
+ */
+
+#define TIOT_READ_TIMEOUT_FOREVER  0xFFFFFFFU  /*!< Read wait timeout forever. */
+
+typedef uintptr_t tiot_handle;
+
+typedef struct {
+    uint8_t *buff; /* 用户需要创建静态buff */
+    uint32_t buff_len;
+    void (*rx_callback)(const uint8_t *buff, uint32_t len);
+    uint32_t flags;
+} tiot_service_open_param;
+
+/**
+ * @brief  TIoT Service Init interface.
+ * @return zero if OK;
+ *         -1 if FAIL.
+ * @note Init for all driver and board.
+ */
+int32_t tiot_service_init(void);
+
+/**
+ * @brief  TIoT Service Deinit interface.
+ * @note Deinit for all driver and board.
+ */
+void tiot_service_deinit(void);
+
+/**
+ * @brief  TIoT Service Open interface.
+ * @param  [in]  device_name TIoT device compatible string.
+ * @param  [in]  param User/Service defined params.
+ * @return valid handle if OK;
+ *         zero if FAIL.
+ * @note   Must write/read after open.
+ */
+tiot_handle tiot_service_open(const char *device_name, void *param);
+
+/**
+ * @brief  TIoT Service Close interface.
+ * @note   Meaningless to return error.
+ */
+void tiot_service_close(tiot_handle handle);
+
+/**
+ * @brief  TIoT Service Write Message interface.
+ * @param  [in]  data Data need to send.
+ * @param  [in]  len Data length.
+ * @return zero or postive for writen OK length;
+ *         negtive if write FAIL.
+ * @note   Will return after data is sent to board uart interface.
+ */
+int32_t tiot_service_write(tiot_handle handle, const uint8_t *data, uint32_t len);
+
+/**
+ * @brief  TIoT Service Read Message interface.
+ * @param  [in/out] buff User read buff.
+ * @param  [in]  buff_len User read buff size.
+ * @param  [in]  timeout_ms Wait timeout ms.
+ * @return if read wait timeout(nothing to read), return 0.
+ *         if read fail, return -1.
+ *         if support ASCII message, message type(2 bytes, ASCII or BINARY) and message will be copied to buff,
+ *         else only message will be copied to buff,
+ *         return read length.
+ * @note   This interface will return only single complete message once,
+ *         for continous message read, call this interface repeatly.
+ */
+int32_t tiot_service_read(tiot_handle handle, uint8_t *buff, uint32_t buff_len, uint32_t timeout_ms);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h
new file mode 100644 (file)
index 0000000..37bcd41
--- /dev/null
@@ -0,0 +1,98 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ *\r
+ * Description:  \n\r
+ *\r
+ * History: \n\r
+ * 2024-01-29, Create file. \n\r
+ */\r
+#ifndef TIOT_SERVICE_INTERFACE_EXT_H\r
+#define TIOT_SERVICE_INTERFACE_EXT_H\r
+\r
+#include "tiot_service_interface.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_service_ext Service Interface Ext\r
+ * @ingroup  tiot_common_interface\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief  TIoT Tx param, for tiot_service_write_ext.\r
+ */\r
+typedef struct {\r
+    uint32_t subsys;     /*!< Write for which sub system, varies for different device. */\r
+} tiot_service_tx_param;\r
+\r
+/**\r
+ * @brief  TIoT Rx param, for tiot_service_read_ext.\r
+ */\r
+typedef struct {\r
+    uint32_t timeout_ms; /*!< Wait timeout ms. */\r
+    uint32_t subsys;     /*!< Read for which sub system, varies for different device. */\r
+#ifdef __KERNEL__\r
+    struct file *filp;     /*!< for poll */\r
+    poll_table *poll_wait; /*!< for poll */\r
+#endif\r
+} tiot_service_rx_param;\r
+\r
+typedef enum {\r
+    TIOT_PM_CTRL_SUSPEND_PREPARE,\r
+    TIOT_PM_CTRL_SUSPEND,\r
+    TIOT_PM_CTRL_RESUME_PREPARE,\r
+    TIOT_PM_CTRL_RESUME,\r
+    TIOT_PM_CTRL_BUTT\r
+} tiot_service_pm_ctrl_cmd;\r
+\r
+/**\r
+ * @brief  TIoT Service Write Message extende interface.\r
+ * @param  [in]  data Data need to send.\r
+ * @param  [in]  len Data length.\r
+ * @param  [in]  param Write Param, see @ref tiot_service_tx_param.\r
+ * @return zero or postive for writen OK length;\r
+ *         negtive if write FAIL.\r
+ * @note   Will return after data is sent to board uart interface.\r
+ */\r
+int32_t tiot_service_write_ext(tiot_handle handle, const uint8_t *data,\r
+                               uint32_t len, const tiot_service_tx_param *param);\r
+\r
+/**\r
+ * @brief  TIoT Service Read Message extended interface.\r
+ * @param  [in/out] buff User read buff.\r
+ * @param  [in]  buff_len User read buff size.\r
+ * @param  [in]  param Read Param, see @ref tiot_service_rx_param.\r
+ * @return if read wait timeout(nothing to read), return 0.\r
+ *         if read fail, return -1.\r
+ *         if support ASCII message, message type(2 bytes, ASCII or BINARY) and message will be copied to buff,\r
+ *         else only message will be copied to buff,\r
+ *         return read length.\r
+ * @note   This interface will return only single complete message once,\r
+ *         for continous message read, call this interface repeatly.\r
+ */\r
+int32_t tiot_service_read_ext(tiot_handle handle, uint8_t *buff, uint32_t buff_len, const tiot_service_rx_param *param);\r
+\r
+/**\r
+ * @brief  TIoT Service Pm Control interface.\r
+ * @param  [in]  handle Service instance handle, should be return by tiot_service_open.\r
+ * @param  [in]  cmd Service pm ctrl cmd.\r
+ * @return return 0 if success else return -1.\r
+ */\r
+int32_t tiot_service_pm_ctrl(tiot_handle handle, tiot_service_pm_ctrl_cmd cmd);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/pm/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6d6660d
--- /dev/null
@@ -0,0 +1,18 @@
+#===============================================================================\r
+# @brief    cmake make file\r
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+#===============================================================================\r
+set(\r
+    tiot_pm_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm.c\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_wakelock.c\r
+)\r
+\r
+add_subdirectory(pm_default)\r
+\r
+if(DEFINED CONFIG_DEV_TIOT_SLAVE)\r
+add_subdirectory(pm_slave)\r
+endif()\r
+\r
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)\r
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3f3d898
--- /dev/null
@@ -0,0 +1,7 @@
+set(
+    tiot_pm_default_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_default.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_default_src_list}" CACHE INTERNAL "tiot src list" FORCE)
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.c b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.c
new file mode 100644 (file)
index 0000000..01a60ef
--- /dev/null
@@ -0,0 +1,288 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT pm default. \n
+ *
+ * History: \n
+ * 2023-06-09, Create file. \n
+ */
+
+#include "tiot_pm_default.h"
+#include "tiot_pm_wakelock.h"
+#include "tiot_board_pin_port.h"
+#include "tiot_board_log.h"
+#include "tiot_controller.h"
+#include "tiot_xfer_utils.h"
+#include "tiot_board.h"
+#include "tiot_sys_msg_types.h"
+#ifdef CONFIG_PM_WAKEUP_BY_UART
+#include "tiot_board_uart_port.h"
+#endif
+
+tiot_pm_retcode tiot_pm_default_power_off(tiot_pm *pm)
+{
+    if (tiot_board_pin_set_level(pm->pm_info[TIOT_PIN_POWER_CTRL], TIOT_PIN_LEVEL_LOW) != 0) {
+        return TIOT_PM_EVTRET_FAIL;
+    }
+    /* 下电时unlock。 */
+    tiot_pm_wake_unlock();
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_default_power_on(tiot_pm *pm)
+{
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    const tiot_device_timings *timings = &ctrl->dev_info->timings;
+    uint32_t power_ctrl_pin = pm->pm_info[TIOT_PIN_POWER_CTRL];
+    int32_t ret = 0;
+    do {
+        ret = tiot_board_pin_set_level(power_ctrl_pin, TIOT_PIN_LEVEL_LOW);
+        if (ret != 0) {
+            tiot_print_err("[TIoT][pm]set pwr pin level low fail.\n");
+            break;
+        }
+        osal_msleep(timings->power_on_wait_ms);
+        ret = tiot_board_pin_set_level(power_ctrl_pin, TIOT_PIN_LEVEL_HIGH);
+        if (ret != 0) {
+            tiot_print_err("[TIoT][pm]set pwr pin level high fail.\n");
+            break;
+        }
+        osal_msleep(timings->boot_time_ms);
+    } while (0);
+
+    if (ret != 0) {
+        tiot_print_err("[TIoT:pm]power on fail.\n");
+        return TIOT_PM_EVTRET_FAIL;
+    }
+    /* 上电时lock。 */
+    tiot_pm_wake_lock();
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+/* 不可在中断环境下使用. */
+int32_t tiot_pm_check_sleeped(uint32_t wakein_pin, uint8_t check_times)
+{
+    int32_t ret;
+    uint8_t level;
+    uint8_t i;
+    const uint8_t sleep_check = check_times;      /* 等待睡眠,重试check_times次. */
+    const uint8_t sleep_wait_ms = 2;     /* 等待睡眠,每次等待2ms. */
+    /* 唤醒时,如果wakein_pin存在,检查wakein_pin拉低后再发送唤醒, 确保主机已休眠. */
+    if (wakein_pin == TIOT_PIN_NONE) {
+        return 0;
+    }
+    for (i = 0; i < sleep_check; i++) {
+        ret = tiot_board_pin_get_level(wakein_pin, &level);
+        if (ret != 0) {
+            tiot_print_err("[TIoT:pm]wakein pin level get error.\n");
+            return -1;
+        }
+        if (level == TIOT_PIN_LEVEL_LOW) {
+            return 0;
+        }
+        osal_msleep(sleep_wait_ms);
+    }
+    /* 此时device侧可能又重新拉高管脚通知有数据上报,保持状态即可, 响应event即转成work. */
+    tiot_print_warning("[TIoT:pm]wakein pin level high after check (%d) times.\n", sleep_check);
+    return -1;
+}
+
+#ifdef CONFIG_PM_WAKEUP_BY_UART
+tiot_pm_retcode tiot_pm_default_wakeup_device_by_uart(tiot_pm *pm)
+{
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    int32_t ret;
+    tiot_print_info("[TIoT][pm]wakeup device enter.\n");
+    const uint32_t wakeup_baudrate = 115200;    /* UART唤醒时设为115200波特率. */
+    const uint8_t wakeup_cmd = 0x00;
+    const uint8_t check_times = 10;
+    tiot_xfer_manager *xfer = &ctrl->transfer;
+    ret = tiot_pm_check_sleeped(pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST], check_times);
+    if (ret != 0) {
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+
+    tiot_uart_config old_config = { 0 };
+    tiot_uart_config wakeup_config = { wakeup_baudrate,
+        { .data_bits = TIOT_UART_ATTR_DATABIT_8, .parity = TIOT_UART_ATTR_PARITY_NONE,
+          .stop_bits = TIOT_UART_ATTR_STOPBIT_1, .flow_ctrl = TIOT_UART_ATTR_FLOW_CTRL_DISABLE } };
+    (void)tiot_xfer_get_config(xfer, &old_config);
+    (void)tiot_xfer_set_config(xfer, &wakeup_config);
+    ret = tiot_xfer_direct_send(xfer, &wakeup_cmd, sizeof(uint8_t));
+    (void)tiot_xfer_set_config(xfer, &old_config);
+    if (ret != sizeof(uint8_t)) {
+        return TIOT_PM_EVTRET_FAIL;
+    }
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+#endif
+
+tiot_pm_retcode tiot_pm_default_wakeup_device_by_gpio(tiot_pm *pm)
+{
+    int32_t ret;
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    const tiot_device_timings *timings = &ctrl->dev_info->timings;
+    uint32_t wakeup_device_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE];
+    const uint8_t check_times = 10;
+
+    tiot_print_info("[TIoT][pm]wakeup device enter.\n");
+    if (wakeup_device_pin == TIOT_PIN_NONE) {
+        tiot_print_err("[TIoT][pm]wakeup pin not set.\n");
+        return TIOT_PM_EVTRET_FAIL;
+    }
+
+    ret = tiot_pm_check_sleeped(pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST], check_times);
+    if (ret != 0) {
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+
+    do {
+        ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_LOW);
+        if (ret != 0) {
+            tiot_print_err("[TIoT][pm]set wakeup pin level low fail.\n");
+            break;
+        }
+        osal_msleep(timings->wakeup_pulse_ms);
+        ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_HIGH);
+        if (ret != 0) {
+            tiot_print_err("[TIoT][pm]set wakeup pin level high fail.\n");
+            break;
+        }
+        osal_msleep(timings->wakeup_pulse_ms);
+        ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_LOW);
+        if (ret != 0) {
+            tiot_print_err("[TIoT][pm]set wakeup pin level low fail.\n");
+            break;
+        }
+    } while (0);
+
+    if (ret != 0) {
+        return TIOT_PM_EVTRET_FAIL;
+    }
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+#ifdef CONFIG_PM_MANAGE_LOWPOWER
+tiot_pm_retcode tiot_pm_default_request_sleep_handle(tiot_pm *pm)
+{
+    const uint8_t allow_sleep_command[] = { 0x7e, 0x00, 0x06, 0x00,
+                                            SYS_PL_BFGNI_HOST_ASKTO_SLP,
+                                            0x7e };
+    int32_t ret;
+    tiot_controller *ctrl = NULL;
+    tiot_xfer_manager *xfer = NULL;
+    if (pm->work_vote == 1) {
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+    ctrl = tiot_container_of(pm, tiot_controller, pm);
+    xfer = &ctrl->transfer;
+    ret = xfer->xmit_ops->write(&xfer->xmit, allow_sleep_command, sizeof(allow_sleep_command));
+    if (ret != sizeof(allow_sleep_command)) {
+        tiot_print_alert("[TIoT:fatal]send allow sleep msg fail.\r\n");
+        return TIOT_PM_EVTRET_FAIL;
+    }
+    tiot_print_info("[TIoT][pm]allow device sleep.\n");
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_default_sleep_ack_handle(tiot_pm *pm)
+{
+    tiot_unused(pm);
+    /* device侧睡眠时可睡眠 */
+    tiot_pm_wake_unlock();
+    tiot_print_info("[TIoT][pm]goes to sleep.\n");
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+/*
+ * 非S3状态,由于在中断中无法等待Sleep Ack(dev wkup host gpio拉低),
+ * 所以在下发allow sleep消息后,就立刻释放唤醒锁进入睡眠。
+ */
+tiot_pm_retcode tiot_pm_default_request_sleep_ack_handle(tiot_pm *pm)
+{
+    tiot_pm_retcode ret = tiot_pm_default_request_sleep_handle(pm);
+    if (ret != TIOT_PM_EVTRET_NEXT_STATE) {
+        return ret;
+    }
+    return tiot_pm_default_sleep_ack_handle(pm);
+}
+
+int32_t tiot_pm_send_disallow_sleep(tiot_xfer_manager *xfer)
+{
+    const uint8_t disallow_sleep_command[] = { 0x7e, 0x00, 0x06, 0x00,
+                                               SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP,
+                                               0x7e };
+    int32_t ret;
+    ret = xfer->xmit_ops->write(&xfer->xmit, disallow_sleep_command, sizeof(disallow_sleep_command));
+    if (ret != sizeof(disallow_sleep_command)) {
+        tiot_print_alert("[TIoT:fatal]send disallow msg fail.\r\n");
+        return -1;
+    }
+    return 0;
+}
+
+tiot_pm_retcode tiot_pm_default_wakeup_ack_handle(tiot_pm *pm)
+{
+    int32_t ret;
+    uint8_t input_level = TIOT_PIN_LEVEL_LOW;
+    uint16_t pre_state = pm->state;
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    tiot_xfer_manager *xfer = &ctrl->transfer;
+    uint32_t wakeup_host_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];
+
+    if (wakeup_host_pin == TIOT_PIN_NONE) {
+        tiot_print_err("[TIoT][pm]wakeup ack event called but dev_wk_host pin is none.\n");
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+
+    /*
+     * host上电后处于INIT状态时,此时接收到device拉高wakeup_host gpio,则不能下发disallow消息,
+     * 否则会多lock()一次,导致host后续无法睡下去。
+     */
+    if (pre_state == TIOT_PM_STATE_INIT) {
+        /* INIT -> WORK */
+        return TIOT_PM_EVTRET_NEXT_STATE;
+    }
+
+    /* 有数据上报时不睡眠 */
+    /* 自唤醒流程: device_wake_out --> wake_lock -......-> request_sleep --> wake_unlock */
+    /* 当前在唤醒中断内持锁,并直接回复disallow消息。 */
+
+    /* check wakeup_ack */
+    ret = tiot_board_pin_get_level(wakeup_host_pin, &input_level);
+    if ((ret != 0) || (input_level == TIOT_PIN_LEVEL_LOW)) {
+        tiot_print_err("[TIoT][pm]get dev_wk_host pin level fail or false positive [state:0x%x].\n", pre_state);
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+    /* 使用临时flag区分suspend. */
+    if (xfer->xmit_suspend & TIOT_XFER_SUSPEND) {
+        tiot_print_info("[TIoT:pm]delay disallow msg [state:0x%x].\n", pre_state);
+        xfer->xmit_suspend |= TIOT_XFER_DELAY_MSG;
+    } else {
+        tiot_print_info("[TIoT][pm]send disallow sleep msg [state:0x%x].\n", pre_state);
+        if (tiot_pm_send_disallow_sleep(xfer) != 0) {
+            return TIOT_PM_EVTRET_FAIL;
+        }
+    }
+    if ((pre_state == TIOT_PM_STATE_SLEEP) || (pre_state == TIOT_PM_STATE_WAKING)) {
+        tiot_pm_wake_lock();
+    }
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_default_work_vote_up(tiot_pm *pm)
+{
+    /* 发送时不睡眠 */
+    tiot_pm_wake_lock();
+    pm->work_vote = 1;
+    return TIOT_PM_EVTRET_KEEP_STATE;
+}
+
+tiot_pm_retcode tiot_pm_default_work_vote_down(tiot_pm *pm)
+{
+    pm->work_vote = 0;
+    /* 发送结束后可睡眠 */
+    tiot_pm_wake_unlock();
+    return TIOT_PM_EVTRET_KEEP_STATE;
+}
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.h b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_default/tiot_pm_default.h
new file mode 100644 (file)
index 0000000..b9d4f9f
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT pm default. \n
+ *
+ * History: \n
+ * 2023-06-09, Create file. \n
+ */
+#ifndef TIOT_PM_DEFAULT_H
+#define TIOT_PM_DEFAULT_H
+
+#include "tiot_pm.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_pm_default PM Default Handlers
+ * @ingroup  tiot_common_pm
+ * @{
+ */
+
+/**
+ * @brief  Default power off handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_power_off(tiot_pm *pm);
+
+/**
+ * @brief  Default power on handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_power_on(tiot_pm *pm);
+
+#ifdef CONFIG_PM_WAKEUP_BY_UART
+/**
+ * @brief  Default wakeup by uart handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_wakeup_device_by_uart(tiot_pm *pm);
+#endif
+
+/**
+ * @brief  Default wakeup by gpio handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_wakeup_device_by_gpio(tiot_pm *pm);
+
+#ifdef CONFIG_PM_MANAGE_LOWPOWER
+/**
+ * @brief  Default request sleep handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_request_sleep_handle(tiot_pm *pm);
+
+/**
+ * @brief  Default sleep ack handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_sleep_ack_handle(tiot_pm *pm);
+
+/**
+ * @brief  Default request sleep ack handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_request_sleep_ack_handle(tiot_pm *pm);
+
+/**
+ * @brief  Default wakeup ack handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_wakeup_ack_handle(tiot_pm *pm);
+
+/**
+ * @brief  Default work vote up handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_work_vote_up(tiot_pm *pm);
+
+/**
+ * @brief  Default work vote down handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_default_work_vote_down(tiot_pm *pm);
+#endif
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/CMakeLists.txt
new file mode 100644 (file)
index 0000000..cdc63ca
--- /dev/null
@@ -0,0 +1,7 @@
+set(
+    tiot_pm_slave_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_slave.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_slave_src_list}" CACHE INTERNAL "tiot src list" FORCE)
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c
new file mode 100644 (file)
index 0000000..7e8669b
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description: TIoT pm slave. \n
+ *
+ * History: \n
+ * 2024-02-28, Create file. \n
+ */
+#include "tiot_pm_slave.h"
+#include "tiot_pm_wakelock.h"
+#include "tiot_board_pin_port.h"
+#include "tiot_board_log.h"
+#include "tiot_controller.h"
+#include "tiot_sys_msg_types.h"
+#include "tiot_packet.h"
+#include "tiot_board.h"
+
+tiot_pm_retcode tiot_pm_slave_power_off(tiot_pm *pm)
+{
+    tiot_unused(pm);
+    tiot_pm_wake_unlock();
+    tiot_print_info("[TIoT][pm]power off.\r\n");
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_power_on(tiot_pm *pm)
+{
+    tiot_unused(pm);
+    tiot_pm_wake_lock();
+    tiot_print_info("[TIoT][pm]power on.\r\n");
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_wakeup_handle(tiot_pm *pm)
+{
+    /* Only SLEEP -> WAKING */
+    uint32_t wakeup_in_pin;
+    uint32_t wakeup_out_pin;
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    const tiot_device_timings *timings = &ctrl->dev_info->timings;
+
+    if (pm->state != TIOT_PM_STATE_SLEEP) {
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+
+    tiot_pm_wake_lock();
+
+    wakeup_out_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];
+    if (wakeup_out_pin != TIOT_PIN_NONE) {
+        if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_LOW) != 0) {
+            tiot_print_err("[TIoT:pm]wakeout pin set level low fail.\r\n");
+            goto wakeout_fail;
+        }
+        osal_msleep(timings->wakeup_pulse_ms);
+        if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_HIGH) != 0) {
+            tiot_print_err("[TIoT:pm]wakeout pin set level high fail.\r\n");
+            goto wakeout_fail;
+        }
+    } else {
+        tiot_print_warning("[TIoT][pm]wakeout pin is invalid.\r\n");
+    }
+    /* 唤醒host/唤醒ack后关闭唤醒源中断使能. */
+    wakeup_in_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE];
+    tiot_board_pin_enable_int(wakeup_in_pin, TIOT_PIN_INT_DISABLE);
+    return TIOT_PM_EVTRET_NEXT_STATE;
+wakeout_fail:
+    tiot_pm_wake_unlock();
+    return TIOT_PM_EVTRET_FAIL;
+}
+
+#ifdef CONFIG_PM_MANAGE_LOWPOWER
+/* 不允许在中断环境下调用 */
+tiot_pm_retcode tiot_pm_slave_request_sleep_handle(tiot_pm *pm)
+{
+    int32_t ret;
+    tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm);
+    tiot_xfer_manager *xfer = &ctrl->transfer;
+    const uint8_t request_sleep_command = SYS_INF_REQUEST_SLEEP;
+    tiot_xfer_tx_param tx_param = { SUBSYS_SYS };
+
+    tiot_print_info("[TIoT][pm]request sleep enter.\n");
+
+    ret = tiot_xfer_send(xfer, &request_sleep_command, sizeof(request_sleep_command), &tx_param);
+    if (ret != sizeof(request_sleep_command)) {
+        tiot_print_err("[TIoT][pm]send request sleep msg fail.\r\n");
+        return TIOT_PM_EVTRET_FAIL;
+    }
+
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_sleep_ack_handle(tiot_pm *pm)
+{
+    uint32_t wakeup_in_pin;
+    uint32_t wakeup_out_pin;
+    /* When we reporting msg, ignore allow sleep msg. */
+    if (pm->work_vote == 1) {
+        return TIOT_PM_EVTRET_KEEP_STATE;
+    }
+
+    wakeup_out_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];
+    /* 睡眠前,slave侧拉低唤醒主机管脚. */
+    if (wakeup_out_pin != TIOT_PIN_NONE) {
+        if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_LOW) != 0) {
+            tiot_print_err("[TIoT][pm]wakeup_out_pin set low fail.\r\n");
+            return TIOT_PM_EVTRET_FAIL;
+        }
+    }
+    /* 进睡眠前 打开唤醒源中断使能. */
+    wakeup_in_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE];
+    tiot_board_pin_enable_int(wakeup_in_pin, TIOT_PIN_INT_ENABLE);
+    tiot_print_info("[TIoT][pm]goes to sleep.\r\n");
+    /* 移除否决票 */
+    tiot_pm_wake_unlock();
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_wakeup_ack_handle(tiot_pm *pm)
+{
+    tiot_unused(pm);
+    tiot_print_info("[TIoT][pm]wakeup succ.\r\n");
+    return TIOT_PM_EVTRET_NEXT_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_work_vote_up(tiot_pm *pm)
+{
+    /* Prevent sleeping while sending data. */
+    tiot_pm_wake_lock();
+    pm->work_vote = 1;
+    return TIOT_PM_EVTRET_KEEP_STATE;
+}
+
+tiot_pm_retcode tiot_pm_slave_work_vote_down(tiot_pm *pm)
+{
+    pm->work_vote = 0;
+    tiot_pm_wake_unlock();
+    return TIOT_PM_EVTRET_KEEP_STATE;
+}
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h b/code/sdk/drivers/peripheral/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h
new file mode 100644 (file)
index 0000000..7c15a97
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description: TIoT pm slave. \n
+ *
+ * History: \n
+ * 2024-02-28, Create file. \n
+ */
+#ifndef TIOT_PM_SLAVE_H
+#define TIOT_PM_SLAVE_H
+
+#include "tiot_pm.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_pm_slave PM Slave Handlers
+ * @ingroup  tiot_common_pm
+ * @{
+ */
+
+/**
+ * @brief  Slave power off handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_power_off(tiot_pm *pm);
+
+/**
+ * @brief  Slave power on handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_power_on(tiot_pm *pm);
+
+/**
+ * @brief  Slave wakeup by gpio handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_wakeup_handle(tiot_pm *pm);
+
+#ifdef CONFIG_PM_MANAGE_LOWPOWER
+/**
+ * @brief  Slave request sleep handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_request_sleep_handle(tiot_pm *pm);
+
+/**
+ * @brief  Slave sleep ack handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_sleep_ack_handle(tiot_pm *pm);
+
+/**
+ * @brief  Slave wakeup ack handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_wakeup_ack_handle(tiot_pm *pm);
+
+/**
+ * @brief  Slave work vote up handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_work_vote_up(tiot_pm *pm);
+
+/**
+ * @brief  Slave work vote down handler.
+ * @param  [in]  pm PM control block.
+ * @return see@ref tiot_pm_retcode.
+ */
+tiot_pm_retcode tiot_pm_slave_work_vote_down(tiot_pm *pm);
+
+#endif
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.c b/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.c
new file mode 100644 (file)
index 0000000..10a51fe
--- /dev/null
@@ -0,0 +1,149 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Power Manager module. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-27, Create file. \n\r
+ */\r
+\r
+#include "tiot_pm.h"\r
+#include "tiot_pm_wakelock.h"\r
+#include "tiot_osal.h"\r
+#include "securec.h"\r
+#include "tiot_controller.h"\r
+#include "tiot_board_log.h"\r
+\r
+typedef struct {\r
+    tiot_pm *pm;\r
+    uint16_t state;\r
+} pm_wait_state;\r
+\r
+/* 传入的event_map必须为静态申请数组 */\r
+int32_t tiot_pm_init(tiot_pm *pm, const uint32_t *pm_info,\r
+                     const tiot_pm_event_entry *event_map, uint8_t event_map_size)\r
+{\r
+    if ((pm == NULL) || (pm_info == NULL) || (event_map == NULL) || (event_map_size == 0)) {\r
+        tiot_print_dbg("[TIoT][pm]pm or pm info or event_map is NULL.\n");\r
+        return -1;\r
+    }\r
+    if (osal_wait_init(&pm->state_wait) != OSAL_SUCCESS) {\r
+        tiot_print_err("[TIoT][pm]pm wait init fail.\n");\r
+        return -1;\r
+    }\r
+\r
+    /* 外部确保为静态变量 */\r
+    pm->pm_info = pm_info;\r
+    pm->event_map = event_map;\r
+    pm->event_map_size = event_map_size;\r
+\r
+    /* 此队列仅用于处理中断内产生pm事件情况,按产生顺序排序,预计不会同时在多个中断内产生pm事件,预留8个已经足够. */\r
+    (void)memset_s(pm->event_queue_buff, TIOT_PM_EVENT_BUFF_MAX, 0, TIOT_PM_EVENT_BUFF_MAX);\r
+    tiot_circ_queue_init(&pm->event_queue, TIOT_PM_EVENT_BUFF_MAX,\r
+                         sizeof(tiot_pm_event), (uintptr_t)pm->event_queue_buff);\r
+    pm->is_in_event = 0;\r
+    pm->work_vote = 0;\r
+    pm->state = TIOT_PM_STATE_POWEROFF;\r
+    return 0;\r
+}\r
+\r
+static int32_t tiot_pm_handle_event(tiot_pm *pm, tiot_pm_event event)\r
+{\r
+    tiot_pm_retcode ret = TIOT_PM_EVTRET_NEXT_STATE;\r
+    /* 取对应事件的 [判断条件 - 执行处理 - 设置下个状态] 流程 */\r
+    const tiot_pm_event_entry *entry = &pm->event_map[event];\r
+\r
+    /* 当前状态不符合tag mask条件, 不需要处理,直接返回OK */\r
+    if ((pm->state & entry->condition_mask) == 0) {\r
+        tiot_print_dbg("[TIoT][pm]state %x not match condition %x, ignore event\n", pm->state, entry->condition_mask);\r
+        return 0;\r
+    }\r
+\r
+    /* pm处理过程持唤醒锁,防止pm未转换完状态就直接进sleep。 */\r
+    tiot_pm_wake_lock();\r
+\r
+    /* 当前状态符合tag mask条件,执行对应事件处理 */\r
+    /* 约定:handler为空不需要处理,例如上报业务消息说明芯片处于WORK状态,只需要切换状态即可 */\r
+    if (entry->handler != NULL) {\r
+        ret = entry->handler(pm);\r
+    }\r
+\r
+    if (ret == TIOT_PM_EVTRET_NEXT_STATE) {\r
+        /* 处理成功,设为下一个状态 */\r
+        tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, next_st: %x.\n", event, pm->state, entry->next_state);\r
+        pm->state = entry->next_state;\r
+        /* 切换状态时保证设置event. */\r
+        osal_wait_wakeup_interruptible(&pm->state_wait);\r
+    } else if (ret == TIOT_PM_EVTRET_FAIL) {\r
+        /* 处理失败,返回false. */\r
+        tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, event fail.\n", event, pm->state);\r
+        tiot_pm_wake_unlock();\r
+        return -1;\r
+    } else {   /* ret == TIOT_PM_EVTRET_KEEP_STATE */\r
+        /* 处理成功,保持当前状态 */\r
+        tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, keep state.\n", event, pm->state);\r
+    }\r
+    tiot_pm_wake_unlock();\r
+\r
+    return 0;\r
+}\r
+\r
+int32_t tiot_pm_set_event(tiot_pm *pm, tiot_pm_event event)\r
+{\r
+    int32_t ret;\r
+    tiot_pm_event *event_node;\r
+\r
+    if ((pm == NULL) || (event >= TIOT_PM_EVENT_MAX) || (event >= pm->event_map_size)) {\r
+        tiot_print_dbg("[TIoT][pm]pm is NULL or illegal event.\n");\r
+        return -1;\r
+    }\r
+\r
+    tiot_circ_queue_enqueue(&pm->event_queue, (uintptr_t)&event);\r
+    /* 依靠队列防止pm事件处理嵌套,此处不使用互斥锁(可能在中断内产生事件),也不使用自旋锁(不能保证提供自旋锁) */\r
+    if (pm->is_in_event == 1) {\r
+        return 0;\r
+    }\r
+\r
+    do {\r
+        event_node = (tiot_pm_event *)tiot_circ_queue_dequeue(&pm->event_queue);\r
+        if (event_node == NULL) {\r
+            return 0;\r
+        }\r
+        pm->is_in_event = 1;\r
+        ret = tiot_pm_handle_event(pm, *event_node);\r
+        pm->is_in_event = 0;\r
+        if (ret != 0) {\r
+            tiot_circ_queue_clear(&pm->event_queue);\r
+            break;\r
+        }\r
+    } while (event_node != NULL);\r
+\r
+    return ret;\r
+}\r
+\r
+static int pm_wait_state_condition(const void *param)\r
+{\r
+    pm_wait_state *wait_state = (pm_wait_state *)param;\r
+    return (wait_state->pm->state == wait_state->state);\r
+}\r
+\r
+int32_t tiot_pm_wait_state(tiot_pm *pm, uint16_t state, uint32_t wait_timeout)\r
+{\r
+    pm_wait_state wait_state = { 0 };\r
+    if (state == TIOT_PM_STATE_INVALID) {\r
+        return -1;\r
+    }\r
+    wait_state.pm = pm;\r
+    wait_state.state = state;\r
+    return osal_wait_timeout_interruptible(&pm->state_wait, pm_wait_state_condition, &wait_state, wait_timeout);\r
+}\r
+\r
+void tiot_pm_deinit(tiot_pm *pm)\r
+{\r
+    tiot_circ_queue_clear(&pm->event_queue);\r
+    osal_spin_lock_destroy(&pm->event_queue.lock);\r
+    osal_wait_destroy(&pm->state_wait);\r
+    (void)memset_s(pm->event_queue_buff, TIOT_PM_EVENT_BUFF_MAX, 0, TIOT_PM_EVENT_BUFF_MAX);\r
+    pm->state = TIOT_PM_STATE_INVALID;\r
+    pm->work_vote = 0;\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.h b/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm.h
new file mode 100644 (file)
index 0000000..587d6c7
--- /dev/null
@@ -0,0 +1,182 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Power Manager module header. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-27, Create file. \n\r
+ */\r
+#ifndef TIOT_PM_H\r
+#define TIOT_PM_H\r
+\r
+#include "tiot_types.h"\r
+#include "tiot_circ_queue.h"\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_pm Power Manager\r
+ * @ingroup  tiot_common\r
+ * @{\r
+ */\r
+\r
+#define TIOT_PM_EVENT_BUFF_MAX    8\r
+\r
+/**\r
+ * @brief  TIoT PM tags.\r
+ */\r
+typedef enum {\r
+    TIOT_PM_TAG_INVALID = 0,                     /*!< Invalid PM tag. */\r
+    TIOT_PM_TAG_POWEROFF = ((uint16_t)1 << 0),   /*!< Power off tag. */\r
+    TIOT_PM_TAG_POWERON  = ((uint16_t)1 << 1),   /*!< Power on tag. */\r
+    /* Low power tags. */\r
+    TIOT_PM_TAG_CAN_WORK  = ((uint16_t)1 << 2),  /*!< Low power can work tag. */\r
+    TIOT_PM_TAG_CAN_SLEEP = ((uint16_t)1 << 3),  /*!< Low power can sleep tag. */\r
+    TIOT_PM_TAG_CAN_WAKEUP = ((uint16_t)1 << 4), /*!< Low power can wakeup tag. */\r
+    TIOT_PM_TAG_CAN_ALLOW_SLEEP = ((uint16_t)1 << 5), /*!< Low power can allow sleep tag. */\r
+    TIOT_PM_TAG_MAX = (uint16_t)0xFFFF           /* PM tag max. */\r
+} tiot_pm_tag;\r
+\r
+/**\r
+ * @brief  TIoT PM states.\r
+ */\r
+typedef enum {\r
+    TIOT_PM_STATE_INVALID = 0,                        /*!< Invalid PM state. */\r
+    TIOT_PM_STATE_POWEROFF = TIOT_PM_TAG_POWEROFF,    /*!< Power off state. */\r
+    TIOT_PM_STATE_POWERON = TIOT_PM_TAG_POWERON,      /*!< Power on state. */\r
+    /* Low power states */\r
+    /*!< Low power init state, can work, can sleep. */\r
+    TIOT_PM_STATE_INIT = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WORK | TIOT_PM_TAG_CAN_SLEEP,\r
+    /*!< Low power work state, can sleep, can allow sleep. */\r
+    /*!< Host: WORK -> SLEEPING -> SLEEP (正常睡眠流程,等待sleep ack)\r
+               WORK -> SLEEP (非S3状态,不等待sleep ack)\r
+       Device: WORK -> SLEEPING -> SLEEP (Device主动请求睡眠)\r
+               WORK -> SLEEP (S3状态,Host强制要求睡眠) */\r
+    TIOT_PM_STATE_WORK = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_SLEEP | TIOT_PM_TAG_CAN_ALLOW_SLEEP,\r
+    /*!< Low power sleep state, can work, can be waked up. */\r
+    TIOT_PM_STATE_SLEEP = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WORK | TIOT_PM_TAG_CAN_WAKEUP,\r
+    /*!< Low power waking state, can be waked up. */\r
+    TIOT_PM_STATE_WAKING = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WAKEUP,\r
+    /*!< Low power sleeping state, can allow sleep. */\r
+    TIOT_PM_STATE_SLEEPING = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_SLEEP\r
+} tiot_pm_state;\r
+\r
+/**\r
+ * @brief Tiot PM event types.\r
+ */\r
+typedef enum {\r
+    /* OUTPUT */\r
+    TIOT_PM_EVENT_POWEROFF,       /*!< Power off. */\r
+    TIOT_PM_EVENT_POWERON,        /*!< Power on. */\r
+    TIOT_PM_EVENT_WAKEUP,         /*!< Host: wakeup device.\r
+                                     Device: wakeup host(pull up dev_wkup_host gpio). */\r
+    /* INPUT,for host to manage device lowpower */\r
+    TIOT_PM_EVENT_WAKEUP_ACK,     /*!< Host: send disallow sleep cmd to ack(device wakeup host).\r
+                                     Device: handle the ack of disallow sleep cmd. */\r
+    TIOT_PM_EVENT_REQUEST_SLEEP,  /*!< Host: send allow sleep cmd.\r
+                                     Device: send request sleep cmd to request sleep. */\r
+    TIOT_PM_EVENT_SLEEP_ACK,      /*!< Host: handle the ack of allow sleep cmd.\r
+                                     Device: pull down dev_wkup_host gpio to ack (host allow sleep cmd). */\r
+    TIOT_PM_EVENT_REQUEST_SLEEP_ACK, /*!< Combine TIOT_PM_EVENT_REQUEST_SLEEP and TIOT_PM_EVENT_SLEEP_ACK */\r
+    TIOT_PM_EVENT_REPORT_WORK,    /*!< Device transmit port report message. */\r
+    /* Vote */\r
+    TIOT_PM_EVENT_WORK_VOTE_UP,   /*!< Host keep device at work state. */\r
+    TIOT_PM_EVENT_WORK_VOTE_DOWN, /*!< Host not keep device at work state. */\r
+    TIOT_PM_EVENT_MAX\r
+} tiot_pm_event;\r
+\r
+/**\r
+ * @brief Tiot PM event retcode.\r
+ */\r
+typedef enum {\r
+    TIOT_PM_EVTRET_FAIL = -1,         /* Event handle failed. */\r
+    TIOT_PM_EVTRET_NEXT_STATE = 0,    /* Change to next state. */\r
+    TIOT_PM_EVTRET_KEEP_STATE = 1,    /* Keep current state. */\r
+} tiot_pm_retcode;\r
+\r
+struct _tiot_pm;\r
+\r
+/**\r
+ * @brief  Tiot PM event handler.\r
+ */\r
+typedef tiot_pm_retcode (* tiot_pm_event_handler)(struct _tiot_pm *pm);\r
+\r
+/**\r
+ * @brief Tiot PM event handle entry.\r
+ */\r
+typedef struct {\r
+    uint16_t condition_mask;        /*!< Enter event condition, could be combination of PM tags. */\r
+    uint16_t next_state;            /*!< Next PM state. */\r
+    tiot_pm_event_handler handler;  /*!< PM event handler, NULL mean this event don't need operation. */\r
+} tiot_pm_event_entry;\r
+\r
+/**\r
+ * @brief Tiot PM control block.\r
+ */\r
+typedef struct _tiot_pm {\r
+    uint16_t state;                        /*!< Current PM state. */\r
+    uint16_t work_vote;                    /*!< Host require device work vote. */\r
+    const uint32_t *pm_info;               /*!< PM board info, pin indexs. */\r
+    osal_wait state_wait;                  /*!< PM state wait, used for wait some state. */\r
+    tiot_circ_queue_t event_queue;         /*!< PM event queue for syncing events. */\r
+    /*!< PM event queue buffer. */\r
+    tiot_pm_event event_queue_buff[TIOT_PM_EVENT_BUFF_MAX];\r
+    volatile uint8_t is_in_event;          /*!< PM event processing. */\r
+    uint8_t event_map_size;                /*!< PM event handle map size. */\r
+    /*!< PM event handle map, must point to static allocated array. */\r
+    const tiot_pm_event_entry *event_map;\r
+} tiot_pm;\r
+\r
+/**\r
+ * @brief  PM control block init.\r
+ * @param  [in]  pm        PM control block.\r
+ * @param  [in]  pm_info   Pointer to board PM info, static allocated, from device saved board info.\r
+ * @param  [in]  event_map Registed PM event handle map, static allocated, from *_device_info.c.\r
+ * @param  [in]  event_map_size Registed PM event handle map size.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_pm_init(tiot_pm *pm, const uint32_t *pm_info,\r
+                     const tiot_pm_event_entry *event_map, uint8_t event_map_size);\r
+\r
+/**\r
+ * @brief  Set event to PM control block.\r
+ * @param  [in]  pm    PM control block.\r
+ * @param  [in]  event PM event.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_pm_set_event(tiot_pm *pm, tiot_pm_event event);\r
+\r
+/**\r
+ * @brief  PM control block wait for state.\r
+ * @param  [in]  pm    PM control block.\r
+ * @param  [in]  state PM state,caller must ensure state is valid.\r
+ * @param  [in]  wait_timeout Wait timeout, shound not be too long.\r
+ * @return negative if wait state fail;\r
+ *         zero if wait state timeout;\r
+ *         postive if wait state OK.\r
+ */\r
+int32_t tiot_pm_wait_state(tiot_pm *pm, uint16_t state, uint32_t wait_timeout);\r
+\r
+/**\r
+ * @brief  PM control block deinit.\r
+ * @param  [in]  pm        PM control block.\r
+ */\r
+void tiot_pm_deinit(tiot_pm *pm);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.c b/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.c
new file mode 100644 (file)
index 0000000..1101a77
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2024-03-01, Create file. \n
+ */
+#include "tiot_pm_wakelock.h"
+#include "tiot_board_misc_port.h"
+#include "tiot_board_log.h"
+#include "tiot_osal.h"
+
+/* 所有controller共享同一个wakelock, 只有所有controller未持锁时才允许睡眠. */
+static tiot_board_wakelock g_top_wakelock;
+static osal_spinlock g_top_wakelock_spinlock;
+static uint16_t g_top_lock_count;
+
+int32_t tiot_pm_wake_lock_init(void)
+{
+    if (tiot_board_wake_lock_init(&g_top_wakelock) != 0) {
+        return -1;
+    }
+    if (osal_spin_lock_init(&g_top_wakelock_spinlock) != OSAL_SUCCESS) {
+        tiot_board_wake_lock_destroy(&g_top_wakelock);
+        return -1;
+    }
+    g_top_lock_count = 0;
+    return 0;
+}
+
+void tiot_pm_wake_lock(void)
+{
+    unsigned long flags;
+    osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags);
+    if (g_top_lock_count == 0) {
+        tiot_board_wake_lock(&g_top_wakelock);
+    }
+    g_top_lock_count++;
+    osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags);
+}
+
+void tiot_pm_wake_unlock(void)
+{
+    unsigned long flags;
+    osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags);
+    if (g_top_lock_count > 0) {
+        g_top_lock_count--;
+        /* 防止count为0时多次调用unlock接口。 */
+        if (g_top_lock_count == 0) {
+            tiot_board_wake_unlock(&g_top_wakelock);
+        }
+    }
+    osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags);
+}
+
+void tiot_pm_wake_lock_destroy(void)
+{
+    /* 确保destroy时一定释放。 */
+    unsigned long flags;
+    osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags);
+    if (g_top_lock_count > 0) {
+        tiot_print_err("[TIoT][wakelock]g_top_lock_count should be 0, but is %d\n", g_top_lock_count);
+        g_top_lock_count = 0;
+        tiot_board_wake_unlock(&g_top_wakelock);
+    }
+    osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags);
+
+    tiot_board_wake_lock_destroy(&g_top_wakelock);
+    osal_spin_lock_destroy(&g_top_wakelock_spinlock);
+}
+
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.h b/code/sdk/drivers/peripheral/gnss/driver/common/pm/tiot_pm_wakelock.h
new file mode 100644 (file)
index 0000000..f29b86a
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2024-03-01, Create file. \n
+ */
+#ifndef TIOT_PM_WAKELOCK_H
+#define TIOT_PM_WAKELOCK_H
+
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_pm_wakelock PM Wake Lock
+ * @ingroup  tiot_common_pm
+ * @{
+ */
+
+/**
+ * @if Eng
+ * @brief PM wake lock initialization interface.
+ * @return if OK return 0, else return -1.
+ * @else
+ * @brief PM唤醒锁初始化接口。
+ * @return 初始化成功返回0,否则返回-1。
+ * @endif
+ */
+int32_t tiot_pm_wake_lock_init(void);
+
+/**
+ * @if Eng
+ * @brief PM wake lock interface, support nested, pair with unlock.
+ * @else
+ * @brief PM唤醒锁接口,支持嵌套使用,需要和unlock配对。
+ * @endif
+ */
+void tiot_pm_wake_lock(void);
+
+/**
+ * @if Eng
+ * @brief PM wake unlock interface, support nested, pair with unlock.
+ * @else
+ * @brief PM唤醒解锁接口,支持嵌套使用,需要和lock配对。
+ * @endif
+ */
+void tiot_pm_wake_unlock(void);
+
+/**
+ * @if Eng
+ * @brief PM wake lock destroy interface.
+ * @else
+ * @brief PM唤醒锁销毁接口。
+ * @endif
+ */
+void tiot_pm_wake_lock_destroy(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9631fb6
--- /dev/null
@@ -0,0 +1,14 @@
+set(
+    tiot_sys_msg_handler_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_sys_msg_handle.c
+)
+
+if(DEFINED CONFIG_DEV_TIOT_SLAVE)
+list(
+    APPEND tiot_sys_msg_handler_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_sys_msg_slave_handle.c
+)
+endif()
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_sys_msg_handler_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c b/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c
new file mode 100644 (file)
index 0000000..f72d88c
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-02-29, Create file. \n
+ */
+#include "tiot_sys_msg_handle.h"
+#include "tiot_sys_msg_types.h"
+#include "tiot_pm.h"
+#include "tiot_board_log.h"
+
+void tiot_pkt_sys_msg_handle(tiot_controller *ctrl, uint8_t code)
+{
+    if ((code == SYS_INF_GNSS_INIT) || (code == SYS_INF_GNSS_LPPE_INIT)) {
+        tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK);
+    } else if (code == SYS_INF_REQUEST_SLEEP) {
+        tiot_print_info("[TIoT:pkt]recv request sleep\n");
+        tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REQUEST_SLEEP_ACK);
+    } else {
+        tiot_print_warning("[TIoT:pkt]recv unknown sys msg:0x%x\n", code);
+    }
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h b/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h
new file mode 100644 (file)
index 0000000..154645a
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-02-29, Create file. \n
+ */
+#ifndef TIOT_SYS_MSG_HANDLE_H
+#define TIOT_SYS_MSG_HANDLE_H
+
+#include "tiot_controller.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+void tiot_pkt_sys_msg_handle(tiot_controller *ctrl, uint8_t code);
+
+void tiot_pkt_sys_msg_slave_handle(tiot_controller *ctrl, uint8_t code);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c b/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c
new file mode 100644 (file)
index 0000000..7b359ff
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-02-29, Create file. \n
+ */
+#include "tiot_sys_msg_handle.h"
+#include "tiot_sys_msg_types.h"
+#include "tiot_slave_board_port.h"
+#include "tiot_pm_slave.h"
+#include "tiot_board_log.h"
+
+void tiot_pkt_sys_msg_slave_handle(tiot_controller *ctrl, uint8_t code)
+{
+    switch (code) {
+        case SYS_PL_BFGNI_HOST_ASKTO_SLP:
+            tiot_print_info("[TIoT:pkt]recv allow sleep.\n");
+            tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_SLEEP_ACK);
+            break;
+        case SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP:
+            tiot_print_info("[TIoT:pkt]recv disallow sleep.\n");
+            tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_WAKEUP_ACK);
+            break;
+        default:
+            tiot_print_warning("[TIoT:pkt]recv unknown sys msg:0x%x\n", code);
+            break;
+    }
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h b/code/sdk/drivers/peripheral/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h
new file mode 100644 (file)
index 0000000..7c5cb36
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description: TIoT sys msg types. \n
+ *
+ * History: \n
+ * 2024-03-11, Create file. \n
+ */
+#ifndef TIOT_SYS_MSG_TYPES_H
+#define TIOT_SYS_MSG_TYPES_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_interface_types TIoT sys msg types.
+ * @ingroup  tiot_common_interface
+ * @{
+ */
+enum SYS_INF_MSG_VALUE_ENUM {
+    SYS_INF_PF_INIT = 0x00,                /* 平台软件初始化完成 */
+    SYS_INF_BT_INIT = 0x01,                /* BT软件初始化完成 */
+    SYS_INF_GNSS_INIT = 0x02,              /* GNSS软件初始化完成 */
+    SYS_INF_FM_INIT = 0x03,                /* FM软件初始化完成 */
+    SYS_INF_BT_DISABLE = 0x04,             /* BT禁能 */
+    SYS_INF_GNSS_DISABLE = 0x05,           /* GNSS禁能 */
+    SYS_INF_FM_DISABLE = 0x06,             /* FM禁能 */
+    SYS_INF_BT_EXIT = 0x07,                /* BT退出 */
+    SYS_INF_GNSS_EXIT = 0x08,              /* GNSS退出 */
+    SYS_INF_FM_EXIT = 0x09,                /* FM退出 */
+    SYS_INF_GNSS_WAIT_DOWNLOAD = 0x0A,     /* 等待GNSS代码下载 */
+    SYS_INF_GNSS_DOWNLOAD_COMPLETE = 0x0B, /* GNSS代码下载完毕 */
+    SYS_INF_BFG_HEART_BEAT = 0x0C,         /* 心跳信号 */
+    SYS_INF_DEV_AGREE_HOST_SLP = 0x0D,     /* device回复host可睡 */
+    SYS_INF_DEV_NOAGREE_HOST_SLP = 0x0E,   /* device回复host不可睡 */
+    SYS_INF_WIFI_OPEN = 0x0F,              /* WCPU上电完成 */
+    SYS_INF_IR_INIT = 0x10,                /* IR软件初始化完成 */
+    SYS_INF_IR_EXIT = 0x11,                /* IR退出 */
+    SYS_INF_NFC_INIT = 0x12,               /* NFC软件初始化完成 */
+    SYS_INF_NFC_EXIT = 0x13,               /* NFC退出 */
+    SYS_INF_WIFI_CLOSE = 0x14,             /* WCPU下电完成 */
+    SYS_INF_RF_TEMP_NORMAL = 0x15,         /* RF温度正常 */
+    SYS_INF_RF_TEMP_OVERHEAT = 0x16,       /* RF温度过热 */
+    SYS_INF_MEM_DUMP_COMPLETE = 0x17,      /* bfgx异常时,MEM DUMP已完成 */
+    SYS_INF_WIFI_MEM_DUMP_COMPLETE = 0X18, /* bfgx异常时,MEM DUMP已完成 */
+    SYS_INF_UART_HALT_WCPU = 0x19,         /* uart halt wcpu ok */
+    SYS_INF_UART_LOOP_SET_DONE = 0x1a,     /* device 设置uart环回ok */
+    SYS_INF_CHR_ERRNO_REPORT = 0x1b,       /* device向host上报CHR异常码 */
+
+    SYS_INF_FAKE_CLOSE_BT =  0x1c,         /* FAKE CLOSE BT的ACK */
+    SYS_INF_RSV1 = 0x1d,                   /* rsv */
+    SYS_INF_RSV2 = 0x1e,                   /* rsv */
+
+    SYS_INF_GNSS_LPPE_INIT = 0x1F,         /* MP13 GNSS 新增的线程初始化完成 */
+    SYS_INF_GNSS_LPPE_EXIT = 0x20,         /* MP13 GNSS 新增的线程退出 */
+    SYS_INF_GNSS_TRICKLE_SLEEP = 0x21,     /* MP13 GNSS_TRICKLE_SLEEP */
+    SYS_INF_ENABLE_GPIO_WKUP_BFG_RSP = 0x22, /* 配置uart or gpio唤醒 */
+    SYS_INF_BOOT_UP_ACK = 0x23,             /* device启动时通过消息回复ack的场景(通常是通过GPIO回复ack) */
+    SYS_INF_WAKE_UP_ACK = 0x24,             /* device被唤醒时通过消息回复ack的场景(通常是通过GPIO回复ack) */
+    SYS_INF_SLE_INIT = 0x25,                /* SLE软件初始化完成 */
+    SYS_INF_SLE_EXIT = 0x26,                /* SLE退出 */
+    SYS_INF_REQUEST_SLEEP = 0x27,           /* device请求睡眠 */
+
+    SYS_INF_BUTT /* 枚举定义最大不能超过127,因为128~255被用来当做心跳的时间戳 */
+};
+
+enum SYS_PL_MSG_VALUE_ENUM {
+    SYS_PL_OPEN_BT = 0x0,
+    SYS_PL_CLOSE_BT = 0x1,
+    SYS_PL_OPEN_GNSS = 0x2,
+    SYS_PL_CLOSE_GNSS = 0x3,
+    SYS_PL_OPEN_FM = 0x4,
+    SYS_PL_CLOSE_FM = 0x5,
+    SYS_PL_OPEN_NFC = 0x6,
+    SYS_PL_CLOSE_NFC = 0x7,
+    SYS_PL_OPEN_IR = 0x8,
+    SYS_PL_CLOSE_IR = 0x9,
+    SYS_PL_OPEN_WIFI = 0xa,                  /* host通过uart打开WCPU */
+    SYS_PL_CLOSE_WIFI = 0xb,                 /* host通过uart关闭WCPU */
+
+    SYS_PL_READ_STACK = 0xc,                 /* host通过uart读栈,心跳超时时使用 */
+    SYS_PL_QUERY_RF_TEMP = 0xd,              /* host通过uart查询rf温度 */
+
+    SYS_PL_BFGNI_HOST_ASKTO_SLP = 0xe,       /* host allow device sleep */
+    SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP = 0xf, /* host disallow device sleep */
+
+    SYS_PL_BFGNI_SHUTDOWN = 0x10,
+    SYS_PL_ENABLE_PM = 0x11,                     /* enable plat dev lowpower feature */
+    SYS_PL_DISABLE_PM = 0x12,                    /* disable plat dev lowpower feature */
+    SYS_PL_BT_ENABLE_PM = 0x13,                  /* enable BT dev lowpower feature */
+    SYS_PL_BT_DISABLE_PM = 0x14,                 /* disable BT dev lowpower feature */
+    SYS_PL_GNSS_ENABLE_PM = 0x15,                /* enable GNSS dev lowpower feature */
+    SYS_PL_GNSS_DISABLE_PM = 0x16,               /* disable GNSS dev lowpower feature */
+    SYS_PL_NFC_ENABLE_PM = 0x17,                 /* enable NFC dev lowpower feature */
+    SYS_PL_NFC_DISABLE_PM = 0x18,                /* disable NFC dev lowpower feature */
+
+    SYS_PL_TEST_CAUSE_PANIC = 0x19,              /* HOST发命令,触发device进入exception */
+    SYS_PL_DUMP_RESET_WCPU = 0x1a,               /* host通过uart不掉电复位WCPU */
+
+    SYS_PL_HALT_WCPU = 0x1b,                     /* halt WCPU */
+    SYS_PL_READ_WLAN_PUB_REG = 0x1c,             /* 读取wcpu的公共寄存器 */
+    SYS_PL_READ_WLAN_PRIV_REG = 0x1d,            /* 读取wcpu的私有寄存器 */
+    SYS_PL_READ_WLAN_MEM = 0x1e,                 /* 读取wcpu的mem */
+
+    SYS_PL_EXCEP_RESET_WCPU = 0x1f,              /* wifi DFR WCPU复位 */
+
+    SYS_PL_SET_UART_LOOP_HANDLER = 0x20,         /* 设置device侧uart环回处理函数 */
+    SYS_PL_SET_UART_LOOP_FINISH = 0x21,          /* UART环回test ok,恢复gnss消息处理函数 */
+
+    SYS_PL_PM_DEBUG = 0x22,                      /* 低功耗维测开关 */
+    SYS_PL_BAUT_CHG_REQ_ACK = 0x23,              /* 波特率切换请求ACK */
+    SYS_PL_BAUT_CHG_COMPLETE = 0x24,             /* 波特率切换完成 */
+
+    SYS_PL_WIFI_OPEN_NOTIFY = 0x25,              /* wifi open  通知 */
+    SYS_PL_WIFI_CLOSE_NOTIFY = 0x26,             /* wifi close 通知 */
+
+    SYS_PL_CFG_OPEN_GLE  = 0x28,                 /* host通过uart打开GLE */
+    SYS_PL_CFG_CLOSE_GLE = 0x29,                 /* host通过uart打开GLE */
+
+    SYS_PL_PM_SET_WAKEUP_HOST_VALID = 0x30,     /* 根据板级连接配置device可以唤醒host */
+    SYS_PL_PM_SET_WAKEUP_HOST_INVALID = 0x31,   /* 根据板级连接配置device不需要唤醒host */
+
+    SYS_PL_BUTT
+};
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7ca3278
--- /dev/null
@@ -0,0 +1,21 @@
+set(\r
+    tiot_transfer_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_xfer.c\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_xfer_utils.c\r
+)\r
+\r
+set(\r
+    tiot_transfer_header_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}\r
+)\r
+\r
+if(DEFINED CONFIG_XFER_PACKET_TIOT)\r
+add_subdirectory(packet_handle/tiot_packet)\r
+endif()\r
+\r
+if(DEFINED CONFIG_XFER_PACKET_NCI)\r
+add_subdirectory(packet_handle/nci_packet)\r
+endif()\r
+\r
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_transfer_src_list}" CACHE INTERNAL "tiot src list" FORCE)\r
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_transfer_header_list}" CACHE INTERNAL "tiot header list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5ec3271
--- /dev/null
@@ -0,0 +1,8 @@
+set(
+    tiot_packet_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_packet_manager.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_packet.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_packet_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c
new file mode 100644 (file)
index 0000000..746933f
--- /dev/null
@@ -0,0 +1,919 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-08-03, Create file. \n
+ */
+
+#include "tiot_packet.h"
+#include "tiot_sys_msg_handle.h"
+#include "tiot_controller.h"
+#include "tiot_board_log.h"
+#include "tiot_board_pin_port.h"
+#include "tiot_xfer_utils.h"
+#include "securec.h"
+
+typedef enum {
+    TIOT_PKT_FRAME_IDLE,
+    TIOT_PKT_FRAME_HEAD,
+    TIOT_PKT_FRAME_PAYLOAD,
+    TIOT_PKT_FRAME_TAIL
+} tiot_pkt_rx_frame;
+
+typedef enum {
+    TIOT_PKT_RX_SEPERATE_START,
+    TIOT_PKT_RX_SEPERATE_COMMON,
+    TIOT_PKT_RX_SEPERATE_LAST,
+    TIOT_PKT_RX_COMPLETE,
+} tiot_pkt_rx_sep_tag;
+
+typedef void (* tiot_pkt_msg_handler)(tiot_packet_context *ctx);
+
+static void tiot_packet_sys_func(tiot_packet_context *ctx);
+static void tiot_packet_recv_not_seperated_data(tiot_packet_context *ctx);
+static void tiot_packet_recv_seperated_data(tiot_packet_context *ctx);
+static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue,
+                                           uint8_t *buff, uint32_t buff_len);
+
+static tiot_pkt_msg_handler g_tiot_pkt_msg_handle[MSG_BUTT] = {
+    [SYS_MSG] = tiot_packet_sys_func,                      // SYS_MSG = 0x00,         系统串口消息
+    [GNSS_FIRST_MSG] = tiot_packet_recv_seperated_data,    // GNSS_FIRST_MSG = 0x02,  GNSS串口消息,第一个分段消息
+    [GNSS_COMMON_MSG] = tiot_packet_recv_seperated_data,   // GNSS_COMMON_MSG = 0x03, GNSS串口消息,中间分段消息
+    [GNSS_LAST_MSG] = tiot_packet_recv_seperated_data,     // GNSS_LAST_MSG = 0x04,   GNSS串口消息,最后一个分段消息
+    [OML_MSG] = tiot_packet_recv_not_seperated_data,       // OML_MSG = 0x0e,         OML串口消息
+    [SLE_MSG] = tiot_packet_recv_not_seperated_data,       // SLE_MSG = 0x15,         SLE串口消息
+};
+
+static const tiot_packet_subsys_info g_tiot_pkt_subsys_info[SUBSYS_BUTT] = {
+    { PKG_SEPRETED, GNSS_FIRST_MSG, GNSS_COMMON_MSG, GNSS_LAST_MSG },
+    { PKG_NOT_SEPRETED, OML_MSG, OML_MSG, OML_MSG },
+    { PKG_NOT_SEPRETED, SYS_MSG, SYS_MSG, SYS_MSG }
+};
+
+/* 将旧packet节点推入队列,若队列已满,则丢包. */
+static inline void tiot_cur_packet_to_queue(tiot_packet_context *ctx)
+{
+    tiot_packet_manager_enqueue_packet(&ctx->rx_manager, ctx->rx_queue_id);
+    ctx->frame_cnt = 0;
+    ctx->packet = NULL;
+}
+
+/* 丢包时释放packet节点,重置当前packet节点为空,收到新数据时重新获取对应节点. */
+static inline void tiot_cur_packet_discard(tiot_packet_context *ctx)
+{
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC
+    if (ctx->packet != NULL) {
+        circ_buf_update_read_pos(&(ctx->rx_buff.buf), ctx->packet->len);
+    }
+#endif
+    tiot_packet_manager_discard_packet(&ctx->rx_manager, ctx->rx_queue_id);
+    ctx->frame_cnt = 0;
+    ctx->packet = NULL;
+}
+
+/* 按照subsys code更新当前packet节点. */
+static inline void tiot_cur_packet_update(tiot_packet_context *ctx, uint8_t subsys_code)
+{
+    uint16_t queue_id = ctx->rx_manager.match(subsys_code);
+    if ((ctx->packet == NULL) || (queue_id != ctx->rx_queue_id)) {
+        ctx->rx_queue_id = queue_id;
+        ctx->packet = tiot_packet_manager_get_packet(&ctx->rx_manager, queue_id);
+    }
+}
+
+static inline void packet_frame_error(tiot_packet_context *ctx)
+{
+    ctx->frame_error = 1;
+    ctx->pos = NULL;
+}
+
+static void tiot_packet_report_work(tiot_packet_context *ctx)
+{
+    tiot_controller *ctrl;
+    tiot_xfer_manager *xfer;
+    uint32_t wakein_pin;
+    if (ctx == NULL) {
+        return;
+    }
+    xfer = ctx->xfer;
+    if (xfer == NULL) {
+        return;
+    }
+    ctrl = tiot_container_of(xfer, tiot_controller, transfer);
+    wakein_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];
+    if (wakein_pin == TIOT_PIN_NONE) {
+        /* 没有dev_wkup_host管脚时,host不休眠(只是PM状态切换),通过上报消息来判断device状态 */
+        tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK);
+    }
+}
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+static inline tiot_packet_rx_node *tiot_packet_rx_node_malloc(uint32_t len)
+{
+    tiot_packet_rx_node *node = (tiot_packet_rx_node *)osal_kmalloc(sizeof(tiot_packet_rx_node) + len, OSAL_GFP_KERNEL);
+    if (node == NULL) {
+        tiot_print_err("[TIoT]pkt rx node malloc fail.");
+        return NULL;
+    }
+    node->data = (uint8_t *)node + sizeof(tiot_packet_rx_node);
+    node->len = len;
+    return node;
+}
+#endif
+
+int32_t tiot_packet_init(tiot_packet_context *ctx, tiot_xfer_manager *xfer, const tiot_packet_context_param *param)
+{
+    tiot_packet_buffer *buff;
+    if ((ctx == NULL) || (xfer == NULL) || (xfer->pkt_context != 0) || (param == NULL)) {
+        return -1;
+    }
+
+    /* 接收状态机初始状态均为0,只需要memset为0即可. */
+    (void)memset_s((void *)ctx, sizeof(tiot_packet_context), 0, sizeof(tiot_packet_context));
+    (void)memcpy_s((void *)&ctx->rx_manager, sizeof(tiot_packet_manager),
+                   &param->rx_manager_info, sizeof(tiot_packet_manager));
+
+    if (osal_mutex_init(&ctx->tx_packet_mutex) != OSAL_SUCCESS) {
+        tiot_print_err("[TIoT][pkt]tx packet mutex init failed.\n");
+        return -1;
+    }
+
+    if (tiot_packet_manager_init(&ctx->rx_manager) != 0) {
+        osal_mutex_destroy(&ctx->tx_packet_mutex);
+        return -1;
+    }
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    tiot_unused(buff);
+#else
+    buff = param->buff;
+    (void)memset_s(buff->start, buff->size, 0, buff->size);
+    circ_buf_init(&(ctx->rx_buff.buf), &(ctx->rx_buff.buff_write), &(ctx->rx_buff.buff_read), buff->start, buff->size);
+#endif
+    ctx->flags = param->flags;
+    ctx->xfer = xfer;
+    /* 调用tiot_xfer_install_packet后才注册到xfer内. */
+    return 0;
+}
+
+void tiot_packet_deinit(tiot_packet_context *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+    ctx->xfer = NULL;
+    ctx->packet = NULL;
+    tiot_packet_manager_deinit(&ctx->rx_manager);
+    osal_mutex_destroy(&ctx->tx_packet_mutex);
+}
+
+static void tiot_packet_sys_func(tiot_packet_context *ctx)
+{
+    uint8_t syschar = ctx->sys_msg;
+    tiot_xfer_manager *xfer = ctx->xfer;
+    tiot_controller *ctrl = tiot_container_of(xfer, tiot_controller, transfer);
+
+    if (ctrl->dev_info->pkt_sys_msg_handle != NULL) {
+        ctrl->dev_info->pkt_sys_msg_handle(ctrl, syschar);
+    } else {
+        tiot_print_warning("[TIoT][pkt]pkt_sys_msg_handle is NULL.\r\n");
+    }
+}
+
+static void tiot_packet_cums_recv_handle(tiot_packet_context *ctx)
+{
+    int32_t copy_len;
+    tiot_packet_queue *queue;
+    tiot_xfer_cbk_param rx_cbk_param = ctx->xfer->rx_cbk_param;
+
+    /* 直接使用上一次的rx_queue_id. */
+    queue = tiot_packet_manager_find_queue(&ctx->rx_manager, ctx->rx_queue_id);
+    if (queue == NULL) {
+        tiot_print_err("[TIoT:pkt]can't find subsys queue(%d).\r\n", ctx->rx_queue_id);
+        return;
+    }
+
+    if (rx_cbk_param.rx_callback != NULL) {
+        /* 用户注册了rx callback,直接就地处理 */
+        copy_len = tiot_packet_copy_from_queue(ctx, queue, rx_cbk_param.buff, rx_cbk_param.buff_len);
+        rx_cbk_param.rx_callback(rx_cbk_param.buff, copy_len);
+    } else {
+        /* 唤醒等待的reader */
+        osal_wait_wakeup_interruptible(&queue->rx_wait);
+    }
+}
+
+static void tiot_packet_recv_not_seperated_data(tiot_packet_context *ctx)
+{
+    /* 处理之前的包错误, 释放当前包 */
+    if (ctx->frame_error == 1) {
+        tiot_cur_packet_discard(ctx);
+        ctx->frame_error = 0;
+        return;
+    }
+    /* 正常完整包. */
+    ctx->packet->tag = TIOT_PKT_TAG_BINARY;
+    tiot_cur_packet_to_queue(ctx);
+    tiot_packet_cums_recv_handle(ctx);
+}
+
+static void tiot_packet_recv_seperated_data(tiot_packet_context *ctx)
+{
+    uint8_t subsys_code = ctx->head.subsys_code;
+    /* 包顺序检测 */
+    if (subsys_code == GNSS_FIRST_MSG) {
+        /* First 包必须为第一个包 */
+        if (ctx->frame_cnt != 1) {
+            tiot_print_err("[TIoT:pkt]parse error: expect first packet.\r\n");
+            packet_frame_error(ctx);
+        }
+        return;
+    }
+    if (subsys_code == GNSS_COMMON_MSG) {
+        /* 必须先有fisrt包再有common包,所以收到common包时frame_cnt最小为2 */
+        if (ctx->frame_cnt < 2) {
+            tiot_print_err("[TIoT:pkt]parse error: expect first-common packet.\r\n");
+            packet_frame_error(ctx);
+        }
+        return;
+    }
+    /* 收完Last包数据才处理之前的包序错误, 确保完整包被释放 */
+    if ((subsys_code == GNSS_LAST_MSG) && (ctx->frame_error == 1)) {
+        tiot_print_err("[TIoT:pkt]packet order error, discard the whole packet.\r\n");
+        tiot_cur_packet_discard(ctx);
+        ctx->frame_error = 0;
+        return;
+    }
+    /* 正常完整包. */
+    ctx->packet->tag = TIOT_PKT_TAG_BINARY;
+    tiot_cur_packet_to_queue(ctx);
+    tiot_packet_cums_recv_handle(ctx);
+}
+
+static int32_t tiot_packet_head_check(tiot_packet_head *head)
+{
+    /* 包头错误!!! */
+    if (head->head != TIOT_PKT_HEAD) {
+        tiot_print_err("[TIoT:pkt]head error: 0x%x\r\n", head->head);
+        return -1;
+    }
+    /* 子系统错误 */
+    if (head->subsys_code >= MSG_BUTT) {
+        tiot_print_err("[TIoT:pkt]subsys error: 0x%x\r\n", head->subsys_code);
+        return -1;
+    }
+    /* 系统消息特殊判断, 长度必须为0x6. */
+    if ((head->subsys_code == SYS_MSG) && (head->len != (TIOT_PKT_PKG_SIZE + sizeof(uint8_t)))) {
+        tiot_print_err("[TIoT:pkt]sys msg len error: 0x%x\r\n", head->len);
+        return -1;
+    }
+    /* payload大小 小于0 或大于最大包大小 */
+    if ((head->len <= TIOT_PKT_PKG_SIZE) ||
+        (head->len > (TIOT_PKT_PAYLOAD_MAX_SIZE + TIOT_PKT_PKG_SIZE))) {
+        tiot_print_err("[TIoT:pkt]payload error: 0x%x\r\n", head->len);
+        return -1;
+    }
+    return 0;
+}
+
+static int32_t tiot_packet_head_try_recovery(tiot_packet_context *ctx)
+{
+    uint8_t i;
+    uint8_t *head_data;
+    errno_t err;
+    head_data = (uint8_t *)&ctx->head;
+    /* 出现问题时,先把上一个起始标志位丢弃. */
+    for (i = 1; i < sizeof(tiot_packet_head); i++) {
+        /* 头部出现其他pkt_head时,可以尝试恢复. */
+        if (head_data[i] == TIOT_PKT_HEAD) {
+            break;
+        }
+    }
+    if (i == sizeof(tiot_packet_head)) {
+        return -1;
+    }
+    tiot_print_dbg("[TIoT][pkt]head: [%x %x %x %x].\r\n",
+                   head_data[0], head_data[1], head_data[2], head_data[3]);  /* 打印恢复前head数据. */
+    tiot_print_warning("[TIoT][pkt]head recovery.\r\n");
+    err = memmove_s((void *)&ctx->head, sizeof(tiot_packet_head), &head_data[i], sizeof(tiot_packet_head) - i);
+    if (err != EOK) {
+        tiot_print_err("[TIoT][pkt]memmove_s error.\r\n");
+        return -1;
+    }
+    /* 更新需要读取的个数 & 位置. */
+    ctx->frame_need_read = i;
+    ctx->pos = &head_data[sizeof(tiot_packet_head) - i];
+    return 0;
+}
+
+static void tiot_packet_head_done(tiot_packet_context *ctx)
+{
+    tiot_packet_head *head = &ctx->head;
+    uint16_t payload_len = head->len - TIOT_PKT_PKG_SIZE;
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    tiot_packet_rx_node *node = NULL;
+#endif
+    if (tiot_packet_head_check(head) != 0) {
+        if (tiot_packet_head_try_recovery(ctx) == 0) {
+            /* 恢复成功,继续处理. */
+            return;
+        }
+        goto discard;
+    }
+    /* 消息头校验OK时,认为work. */
+    tiot_packet_report_work(ctx);
+    /* 系统消息不分包特殊处理,避免申请内存. */
+    if (head->subsys_code == SYS_MSG) {
+        ctx->frame_need_read = sizeof(uint8_t);
+        ctx->pos = &ctx->sys_msg;
+        ctx->current_frame = TIOT_PKT_FRAME_PAYLOAD;
+        return;
+    }
+
+    tiot_cur_packet_update(ctx, head->subsys_code);
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    if (ctx->packet != NULL) {
+        node = tiot_packet_rx_node_malloc(payload_len);
+        if (node == NULL) {
+            packet_frame_error(ctx);
+        } else {
+            tiot_list_add_tail(&(node->node), ctx->packet->head);
+            ctx->pos = node->data;
+        }
+    } else {
+        tiot_print_err("[TIoT:rx]circ queue no space.\n");
+        packet_frame_error(ctx);
+    }
+#else
+    if ((ctx->packet == NULL) || (circ_buf_query_free(&(ctx->rx_buff.buf)) <= payload_len)) {
+        tiot_print_err("[TIoT:rx]circ queue or rx buff no space.\n");
+        packet_frame_error(ctx);
+    }
+    if (ctx->packet != NULL) {
+        ctx->packet->len += payload_len;
+    }
+#endif
+    ctx->frame_need_read = payload_len;
+    ctx->frame_cnt++;
+    ctx->current_frame = TIOT_PKT_FRAME_PAYLOAD;
+    return;
+
+discard:
+    tiot_cur_packet_discard(ctx);
+    ctx->current_frame = TIOT_PKT_FRAME_IDLE;
+}
+
+static void tiot_packet_payload_done(tiot_packet_context *ctx)
+{
+    ctx->current_frame = TIOT_PKT_FRAME_TAIL;
+    ctx->frame_need_read = TIOT_PKT_TAIL_SIZE;
+    ctx->pos = &ctx->tail;
+}
+
+static void tiot_packet_tail_done(tiot_packet_context *ctx)
+{
+    uint8_t tail = ctx->tail;
+    uint8_t subsys_code;
+    if (tail != TIOT_PKT_TAIL) {
+        tiot_cur_packet_discard(ctx);
+        ctx->current_frame = TIOT_PKT_FRAME_IDLE;
+        ctx->frame_error = 0;
+        return;
+    }
+
+    /* 在head done内已经确保subsys_code正确 */
+    subsys_code = ctx->head.subsys_code;
+    if (g_tiot_pkt_msg_handle[subsys_code] != NULL) {
+        g_tiot_pkt_msg_handle[subsys_code](ctx);
+    }
+    ctx->current_frame = TIOT_PKT_FRAME_IDLE;
+}
+
+uint32_t tiot_packet_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t data_len)
+{
+    uint16_t packet_len = (uint16_t)(data_len & 0xFFFF);  /* 取低16位,包格式只需要16位大小. */
+    uint32_t handle_len = packet_len < ctx->frame_need_read ? packet_len : ctx->frame_need_read;
+    ctx->frame_need_read -= handle_len;
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    if (ctx->pos != NULL) {
+        (void)memcpy_s(ctx->pos, handle_len, data, handle_len);
+        ctx->pos += handle_len;
+    } else {
+        tiot_print_dbg("[TIoT][rx]packet buff pos is NULL.\n");
+    }
+#else
+    /* 系统消息直接拷贝;buffer放不下时丢包处理,使用frame_error标识. */
+    if ((ctx->current_frame == TIOT_PKT_FRAME_PAYLOAD) &&
+        (ctx->head.subsys_code != SYS_MSG)) {
+        circ_buf_write_data(&(ctx->rx_buff.buf), data, handle_len, ctx->rx_buff.buff_write);
+        circ_buf_update_write_pos(&(ctx->rx_buff.buf), handle_len);
+    } else {
+        if (ctx->pos != NULL) {
+            (void)memcpy_s(ctx->pos, handle_len, data, handle_len);
+            ctx->pos += handle_len;
+        } else {
+            tiot_print_dbg("[TIoT][rx]packet buff pos is NULL.\n");
+        }
+    }
+#endif
+
+    if (ctx->frame_need_read != 0) {
+        return handle_len;
+    }
+
+    /* 完成一帧数据 */
+    switch (ctx->current_frame) {
+        case TIOT_PKT_FRAME_HEAD:
+            tiot_packet_head_done(ctx);
+            break;
+        case TIOT_PKT_FRAME_PAYLOAD:
+            tiot_packet_payload_done(ctx);
+            break;
+        case TIOT_PKT_FRAME_TAIL:
+            tiot_packet_tail_done(ctx);
+            break;
+        default:
+            tiot_print_dbg("[TIoT][rx]err frame: %d\n", ctx->current_frame);
+            break;
+    }
+    return handle_len;
+}
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+static inline void tiot_packet_ascii_line_store(tiot_packet_context *ctx, uint8_t *line_start, uint32_t line_len)
+{
+    tiot_packet_rx_node *node = tiot_packet_rx_node_malloc(line_len);
+    if (node == NULL) {
+        /* discard */
+        return;
+    }
+    (void)memcpy_s(node->data, line_len, line_start, line_len);
+    tiot_list_add_tail(&(node->node), ctx->packet->head);
+}
+#else
+static inline void tiot_packet_ascii_line_store(tiot_packet_context *ctx, uint8_t *line_start, uint32_t line_len)
+{
+    if (circ_buf_query_free(&(ctx->rx_buff.buf)) <= line_len) {
+        tiot_print_err("[TIoT][rx]rx buffer no space for data.");
+        return;
+    }
+    circ_buf_write(&(ctx->rx_buff.buf), line_start, line_len);
+    ctx->packet->len += line_len;
+}
+#endif
+
+static void tiot_packet_ascii_line_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t handle_len)
+{
+    uint8_t *left = data;
+    uint8_t *right = data;
+    uint32_t line_len = 0;
+    while (right < (data + handle_len)) {
+        if (*right != '\n') {
+            right++;
+            continue;
+        }
+        /* 找到行尾. */
+        line_len = right - left + 1; /* 当前字符也复制 '\n'. */
+        tiot_cur_packet_update(ctx, MSG_BUTT); /* ASCII消息使用MSG_BUTT,避免重复. */
+        if (ctx->packet != NULL) {
+            tiot_packet_ascii_line_store(ctx, left, line_len);
+            ctx->packet->tag = TIOT_PKT_TAG_ASCII;
+            tiot_cur_packet_to_queue(ctx);
+            tiot_packet_cums_recv_handle(ctx);
+        } else {
+            tiot_print_err("[TIoT:rx]circ queue no space, discard: 0x%x\r\n", line_len);
+        }
+        left = right + 1;  /* 下一行起始 */
+        right = left;
+    }
+    /* 最后一段没有结尾的情况 */
+    line_len = (data + handle_len) - left;
+    if (line_len == 0) {
+        return;
+    }
+    tiot_cur_packet_update(ctx, MSG_BUTT); /* ASCII消息使用MSG_BUTT,避免重复. */
+    if (ctx->packet != NULL) {
+        tiot_packet_ascii_line_store(ctx, left, line_len);
+        /* ASCII字符串结束判断. */
+        if (ctx->current_frame == TIOT_PKT_FRAME_HEAD) {
+            ctx->packet->tag = TIOT_PKT_TAG_ASCII;
+            tiot_cur_packet_to_queue(ctx);
+            tiot_packet_cums_recv_handle(ctx);
+        }
+    } else {
+        tiot_print_err("[TIoT:rx]circ queue no space, discard: 0x%x\r\n", line_len);
+    }
+}
+
+uint32_t tiot_packet_ascii_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t data_len)
+{
+    /* ascii字符串处理 */
+    uint32_t handle_len = 0;
+    uint8_t *tmp = data;
+    /* 寻找包头起始 */
+    while (handle_len < data_len) {
+        if (*tmp == 0x7e) {
+            break;
+        }
+        tmp++;
+        handle_len++;
+    }
+
+    if (handle_len < data_len) {
+        /* 找到包头 */
+        ctx->current_frame = TIOT_PKT_FRAME_HEAD;
+        ctx->frame_need_read = TIOT_PKT_HEAD_SIZE;
+        ctx->pos = (uint8_t *)&ctx->head;
+    }
+
+    if ((handle_len == 0) || !(ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII)) {
+        /* 1. 第一个字节即0x7e, 不需要处理. */
+        /* 2. 不支持上报ascii数据,直接丢包处理. */
+        goto discard;
+    }
+    /* 支持上报ascii数据时,有数据认为work. */
+    tiot_packet_report_work(ctx);
+    tiot_packet_ascii_line_handle(ctx, data, handle_len);
+discard:
+    return handle_len;
+}
+
+void tiot_packet_rx_data_parse(tiot_packet_context *ctx, uint8_t *data, uint32_t len)
+{
+    uint8_t *buff = data;
+    uint32_t handle_len = 0;
+    uint32_t total_len = len;
+
+    while (total_len) {
+        if (ctx->current_frame == TIOT_PKT_FRAME_IDLE) {
+            handle_len = tiot_packet_ascii_handle(ctx, buff, total_len);
+        } else {
+            handle_len = tiot_packet_handle(ctx, buff, total_len);
+        }
+        buff += handle_len;
+        total_len -= handle_len;
+    }
+}
+
+void tiot_packet_rx_data_store(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len)
+{
+    tiot_packet_context *ctx = NULL;
+    /* 入参已在调用处判空 */
+    ctx = (tiot_packet_context *)xfer->pkt_context;
+    tiot_packet_rx_data_parse(ctx, data, len);
+}
+
+static int tiot_packet_read_out_check(const void *param)
+{
+    int check;
+    tiot_packet_manager_query *query = (tiot_packet_manager_query *)param;
+    tiot_xfer_manager *xfer = query->xfer;
+    tiot_packet_context *ctx = (tiot_packet_context *)xfer->pkt_context;
+    if (ctx == NULL) {
+        tiot_print_warning("[TIoT][rx]read out check: pkt_context is NULL\n");
+        return 1;
+    }
+    check = (xfer->rx_wait_func(xfer) != 0) ||
+            (tiot_packet_manager_has_data(&ctx->rx_manager, query->queue_id));
+    return check;
+}
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+static int32_t tiot_packet_is_valid(tiot_packet *packet)
+{
+    uint16_t frame_cnt = 0;
+    tiot_packet_rx_node *pos;
+    if (packet->head == NULL) {
+        return -1;
+    }
+    tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) {
+        if ((pos->data == NULL) || (pos->len == 0)) {
+            return -1;
+        }
+        frame_cnt++;
+    }
+    if (frame_cnt == 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue,
+                                           uint8_t *buff, uint32_t buff_len)
+{
+    tiot_packet *packet = NULL;
+    uint8_t *tmp_buff = buff;
+    uint32_t copy_len;
+    tiot_packet_rx_node *pos;
+
+    do {
+        copy_len = 0;
+        packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue);
+        if (packet == NULL) {
+            tiot_print_info("[TIoT][rx]packet queue is empty.\n");
+            break;
+        }
+        if (tiot_packet_is_valid(packet) != 0) {
+            tiot_print_err("[TIoT][rx]invalid packet.");
+            tiot_packet_free_packet(packet);
+            continue;
+        }
+
+        tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) {
+            copy_len += pos->len;
+        }
+        if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) {
+            copy_len += sizeof(uint16_t);
+        }
+        if (copy_len > buff_len) {
+            tiot_print_info("[TIoT][rx]not enough buff len:%d for this packet: %d.", buff_len, copy_len);
+            tiot_packet_free_packet(packet);
+            continue;
+        }
+        /* 完整包正常, 复制一包到用户buffer后退出. */
+        if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) {
+            (void)memcpy_s((void *)tmp_buff, sizeof(uint16_t), (void *)&packet->tag, sizeof(uint16_t));
+            tmp_buff += sizeof(uint16_t);
+        }
+        tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) {
+            (void)memcpy_s((void *)tmp_buff, pos->len, (void *)pos->data, pos->len);
+            tmp_buff += pos->len;
+        }
+        tiot_packet_free_packet(packet);
+        break;
+    } while (packet != NULL);
+
+    return copy_len;
+}
+#else
+static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue,
+                                           uint8_t *buff, uint32_t buff_len)
+{
+    uint32_t copy_len;
+    uint8_t *tmp_buff = buff;
+    tiot_packet *packet;
+    do {
+        copy_len = 0;
+        packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue);
+        if (packet == NULL) {
+            tiot_print_info("[TIoT][rx]packet queue is empty.");
+            break;
+        }
+        copy_len = packet->len;
+        if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) {
+            copy_len += sizeof(uint16_t);
+        }
+        if (copy_len > buff_len) {
+            tiot_print_info("[TIoT][rx]not enough buff len:%d for this packet: %d.", buff_len, copy_len);
+            (void)circ_buf_update_read_pos(&(ctx->rx_buff.buf), packet->len);
+            continue;
+        }
+        /* 完整包正常, 复制一包到用户buffer后退出. */
+        if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) {
+            (void)memcpy_s((void *)tmp_buff, sizeof(uint16_t), (void *)&packet->tag, sizeof(uint16_t));
+            tmp_buff += sizeof(uint16_t);
+        }
+        /* 按顺序读即可,不需要记录起始. */
+        (void)circ_buf_read(&(ctx->rx_buff.buf), tmp_buff, packet->len);
+        break;
+    } while (packet != NULL);
+    return copy_len;
+}
+#endif
+
+#ifdef __KERNEL__
+static int32_t packet_poll(tiot_packet_manager_query *query, tiot_packet_queue *queue, const tiot_xfer_rx_param *param)
+{
+    if (tiot_packet_read_out_check(query) != 0) {
+        return 1;
+    }
+
+    poll_wait(param->filp, (wait_queue_head_t *)(queue->rx_wait.wait), param->poll_wait);
+
+    if (tiot_packet_read_out_check(query) != 0) {
+        return 1;
+    }
+    return 0;
+}
+#endif
+
+int32_t tiot_packet_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param)
+{
+    int32_t read_ret;
+    tiot_packet_queue *queue;
+    tiot_packet_manager_query query;
+    tiot_packet_context *ctx = (tiot_packet_context *)xfer->pkt_context;
+    if (ctx == NULL) {
+        return -1;
+    }
+    queue = tiot_packet_manager_find_queue(&ctx->rx_manager, param->subsys); /* 对应queue_id */
+    if (queue == NULL) {
+        return -1;
+    }
+    query.xfer = xfer;
+    query.queue_id = param->subsys;  /* 对应queue_id. */
+
+#ifdef __KERNEL__
+    if (param->filp != NULL && param->poll_wait != NULL) { /* poll mode */
+        return packet_poll(&query, queue, param);
+    }
+#endif
+
+    if (param->timeout == 0) { /* 非阻塞. */
+        /* 没有数据直接返回. */
+        if (tiot_packet_read_out_check(&query) == 0) {
+            tiot_print_dbg("[TIoT:pkt][%d]no data to read.\r\n", param->subsys);
+            return 0;
+        }
+    } else { /* 阻塞. */
+        if (queue->flags & TIOT_PACKET_QUEUE_RX_WAITING) {
+            tiot_print_err("[TIoT:pkt][%d]there's already a thread blocking read().\r\n", param->subsys);
+            return -1;
+        }
+        queue->flags |= TIOT_PACKET_QUEUE_RX_WAITING;
+        /* 等待接收到一个完整包. */
+        read_ret = osal_wait_timeout_interruptible(&queue->rx_wait, tiot_packet_read_out_check, &query, param->timeout);
+        if (xfer->pkt_context == 0) {
+            read_ret = 0;
+        }
+        queue->flags &= ~TIOT_PACKET_QUEUE_RX_WAITING;
+        if (read_ret <= 0) {
+            tiot_print_warning("[TIoT:pkt][%d]osal_wait timeout.\r\n", param->subsys);
+            return read_ret;
+        }
+    }
+
+    return tiot_packet_copy_from_queue(ctx, queue, buff, len);
+}
+
+#ifdef CONFIG_XFER_SUPPORT_TX_TASK
+static int32_t tiot_tx_packet_fill(uint8_t *dest, uint8_t *payload, uint16_t payload_len, uint8_t subsys_code)
+{
+    uint16_t packet_len = payload_len + TIOT_PKT_PKG_SIZE;
+    uint8_t *packet_buff = dest;
+
+    tiot_packet_head *head = (tiot_packet_head *)packet_buff;
+    head->head = TIOT_PKT_HEAD;
+    head->subsys_code = subsys_code;
+    head->len = packet_len;
+
+    if (memcpy_s(&packet_buff[TIOT_PKT_HEAD_SIZE], payload_len, payload, payload_len) != EOK) {
+        tiot_print_err("[TIoT][tx]packet memcpy err.\r\n");
+        return -1;
+    }
+    packet_buff[packet_len - 1] = TIOT_PKT_TAIL;
+    return 0;
+}
+
+int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len,
+                            const tiot_xfer_tx_param *param)
+{
+    int32_t ret;
+    uint16_t payload_len;
+    uint32_t total_len;
+    const uint8_t *buff;
+    uint8_t packet_count;
+    const tiot_packet_subsys_info *subsys_info;
+    tiot_xfer_tx_data new_data;
+
+    /* data外部已验证 */
+    if ((param == NULL) || (len == 0)) {
+        tiot_print_err("[TIoT:pkt]tx param is NULL or len is 0.\r\n");
+        return -1;
+    }
+
+    total_len = len;
+    subsys_info = &g_tiot_pkt_subsys_info[param->subsys];
+    /* 分包个数: tx_len / 4095 + (tx_len % 4095 ? 1 : 0) ==> (tx_len + (4095 - 1)) / 4095。 */
+    packet_count = (total_len + TIOT_PKT_PAYLOAD_MAX_SIZE - 1) / TIOT_PKT_PAYLOAD_MAX_SIZE;
+    /* 预先申请 */
+    packet_buff = osal_kmalloc(total_len + packet_count * (TIOT_PKT_PKG_SIZE));
+    if (packet_buff == NULL) {
+        return -1;
+    }
+    tmp = packet_buff;
+
+    for (i = 0; i < packet_count - 1; i++) {
+        payload_len = TIOT_PKT_PAYLOAD_MAX_SIZE;
+        if (i == 0) {
+            ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->common);
+        } else {
+            ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->first);
+        }
+        if (ret != 0) {
+            /* 复制数据出错,释放buffer */
+            osal_kfree(packet_buff);
+            return -1;
+        }
+        tmp += payload_len + TIOT_PKT_PKG_SIZE;
+        buff += payload_len;
+    }
+
+    payload_len = total_len - (packet_count - 1) * TIOT_PKT_PAYLOAD_MAX_SIZE;
+    ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->last);
+    if (ret != 0) {
+        /* 复制数据出错,释放buffer */
+        osal_kfree(packet_buff);
+        return -1;
+    }
+
+    new_data.data = packet_buff;
+    new_data.len = total_len + packet_count * (TIOT_PKT_PKG_SIZE);
+    if (tiot_circ_queue_enqueue(&xfer->tx_queue, (uintptr_t)&new_data) != 0) {
+        osal_kfree(packet_buff);
+        return -1;
+    }
+    return (ret >= 0) ? total_len : (-1);
+}
+#else
+static int32_t tiot_tx_packet_push(tiot_xfer_manager *xfer, const uint8_t *payload,
+                                   uint16_t payload_len, uint8_t subsys_code)
+{
+    int32_t ret = 0;
+    uint16_t packet_len = payload_len + TIOT_PKT_PKG_SIZE;
+    const uint8_t tail = TIOT_PKT_TAIL;
+    tiot_packet_head head = { TIOT_PKT_HEAD, subsys_code, packet_len };
+
+    do {
+        ret = tiot_xfer_direct_send(xfer, (uint8_t *)&head, sizeof(tiot_packet_head));
+        if (ret != sizeof(tiot_packet_head)) {
+            ret = -1;
+            break;
+        }
+        ret = tiot_xfer_direct_send(xfer, payload, payload_len);
+        if (ret != payload_len) {
+            ret = -1;
+            break;
+        }
+        ret = tiot_xfer_direct_send(xfer, &tail, sizeof(uint8_t));
+        if (ret != sizeof(uint8_t)) {
+            ret = -1;
+            break;
+        }
+    } while (0);
+
+    return (ret >= 0) ? (int32_t)packet_len : (-1);
+}
+
+int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len,
+                            const tiot_xfer_tx_param *param)
+{
+    int32_t ret;
+    uint16_t payload_len;
+    uint32_t total_len;
+    const uint8_t *buff;
+    uint8_t packet_count;
+    uint8_t i;
+    const tiot_packet_subsys_info *subsys_info;
+    tiot_packet_context *pkt_ctx;
+
+    /* data外部已验证 */
+    if ((param == NULL) || (len == 0)) {
+        tiot_print_err("[TIoT:pkt]tx param is NULL or len is 0.\r\n");
+        return -1;
+    }
+
+    pkt_ctx = (tiot_packet_context*)(xfer->pkt_context);
+    if (pkt_ctx == NULL) {
+        tiot_print_err("[TIoT][pkt]packet context is NULL.\r\n");
+        return -1;
+    }
+
+    total_len = len;
+    buff = data;
+    /* 分包个数: tx_len / 4095 + (tx_len % 4095 ? 1 : 0) ==> (tx_len + (4095 - 1)) / 4095。 */
+    packet_count = (total_len + TIOT_PKT_PAYLOAD_MAX_SIZE - 1) / TIOT_PKT_PAYLOAD_MAX_SIZE;
+    subsys_info = &g_tiot_pkt_subsys_info[param->subsys];
+
+    /*
+     * 多线程并发情况下,必须保证每个线程完整地发完整个packet,中间不能插入同类型的其他packet
+     * thread1:  gnss-first           gnss-last
+     * thread2:            gnss-first
+     * 像如上情况就会出现first-first-last,导致解包出现错误
+     */
+    osal_mutex_lock(&pkt_ctx->tx_packet_mutex);
+
+    for (i = 0; i < packet_count - 1; i++) {
+        payload_len = TIOT_PKT_PAYLOAD_MAX_SIZE;
+        if (i == 0) {
+            ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->first);
+        } else {
+            ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->common);
+        }
+
+        if (ret == -1) {
+            osal_mutex_unlock(&pkt_ctx->tx_packet_mutex);
+            return -1;
+        }
+        buff += payload_len;
+    }
+    payload_len = total_len - (packet_count - 1) * TIOT_PKT_PAYLOAD_MAX_SIZE;
+    ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->last);
+
+    osal_mutex_unlock(&pkt_ctx->tx_packet_mutex);
+
+    return (ret >= 0) ? (int32_t)total_len : (-1);
+}
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h
new file mode 100644 (file)
index 0000000..9fa18d7
--- /dev/null
@@ -0,0 +1,205 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-07-21, Create file. \n
+ */
+#ifndef TIOT_PACKET_H
+#define TIOT_PACKET_H
+
+#include "tiot_types.h"
+#include "tiot_xfer.h"
+#include "tiot_list.h"
+#include "tiot_packet_manager.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_transfer_packet_handle_tiot_packet Packet Handle
+ * @ingroup  tiot_common_transfer_packet_handle
+ * @{
+ */
+
+#define TIOT_PKT_FLAGS_SUPPORT_ASCII       0x1U
+
+#define TIOT_PKT_PAYLOAD_MAX_SIZE 4095U
+#define TIOT_PKT_HEAD_SIZE 4
+#define TIOT_PKT_TAIL_SIZE 1
+#define TIOT_PKT_PKG_SIZE  (TIOT_PKT_HEAD_SIZE + TIOT_PKT_TAIL_SIZE)
+
+#define TIOT_PKT_HEAD  0x7e
+#define TIOT_PKT_TAIL  0x7e
+
+/* 重新定义, 暂时只需要这些 */
+typedef enum {
+    SUBSYS_GNSS = 0x00,
+    SUBSYS_OM  = 0x01,
+    SUBSYS_SYS  = 0x02,
+    SUBSYS_BUTT
+} subsys_type_enum;
+
+typedef enum {
+    TIOT_PKT_TAG_BINARY,
+    TIOT_PKT_TAG_ASCII
+} tiot_pkt_rx_tag;
+
+typedef enum {
+    PKG_NOT_SEPRETED = 0,
+    PKG_SEPRETED = 1,
+} pkg_sepreted_state;
+
+enum TIOT_PKT_DATA_MSG_TYPE_ENUM {
+    SYS_MSG = 0x00,         /* 系统串口消息 */
+    BT_MSG = 0x01,          /* BT串口消息 */
+    GNSS_FIRST_MSG = 0x02,  /* GNSS串口消息,第一个分段消息 */
+    GNSS_COMMON_MSG = 0x03, /* GNSS串口消息,中间分段消息 */
+    GNSS_LAST_MSG = 0x04,   /* GNSS串口消息,最后一个分段消息 */
+    FM_FIRST_MSG = 0x05,    /* FM串口消息,第一个分段消息 */
+    FM_COMMON_MSG = 0x06,   /* FM串口消息,中间分段消息 */
+    FM_LAST_MSG = 0x07,     /* FM串口消息,最后一个分段消息 */
+    IR_FIRST_MSG = 0x08,    /* 红外串口消息,第一个分段消息 */
+    IR_COMMON_MSG = 0x09,   /* 红外串口消息,中间分段消息 */
+    IR_LAST_MSG = 0x0A,     /* 红外串口消息,最后一个分段消息 */
+    NFC_FIRST_MSG = 0x0B,   /* NFC串口消息,第一个分段消息 */
+    NFC_COMMON_MSG = 0x0C,  /* NFC串口消息,中间分段消息 */
+    NFC_LAST_MSG = 0x0D,    /* NFC串口消息,最后一个分段消息 */
+    OML_MSG = 0x0E,         /* 可维可测消息 */
+    MEM_DUMP_SIZE = 0x0f,   /* bfgx异常时,要dump的mem长度消息 */
+    MEM_DUMP = 0x10,        /* bfgx异常时,内存dump消息 */
+    WIFI_MEM_DUMP = 0x11,   /* UART READ WIFI MEM,内存dump消息 */
+    BFGX_CALI_MSG = 0x12,   /* BFGX 校准数据上报 */
+
+    /* GF_CPU消息 */
+    GF_SYS_MSG = 0x13,      /* GF系统串口消息 */
+    GF_OML_MSG = 0x14,      /* GF可维可测消息 */
+
+    SLE_MSG = 0x15,         /* SLE串口消息 */
+
+    MSG_BUTT,
+};
+
+typedef struct {
+    uint8_t seperated;
+    uint8_t first;
+    uint8_t common;
+    uint8_t last;
+} tiot_packet_subsys_info;
+
+typedef struct {
+    uint8_t head;
+    uint8_t subsys_code;
+    uint16_t len;
+} tiot_packet_head;
+
+typedef struct {
+    uint8_t *start;
+    uint32_t size;
+    uint32_t recv_cnt;
+} tiot_packet_buffer;
+
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC
+typedef struct {
+    tiot_circ_buf buf;
+    uint32_t buff_write;
+    uint32_t buff_read;
+} tiot_packet_circ_buffer;
+#endif
+
+typedef struct {
+    uint32_t flags;              /*!< Control behave. */
+    tiot_packet_manager rx_manager_info;
+    tiot_packet_buffer *buff;
+} tiot_packet_context_param;
+
+/**
+ * @brief  Packet parser context.
+ */
+typedef struct {
+    tiot_packet_manager rx_manager;
+    tiot_packet *packet;
+    uint32_t flags;              /*!< Control behave. */
+    osal_mutex tx_packet_mutex;
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC
+    tiot_packet_circ_buffer rx_buff;
+#endif
+    /* Rx State machine. */
+    uint8_t *pos;
+    tiot_packet_head head;
+    uint8_t tail;
+    uint8_t sys_msg;
+    uint8_t frame_error;
+    uint16_t frame_cnt;
+    uint16_t current_frame;
+    uint16_t frame_need_read;
+    uint16_t rx_queue_id;
+
+    tiot_xfer_manager *xfer;  /*!< Connect transfer manager. */
+} tiot_packet_context;
+
+typedef struct {
+    tiot_xfer_tx_data data;
+    uint16_t subsys;
+} tiot_packet_tx_data;
+
+/**
+ * @brief  Packet context init.
+ * @param  [in]  ctx   packet context.
+ * @param  [in]  xfer  Transfer manager.
+ * @param  [in]  flags control flags.
+ * @return if OK, return 0, else return -1.
+ */
+int32_t tiot_packet_init(tiot_packet_context *ctx, tiot_xfer_manager *xfer, const tiot_packet_context_param *param);
+
+/**
+ * @brief  Packet context deinit.
+ * @param  [in]  ctx packet context.
+ */
+void tiot_packet_deinit(tiot_packet_context *ctx);
+
+/**
+ * @brief  tx packet push.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [out] data Caller send data.
+ * @param  [in]  len  Caller data len.
+ * @param  [in]  param Caller send param, must.
+ * @return if OK, return sent data, else return -1.
+ */
+int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len,
+                            const tiot_xfer_tx_param *param);
+
+/**
+ * @brief  rx data store.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [in]  data Received data.
+ * @param  [in]  len  Received data length.
+ */
+void tiot_packet_rx_data_store(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len);
+
+/**
+ * @brief  rx data read out, copy uint16_t data_tag and single complete packet into user buffer.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [out] buff User buffer.
+ * @param  [in]  len  Max read length.
+ * @param  [in]  param Caller receive param.
+ * @return int32_t if OK, return readout length;if wait timeout, return 0; if err, return -1.
+ * @note   First two bytes copyed to buff indicate data type, ASCII or BINARY.
+ */
+int32_t tiot_packet_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c
new file mode 100644 (file)
index 0000000..9f11492
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2024-01-27, Create file. \n
+ */
+
+#include "tiot_packet_manager.h"
+#include "tiot_osal.h"
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+void tiot_packet_free_packet(tiot_packet *packet)
+{
+    tiot_packet_rx_node *pos, *next;
+    tiot_list_head_create(tmp_head);
+    if ((packet == NULL) || (packet->head == NULL)) {
+        return;
+    }
+    tiot_list_replace(packet->head, &tmp_head);
+    /* 使用临时节点遍历删除. */
+    tiot_list_for_each_entry_safe(pos, next, &tmp_head, node, tiot_packet_rx_node, tiot_packet_rx_node) {
+        if (pos != NULL) {
+            tiot___list_del_entry(&pos->node);
+            osal_kfree(pos);
+        }
+    }
+    osal_kfree(packet->head);
+}
+#endif
+
+void tiot_packet_queue_deinit(tiot_packet_queue *queue)
+{
+    /* 唤醒并等待可能的blocking-read()线程正常退出 */
+    osal_wait_wakeup_interruptible(&queue->rx_wait);
+    while (queue->flags & TIOT_PACKET_QUEUE_RX_WAITING) {
+        osal_msleep(1);
+    }
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    /* 动态申请buffer时才需要清除. */
+    /* 释放所有未处理缓存数据. */
+    tiot_packet *packet = NULL;
+    tiot_packet_free_packet(&queue->active_node);
+    do {
+        packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue);
+        if (packet == NULL) {
+            break;
+        }
+        tiot_packet_free_packet(packet);
+    } while (packet != NULL);
+#endif
+    osal_spin_lock_destroy(&queue->queue.lock);
+    osal_wait_destroy(&queue->rx_wait);
+}
+
+tiot_packet *tiot_packet_manager_get_packet(tiot_packet_manager *manager, uint16_t queue_id)
+{
+    tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id);
+    if (queue == NULL) {
+        return NULL;
+    }
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    if (queue->active_node.head == NULL) {
+        queue->active_node.head = (struct tiot_list_head *)osal_kmalloc(sizeof(struct tiot_list_head), OSAL_GFP_KERNEL);
+        if (queue->active_node.head == NULL) {
+            return NULL;
+        }
+        tiot_init_list_head(queue->active_node.head);
+    }
+#endif
+    return &queue->active_node;
+}
+
+int32_t tiot_packet_manager_init(tiot_packet_manager *manager)
+{
+    uint16_t i, j;
+    if (manager->match == NULL) {
+        return -1;
+    }
+    for (i = 0; i < manager->queue_num; i++) {
+        if (tiot_packet_queue_init((tiot_packet_queue *)&(manager->queues[i])) != 0) {
+            for (j = 0; j < i; j++) { /* 释放之前已初始化的queue */
+                tiot_packet_queue_deinit((tiot_packet_queue *)&manager->queues[j]);
+            }
+            return -1;
+        }
+    }
+    return 0;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h
new file mode 100644 (file)
index 0000000..29605bb
--- /dev/null
@@ -0,0 +1,213 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+ *
+ * Description: TIoT Packet Manager. \n
+ *
+ * History: \n
+ * 2024-01-13, Create file. \n
+ */
+#ifndef TIOT_PACKET_MANAGER_H
+#define TIOT_PACKET_MANAGER_H
+
+#include "tiot_types.h"
+#include "tiot_xfer.h"
+#include "tiot_circ_queue.h"
+#include "tiot_list.h"
+#include "tiot_board_log.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_transfer_packet_handle_tiot_packet_manager Packet Manager
+ * @ingroup  tiot_common_transfer_packet_handle_tiot_packet
+ * @{
+ */
+
+#define TIOT_PACKET_QUEUE_RX_WAITING    0x1
+
+/**
+ * @brief  TIOT Complete Packet, simple replace for skb_queue.
+ */
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+typedef struct {
+    struct tiot_list_head *head;  /* Dynamic Allocated. */
+    uint16_t tag;                 /* BINARY | ASCII. */
+} tiot_packet;
+
+typedef struct {
+    struct tiot_list_head node;
+    uint8_t *data;
+    uint32_t len;
+} tiot_packet_rx_node;
+#else
+typedef struct {
+    uint32_t len;
+    uint16_t tag;        /* BINARY | ASCII. */
+} tiot_packet;
+#endif
+
+typedef struct {
+    tiot_circ_queue_t queue;
+    const tiot_packet *queue_nodes;
+    uint16_t queue_size;
+    uint8_t flags;
+    tiot_packet active_node;
+    osal_wait rx_wait;
+} tiot_packet_queue;
+
+typedef uint16_t (* tiot_packet_match_func)(uint32_t msg_type);
+
+typedef struct {
+    const tiot_packet_queue *queues;
+    uint16_t queue_num;
+    tiot_packet_match_func match;
+} tiot_packet_manager;
+
+typedef struct {
+    tiot_xfer_manager *xfer;
+    uint16_t queue_id;
+} tiot_packet_manager_query;
+
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+/**
+ * @if Eng
+ * @brief  Free TIoT packlet.
+ * @param  packet Pointer to TIoT packet.
+ * @else
+ * @brief  释放TIoT消息包。
+ * @param  packet TIoT消息包指针。
+ * @endif
+ */
+void tiot_packet_free_packet(tiot_packet *packet);
+#endif
+
+/**
+ * @if Eng
+ * @brief  Deinit packet queue.
+ * @param  queue Pointer to TIoT packet queue.
+ * @else
+ * @brief  去初始化包格式队列。
+ * @param  queue 包格式队列指针。
+ * @endif
+ */
+void tiot_packet_queue_deinit(tiot_packet_queue *queue);
+
+/**
+ * @if Eng
+ * @brief  Get packet pointer for queue_id, from packet manager.
+ * @param  manager Packet manager.
+ * @param  queue_id The index of queue in packet manager.
+ * @return Return packet pointer for queue_id,if no such queue or malloc fail, return NULL.
+ * @else
+ * @brief  从包管理器中获取指定队列ID的包。
+ * @param  manager 包管理器。
+ * @param  queue_id 包管理器内队列ID。
+ * @return 返回指定队列ID的包的指针,如果没有对应队列,或内存申请失败则返回NULL。
+ * @endif
+ */
+tiot_packet *tiot_packet_manager_get_packet(tiot_packet_manager *manager, uint16_t queue_id);
+
+/**
+ * @if Eng
+ * @brief  init packet manager.
+ * @param  manager Packet manager.
+ * @else
+ * @brief  初始化包包管理器。
+ * @param  manager 包管理器。
+ * @endif
+ */
+int32_t tiot_packet_manager_init(tiot_packet_manager *manager);
+
+static inline int32_t tiot_packet_queue_init(tiot_packet_queue *queue)
+{
+    const uint32_t queue_mem_size = queue->queue_size * sizeof(tiot_packet);
+    tiot_circ_queue_init(&queue->queue, queue->queue_size, sizeof(tiot_packet), (uintptr_t)queue->queue_nodes);
+    (void)memset_s((void *)queue->queue_nodes, queue_mem_size, 0, queue_mem_size);
+    (void)memset_s((void *)&queue->active_node, sizeof(tiot_packet), 0, sizeof(tiot_packet));
+    queue->flags = 0;
+    if (osal_wait_init(&queue->rx_wait) != OSAL_SUCCESS) {
+        return -1;
+    }
+    return 0;
+}
+
+static inline void tiot_packet_manager_deinit(tiot_packet_manager *manager)
+{
+    uint16_t i;
+    for (i = 0; i < manager->queue_num; i++) {
+        tiot_packet_queue_deinit((tiot_packet_queue *)&manager->queues[i]);
+    }
+}
+
+static inline tiot_packet_queue *tiot_packet_manager_find_queue(tiot_packet_manager *manager, uint16_t queue_id)
+{
+    tiot_packet_queue *queue = NULL;
+    if (manager == NULL) {
+        return queue;
+    }
+    if (queue_id < manager->queue_num) {
+        queue = (tiot_packet_queue *)&manager->queues[queue_id];
+    }
+    return queue;
+}
+
+static inline void tiot_packet_manager_enqueue_packet(tiot_packet_manager *manager, uint16_t queue_id)
+{
+    tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id);
+    if (queue == NULL) {
+        return;
+    }
+    if (tiot_circ_queue_enqueue(&queue->queue, (uintptr_t)&queue->active_node) != 0) {
+        tiot_print_err("[TIoT:rx]circ queue [%d] no space.\r\n", queue_id);
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+        tiot_packet_free_packet(&queue->active_node);
+#endif
+    }
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    /* 指针转移至循环队列内或已释放. */
+    queue->active_node.head = NULL;
+#else
+    queue->active_node.len = 0;
+#endif
+}
+
+static inline void tiot_packet_manager_discard_packet(tiot_packet_manager *manager, uint16_t queue_id)
+{
+    tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id);
+    if (queue == NULL) {
+        return;
+    }
+#ifdef CONFIG_BOARD_DYNAMIC_ALLOC
+    tiot_packet_free_packet(&queue->active_node);
+    /* 指针已释放. */
+    queue->active_node.head = NULL;
+#else
+    queue->active_node.len = 0;
+#endif
+}
+
+static inline int32_t tiot_packet_manager_has_data(tiot_packet_manager *manager, uint16_t queue_id)
+{
+    tiot_packet_queue *queue;
+    queue = tiot_packet_manager_find_queue(manager, queue_id);
+    if (queue == NULL) {
+        return 0;
+    }
+    return (tiot_circ_queue_empty(&queue->queue) == 0);
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.c b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.c
new file mode 100644 (file)
index 0000000..1b82ac8
--- /dev/null
@@ -0,0 +1,493 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT transfer module. \n
+ *
+ * History: \n
+ * 2023-04-18, Create file. \n
+ */
+#include "tiot_xfer.h"
+#include "tiot_xfer_utils.h"
+#include "tiot_board_log.h"
+
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+#define TIOT_XFER_MANAGER_MAX   16
+
+typedef enum {
+    TIOT_XFER_TASK_UNINIT,
+    TIOT_XFER_TASK_INIT,
+    TIOT_XFER_TASK_ABORT,
+} tiot_xfer_task_state;
+
+typedef struct {
+    osal_task *task;
+    tiot_xfer_manager *xfer_list[TIOT_XFER_MANAGER_MAX];
+    volatile uint16_t xfer_count;
+    volatile uint16_t state;
+    osal_wait tx_wait;
+} tiot_xfer_send_task;
+
+/* 单线程 */
+static tiot_xfer_send_task g_tiot_xfer_send_task = { 0 };
+
+static int32_t tiot_xfer_send_task_init(tiot_xfer_manager *xfer);
+static void tiot_xfer_send_task_quit(tiot_xfer_manager *xfer);
+
+static int32_t tiot_xfer_send_task_queue_init(tiot_xfer_manager *xfer)
+{
+    /* 仅单一发送队列 */
+    const uint32_t tx_queue_node_num = CONFIG_XFER_TX_NODE_NUM;
+    uint32_t tx_queue_mem_size = sizeof(tiot_xfer_tx_data) * tx_queue_node_num;
+    xfer->tx_queue_mem = (uintptr_t)osal_kmalloc(tx_queue_mem_size, OSAL_GFP_KERNEL);
+    if (xfer->tx_queue_mem == 0) {
+        tiot_print_err("[TIoT][xfer]tx queue malloc failed.\n");
+        return -1;
+    }
+    (void)memset_s((void *)xfer->tx_queue_mem, tx_queue_mem_size, 0, tx_queue_mem_size);
+    tiot_circ_queue_init(&xfer->tx_queue, tx_queue_node_num, sizeof(tiot_xfer_tx_data), xfer->tx_queue_mem);
+    return 0;
+}
+
+static void tiot_xfer_send_task_queue_deinit(tiot_xfer_manager *xfer)
+{
+    if (xfer->tx_queue_mem != 0) {
+        osal_kfree((void *)xfer->tx_queue_mem);
+        xfer->tx_queue_mem = 0;
+    }
+}
+#endif
+
+static inline int32_t tiot_xfer_default_rx_buff_init(tiot_xfer_manager *xfer)
+{
+#ifdef CONFIG_XFER_DEFAULT_RX_BUFF
+    (void)memset_s((void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE, 0, CONFIG_XFER_RX_BUFF_SIZE);
+    circ_buf_init(&xfer->rx_buff, &xfer->rx_buff_write, &xfer->rx_buff_read,
+                  (void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE);
+    return 0;
+#else
+    tiot_unused(xfer);
+    tiot_print_err("[TIoT][xfer]no rx buff, check tiot_autoconfig.h.\n");
+    return -1;
+#endif
+}
+
+int32_t tiot_xfer_init(tiot_xfer_manager *xfer, uintptr_t xmit_id, const tiot_xfer_device_info *dev_info)
+{
+    int32_t ret = 0;
+    const tiot_xmit_ops *xmit_ops;
+    /* 等待函数必须不为空,否则osal_wait_timeout_interruptible不能正常工作. */
+    if ((xfer == NULL) || (dev_info == NULL) || (dev_info->rx_wait_func == NULL)) {
+        return -1;
+    }
+    xmit_ops = tiot_xmit_get_ops(dev_info->xmit_type);
+    if (xmit_ops == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transmit type invalid.\n");
+        return -1;
+    }
+    xfer->tx_queue_mem = 0;
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+    /* 仅单一发送队列 */
+    ret = tiot_xfer_send_task_init(xfer);
+    if (ret != 0) {
+        goto rx_wait_err;
+    }
+#endif
+    if ((xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (tiot_xfer_default_rx_buff_init(xfer) != 0)) {
+        goto rx_wait_err;
+    }
+    if (osal_wait_init(&xfer->rx_wait) != OSAL_SUCCESS) {
+        tiot_print_err("[TIoT][xfer]rx wait init failed.\n");
+        goto rx_wait_err;
+    }
+    if (osal_mutex_init(&xfer->dev_mutex) != OSAL_SUCCESS) {
+        tiot_print_err("[TIoT][xfer]device mutex init failed.\n");
+        goto dev_mutex_err;
+    }
+    if (osal_mutex_init(&xfer->read_mutex) != OSAL_SUCCESS) {
+        tiot_print_err("[TIoT][xfer]read mutex init failed.\n");
+        goto read_mutex_err;
+    }
+
+    /* Transmit实例初始化. */
+    xfer->xmit_ops = xmit_ops;
+    xfer->xmit.id = xmit_id;
+    xfer->xmit_state = TIOT_XMIT_STATE_CLOSE;
+    /* 接收初始化 */
+    xfer->rx_wait_func = dev_info->rx_wait_func;
+    (void)memset_s(&xfer->config, sizeof(struct tiot_xmit_config), 0, sizeof(struct tiot_xmit_config));
+     /* 包格式处理初始化 */
+    (void)memset_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), 0, sizeof(tiot_xfer_packet_ops));
+    tiot_print_suc("[TIoT][xfer]transfer manager init succ.\n");
+    return ret;
+read_mutex_err:
+    osal_mutex_destroy(&xfer->dev_mutex);
+dev_mutex_err:
+    osal_wait_destroy(&xfer->rx_wait);
+rx_wait_err:
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+    tiot_xfer_send_task_quit(xfer);
+#endif
+    return -1;
+}
+
+void tiot_xfer_deinit(tiot_xfer_manager *xfer)
+{
+    if (xfer == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n");
+        return;
+    }
+
+    tiot_print_info("[TIoT][xfer]transfer manager deinit.\n");
+    /* 先关闭xfer保证硬件不再发送接收 */
+    tiot_xfer_close(xfer);
+
+    /* Transmit实例去初始化. */
+    (void)memset_s(&xfer->xmit, sizeof(tiot_xmit), 0, sizeof(tiot_xmit));
+    (void)memset_s(&xfer->config, sizeof(struct tiot_xmit_config), 0, sizeof(struct tiot_xmit_config));
+    xfer->xmit_ops = NULL;
+
+    tiot_xfer_uninstall_packet(xfer);
+
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+    tiot_xfer_send_task_quit(xfer);
+#endif
+    osal_wait_destroy(&xfer->rx_wait);
+
+    /* 互斥锁初始化 */
+    osal_mutex_destroy(&xfer->dev_mutex);
+    osal_mutex_destroy(&xfer->read_mutex);
+}
+
+int32_t tiot_xfer_install_packet(tiot_xfer_manager *xfer, tiot_xfer_packet_ops *pkt_ops, uintptr_t pkt_context)
+{
+    if (xfer == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n");
+        return -1;
+    }
+
+    osal_mutex_lock(&xfer->dev_mutex);
+    (void)memcpy_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), pkt_ops, sizeof(tiot_xfer_packet_ops));
+    xfer->pkt_context = pkt_context;
+    osal_mutex_unlock(&xfer->dev_mutex);
+    return 0;
+}
+
+void tiot_xfer_uninstall_packet(tiot_xfer_manager *xfer)
+{
+    if (xfer == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n");
+        return;
+    }
+
+    osal_mutex_lock(&xfer->dev_mutex);
+    xfer->pkt_context = 0;
+    memset_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), 0, sizeof(tiot_xfer_packet_ops));
+    osal_mutex_unlock(&xfer->dev_mutex);
+}
+
+int32_t tiot_xfer_open(tiot_xfer_manager *xfer, tiot_xfer_open_param *param)
+{
+    int32_t ret;
+    tiot_xmit_callbacks cbs = { tiot_xfer_rx_notify };
+    if (xfer == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n");
+        return -1;
+    }
+
+    osal_mutex_lock(&xfer->dev_mutex);
+    if (xfer->xmit_state != TIOT_XMIT_STATE_CLOSE) {
+        osal_mutex_unlock(&xfer->dev_mutex);
+        tiot_print_err("[TIoT][xfer]transmit state already opened.\n");
+        return -1;
+    }
+    ret = xfer->xmit_ops->open(&xfer->xmit, &cbs);
+    if (ret != 0) {
+        osal_mutex_unlock(&xfer->dev_mutex);
+        tiot_print_err("[TIoT][xfer]transmit open failed.\n");
+        return ret;
+    }
+
+    if ((xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (param != NULL)) {
+        (void)memcpy_s(&xfer->rx_cbk_param, sizeof(tiot_xfer_cbk_param),
+                       &param->rx_cbk_param, sizeof(tiot_xfer_cbk_param));
+    } else {
+        xfer->rx_cbk_param.rx_callback = NULL;
+    }
+
+    xfer->xmit_state = TIOT_XMIT_STATE_OPEN;
+
+    osal_mutex_unlock(&xfer->dev_mutex);
+    return ret;
+}
+
+int32_t tiot_xfer_set_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config)
+{
+    int32_t ret;
+    if ((xfer == NULL) || (config == NULL)) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager or config is NULL.\n");
+        return -1;
+    }
+    (void)osal_mutex_lock(&xfer->dev_mutex);
+    if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) {
+        tiot_print_dbg("[TIoT][xfer]transmit state closed, cannot set config.\n");
+        (void)osal_mutex_unlock(&xfer->dev_mutex);
+        return -1;
+    }
+    ret = xfer->xmit_ops->set_config(&xfer->xmit, config);
+    if (ret == 0) {
+        (void)memcpy_s(&xfer->config, sizeof(struct tiot_xmit_config), config, sizeof(struct tiot_xmit_config));
+    }
+    (void)osal_mutex_unlock(&xfer->dev_mutex);
+    return ret;
+}
+
+int32_t tiot_xfer_get_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config)
+{
+    if ((xfer == NULL) || (config == NULL)) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager or config is NULL.\n");
+        return -1;
+    }
+
+    (void)memcpy_s(config, sizeof(struct tiot_xmit_config), &xfer->config, sizeof(struct tiot_xmit_config));
+    return 0;
+}
+
+void tiot_xfer_close(tiot_xfer_manager *xfer)
+{
+    if (xfer == NULL) {
+        tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n");
+        return;
+    }
+
+    (void)osal_mutex_lock(&xfer->dev_mutex);
+    if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) {
+        (void)osal_mutex_unlock(&xfer->dev_mutex);
+        tiot_print_dbg("[TIoT][xfer]transmit state already closed.\n");
+        return;
+    }
+
+    xfer->xmit_ops->close(&xfer->xmit);
+    (void)memset_s(&xfer->rx_cbk_param, sizeof(tiot_xfer_cbk_param), 0, sizeof(tiot_xfer_cbk_param));
+
+    xfer->xmit_state = TIOT_XMIT_STATE_CLOSE;
+#ifdef CONFIG_XFER_DEFAULT_RX_BUFF
+    (void)memset_s((void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE, 0, CONFIG_XFER_RX_BUFF_SIZE);
+    circ_buf_flush(&xfer->rx_buff);
+#endif
+    (void)osal_mutex_unlock(&xfer->dev_mutex);
+    return;
+}
+
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+static int tiot_xfer_send_task_wait_condition(void *param)
+{
+    tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task;
+    if (send_task->state == TIOT_XFER_TASK_ABORT) {
+        return OSAL_WAIT_CONDITION_TRUE;
+    }
+
+    uint16_t xfer_count = g_tiot_xfer_send_task.xfer_count;
+    for (uint16_t i = 0; i < xfer_count; i++) {
+        if (tiot_circ_queue_empty(&xfer_list[i]->tx_queue) == 0) {
+            return OSAL_WAIT_CONDITION_TRUE;
+        }
+    }
+    return 0;
+}
+
+static void tiot_xfer_send_schedule(tiot_xfer_manager *xfer)
+{
+    if ((xfer == NULL) || (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE)) {
+        tiot_print_info("[TIoT][xfer]xfer is null or xmit close.");
+        return;
+    }
+    tiot_xfer_tx_data *node = NULL;
+    do {
+        node = (tiot_xfer_tx_data *)tiot_circ_queue_dequeue(&xfer->tx_queue);
+        if (node != NULL) {
+            tiot_xfer_direct_send(xfer, node->data, node->len);
+        } else {
+            tiot_print_info("[TIoT][xfer]tx queue is empty.");
+        }
+    } while (node != NULL);
+}
+
+static void tiot_xfer_send_task_handle(void *param)
+{
+    (void)param;
+    tiot_xfer_manager **xfer_list = g_tiot_xfer_send_task.xfer_list;
+    uint16_t xfer_count;
+    for (;;) {
+        /* 等待某个transfer manager有数据或退出 */
+        osal_wait_timeout_interruptible(&g_tiot_xfer_send_task.tx_wait, tiot_xfer_send_task_wait_condition,
+                                        NULL, OSAL_WAIT_FOREVER);
+        if (g_tiot_xfer_send_task.state == TIOT_XFER_TASK_ABORT) {
+            break;
+        }
+        xfer_count = g_tiot_xfer_send_task.xfer_count;
+        for (uint16_t i = 0; i < xfer_count; i++) {
+            tiot_xfer_send_schedule(xfer_list[i]);
+        }
+    }
+
+    /* 退出流程. */
+    g_tiot_xfer_send_task.state = TIOT_XFER_TASK_UNINIT;
+    osal_wait_wakeup(&g_tiot_xfer_send_task.tx_wait);
+}
+
+static int32_t tiot_xfer_send_task_init(tiot_xfer_manager *xfer)
+{
+    const uint32_t stack_size = 2048;
+    tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task;
+    if (send_task->xfer_count == 0) {
+        if (osal_wait_init(&send_task->tx_wait) != OSAL_SUCCESS) {
+            tiot_print_err("[TIoT][xfer]send task wait init failed.\n");
+            return -1;
+        }
+        send_task->task = osal_kthread_create(tiot_xfer_send_task_handle, NULL, "tiot_tx", stack_size);
+        if (send_task->task == NULL) {
+            osal_wait_destroy(&send_task->tx_wait);
+            tiot_print_err("[TIoT][xfer]send task init failed.\n");
+            return -1;
+        }
+    }
+    if (tiot_xfer_send_task_queue_init(xfer) != 0) {
+        return -1;
+    }
+    send_task->xfer_count++;
+    send_task->xfer_list[send_task->xfer_count] = xfer;
+    return 0;
+}
+
+static int tiot_xfer_send_task_quit_wait_condition(void *param)
+{
+    if (g_tiot_xfer_send_task.state == TIOT_XFER_TASK_UNINIT) {
+        return OSAL_WAIT_CONDITION_TRUE;
+    }
+    return 0;
+}
+
+/* Transfer manager去初始化时调用 */
+static void tiot_xfer_send_task_quit(tiot_xfer_manager *xfer)
+{
+    tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task;
+    uint16_t xfer_count = send_task->xfer_count;
+    uint16_t i = 0;
+    for (; i < xfer_count; i++) {
+        if (send_task->xfer_list[i] == xfer) {
+            send_task->xfer_list[i] = NULL;
+            break;
+        }
+    }
+    tiot_xfer_send_task_queue_deinit(xfer);
+    if (i == xfer_count) {
+        /* 未注册 */
+        return;
+    }
+    send_task->xfer_count--;
+    /* 当所有transfer manager均去初始化时,释放task */
+    if (send_task->xfer_count == 0) {
+        g_tiot_xfer_send_task.state = TIOT_XFER_TASK_ABORT;
+        osal_wait_wakeup(&g_tiot_xfer_send_task.tx_wait);
+        /* 等待任务退出 */
+        osal_wait_timeout_interruptible(&g_tiot_xfer_send_task.tx_wait,
+                                        tiot_xfer_send_task_quit_wait_condition, NULL, OSAL_WAIT_FOREVER);
+        osal_kthread_destroy(g_tiot_xfer_send_task.task, 0);
+        g_tiot_xfer_send_task.task = NULL;
+        (void)memset_s(&g_tiot_xfer_send_task, sizeof(tiot_xfer_send_task), 0, sizeof(tiot_xfer_send_task));
+    }
+}
+#endif
+
+int32_t tiot_xfer_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, const tiot_xfer_tx_param *param)
+{
+    int32_t ret;
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+    tiot_xfer_tx_data node = { data, len };
+#endif
+    if ((xfer == NULL) || (data == NULL)) {
+        tiot_print_err("[TIoT][xfer]transfer manager is NULL or input data is NULL.");
+        return -1;
+    }
+
+    if (xfer->pkt_ops.tx_push != NULL) {
+        ret = xfer->pkt_ops.tx_push(xfer, data, len, param);
+    } else {
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+        ret = tiot_circ_queue_enqueue(&xfer->tx_queue, (uintptr_t)&node);
+#else
+        ret = tiot_xfer_direct_send(xfer, data, len);
+#endif
+    }
+
+#ifdef CONFIG_XFER_TX_SUPPORT_TASK
+    tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task;
+    if (ret == 0) {
+        osal_wait_wakeup(&send_task->tx_wait);
+    }
+#endif
+    return ret;
+}
+
+void tiot_xfer_rx_notify(tiot_xmit *xmit, uint8_t *data, uint32_t len)
+{
+    int32_t ret = 0;
+    tiot_xfer_manager *xfer = (tiot_xfer_manager *)xmit;
+    if (xfer == NULL) {
+        tiot_print_err("[TIoT][rx]notified transmit is NULL.\n");
+        return;
+    }
+
+    /* 可能中断内被调用 */
+    if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) {
+        tiot_print_dbg("[TIoT][rx]transmit state closed.\n");
+        return;
+    }
+
+    if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) {
+        if ((data == NULL) || (len == 0)) {
+            tiot_print_err("[TIoT][rx]notified data is NULL or len is 0.\n");
+            return;
+        }
+        if (xfer->pkt_ops.rx_data_store != NULL) {
+            /* 由包格式决定什么时候唤醒rx_wait */
+            xfer->pkt_ops.rx_data_store(xfer, data, len);
+            return;
+        } else {
+            /* 存入默认buffer */
+            ret = tiot_xfer_read_store(&xfer->rx_buff, data, len);
+        }
+    }
+
+    if (ret == 0) {
+        osal_wait_wakeup_interruptible(&xfer->rx_wait);
+    } else {
+        tiot_print_err("[TIoT][rx]circ buff not stored.\n");
+    }
+}
+
+int32_t tiot_xfer_recv(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param)
+{
+    int32_t ret;
+    if ((xfer == NULL) || (param == NULL)) {
+        tiot_print_dbg("[TIoT][rx]transfer manager is NULL or param is NULL.\n");
+        return -1;
+    }
+
+    osal_mutex_lock(&xfer->dev_mutex);
+    if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) {
+        osal_mutex_unlock(&xfer->dev_mutex);
+        tiot_print_dbg("[TIoT][rx]transmit state closed.\n");
+        return -1;
+    }
+    osal_mutex_unlock(&xfer->dev_mutex);
+
+    if (xfer->pkt_ops.read_out != NULL) {
+        ret =  xfer->pkt_ops.read_out(xfer, buff, len, param);
+    } else {
+        /* 默认读取路径,固件加载时使用. */
+        ret = tiot_xfer_read_out(xfer, buff, len, param->timeout);
+    }
+
+    return ret;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.h b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer.h
new file mode 100644 (file)
index 0000000..d9866bf
--- /dev/null
@@ -0,0 +1,248 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT transfer module. \n
+ *
+ * History: \n
+ * 2023-04-18, Create file. \n
+ */
+#ifndef TIOT_XFER_H
+#define TIOT_XFER_H
+
+#include "tiot_board_xmit.h"
+#include "tiot_board_xmit_ops.h"
+#include "tiot_circ_queue.h"
+#include "tiot_circ_buf.h"
+#include "tiot_osal.h"
+#include "tiot_board_uart_port.h"
+
+#ifdef __KERNEL__
+#include <linux/poll.h>
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_transfer Transfer
+ * @ingroup  tiot_common
+ * @{
+ */
+
+/* 临时flags, 用于拆分低功耗持锁 & disallow消息. */
+#define TIOT_XFER_RESUME                0U
+#define TIOT_XFER_SUSPEND               ((uint16_t)1 << 1)
+#define TIOT_XFER_DELAY_MSG             ((uint16_t)1 << 2)
+
+#define TIOT_XFER_RECV_NO_WAIT       ((uint32_t)0)
+#define TIOT_XFER_RECV_WAIT_FOREVER  ((uint32_t)0xFFFFFFF)
+
+/**
+ * @brief  TIoT Transmit port state.
+ */
+typedef enum {
+    TIOT_XMIT_STATE_CLOSE,  /* TIoT Transmit state close. */
+    TIOT_XMIT_STATE_OPEN,   /* TIoT Transmit state open. */
+    TIOT_XMIT_STATE_BUSY    /* TIoT Transmit state busy for reading or writing. */
+} tiot_xmit_state;
+
+/**
+ * @brief  TIoT Transfer send node, cound be exetend by packet ops with other attributes.
+ */
+typedef struct {
+    const uint8_t *data;    /* Pointer to send buff. */
+    uint32_t len;     /* Send len. */
+} tiot_xfer_tx_data;
+
+/**
+ * @brief  TIoT Transfer send param, cound be exetend by packet ops with other attributes.
+ */
+typedef struct {
+    uint32_t subsys;     /* subsys info. */
+} tiot_xfer_tx_param;
+
+/**
+ * @brief  TIoT Transfer receive param, cound be exetend by packet ops with other attributes.
+ */
+typedef struct {
+    uint32_t timeout;    /* Read timeout by ms, 0 timeout means no wait. */
+    uint32_t subsys;     /* subsys info. */
+#ifdef __KERNEL__
+    struct file *filp;
+    poll_table *poll_wait;
+#endif
+} tiot_xfer_rx_param;
+
+struct _tiot_xfer_manager;
+struct _tiot_xfer_packet;
+
+/**
+ * @brief  TIoT Transfer packet operations.
+ */
+typedef struct {
+    /*!< Packet parse tx node, and push to transmit or tx queue. */
+    int32_t (* tx_push)(struct _tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len,
+                        const tiot_xfer_tx_param *param);
+    /*!< Read data out to caller buffer, same as tiot_xfer_recv. */
+    int32_t (* read_out)(struct _tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param);
+    /*!< For async read, store data from board transmit isr. */
+    void (* rx_data_store)(struct _tiot_xfer_manager *xfer, uint8_t *data, uint32_t len);
+} tiot_xfer_packet_ops;
+
+/**
+ * @brief  TIoT Transfer device info.
+ */
+typedef struct {
+    tiot_xmit_type xmit_type;
+    osal_wait_condition_func rx_wait_func;  /*!< Device related read wait func, could be gpio level. */
+} tiot_xfer_device_info;
+
+typedef struct {
+    uint8_t *buff;
+    uint32_t buff_len;
+    void (*rx_callback)(const uint8_t *buff, uint32_t len);
+} tiot_xfer_cbk_param;
+
+typedef struct {
+    tiot_xfer_cbk_param rx_cbk_param;
+} tiot_xfer_open_param;
+
+/**
+ * @brief  TIoT Transfer manager.
+ */
+typedef struct _tiot_xfer_manager {
+    /* Board transmit infos. */
+    tiot_xmit xmit;                   /*!< Board transmit instance. */
+    const tiot_xmit_ops *xmit_ops;    /*!< Board transmit operations. */
+    struct tiot_xmit_config config;   /*!< Board transmit config saved. */
+    uint16_t xmit_state;              /*!< Board transmit state, close or open. */
+    uint16_t xmit_suspend;            /*!< Tmp flag for suspend, will merge to state. */
+
+    /* Mutexes */
+    osal_mutex dev_mutex;             /*!< Transmit device mutex. */
+    osal_mutex read_mutex;            /*!< Transmit read mutex. */
+
+    /* Send */
+    tiot_circ_queue_t tx_queue;       /*!< Tx circular queue, with tiot_xfer_tx_node as node. */
+    uintptr_t tx_queue_mem;           /*!< Tx circular queue allocated memory. */
+
+    /* Recieve */
+    osal_wait rx_wait;
+    osal_wait_condition_func rx_wait_func;  /*!< Registed read wait func, could be gpio level. */
+
+    tiot_circ_buf rx_buff;            /*!< Rx circular buff. */
+    uint32_t rx_buff_write;           /*!< Rx circular buff write index. */
+    uint32_t rx_buff_read;            /*!< Rx circular buff read index. */
+#ifdef CONFIG_XFER_DEFAULT_RX_BUFF
+    /*!< Rx circular buff memory. */
+    uint8_t rx_buff_mem[CONFIG_XFER_RX_BUFF_SIZE];
+#endif
+
+    /* Packet */
+    tiot_xfer_packet_ops pkt_ops;    /*!< Packet operation, tx & rx data packet parse. */
+    uintptr_t pkt_context;           /*!< Packet operation used context. */
+
+    tiot_xfer_cbk_param rx_cbk_param;
+} tiot_xfer_manager;
+
+/**
+ * @brief  TIoT Transfer manager init.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [in]  xmit_id Board Transmit id.
+ * @param  [in]  dev_info Device Transfer related info.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_xfer_init(tiot_xfer_manager *xfer, uintptr_t xmit_id, const tiot_xfer_device_info *dev_info);
+
+/**
+ * @brief  TIoT Transfer manager deinit.
+ * @param  [in]  xfer Transfer manager.
+ */
+void tiot_xfer_deinit(tiot_xfer_manager *xfer);
+
+/**
+ * @brief  TIoT Transfer manager install packet.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [in]  pkt_ops Transfer packet ops.
+ * @param  [in]  pkt_context Transfer packet context.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_xfer_install_packet(tiot_xfer_manager *xfer, tiot_xfer_packet_ops *pkt_ops, uintptr_t pkt_context);
+
+/**
+ * @brief  TIoT Transfer manager uninstall packet.
+ * @param  [in]  xfer Transfer manager.
+ */
+void tiot_xfer_uninstall_packet(tiot_xfer_manager *xfer);
+
+/**
+ * @brief  TIoT Transfer manager open, with packet installed.
+ * @param  [in]  xfer Transfer manager.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_xfer_open(tiot_xfer_manager *xfer, tiot_xfer_open_param *param);
+
+/**
+ * @brief  TIoT Transfer manager close.
+ * @param  [in]  xfer Transfer manager.
+ */
+void tiot_xfer_close(tiot_xfer_manager *xfer);
+
+/**
+ * @brief  TIoT Transfer manager set config.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [in]  config New config to be set.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_xfer_set_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config);
+
+/**
+ * @brief  TIoT Transfer manager get config.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [out] config copy old transmit config to caller.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_xfer_get_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config);
+
+/**
+ * @brief  TIoT Transfer manager send.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [out] data Caller send data.
+ * @param  [in]  len  Caller data len.
+ * @param  [in]  param Caller send param, optional.
+ * @return if Send OK return actual send len, else return -1.
+ */
+int32_t tiot_xfer_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, const tiot_xfer_tx_param *param);
+
+/**
+ * @brief  TIoT Transfer RX read notify.
+ * @param  [in]  xmit Transmit instance, will be extend to Transfer manager instance.
+ * @param  [in]  data RX data need to read, could be NULL for sync read.
+ * @param  [in]  len  Rx data len need to read, 0 indicates sync read.
+ */
+void tiot_xfer_rx_notify(tiot_xmit *xmit, uint8_t *data, uint32_t len);
+
+/**
+ * @brief  TIoT Transfer receive.
+ * @param  [in]  xfer Transfer manager.
+ * @param  [out] data Caller read buff.
+ * @param  [in]  len  Caller expected read len.
+ * @param  [in]  param Caller receive param.
+ * @return if Read OK return actual read len, if timeout, return 0, else return -1.
+ */
+int32_t tiot_xfer_recv(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len, const tiot_xfer_rx_param *param);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.c b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.c
new file mode 100644 (file)
index 0000000..0393775
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-04-26, Create file. \n
+ */
+
+#include "tiot_xfer_utils.h"
+
+int32_t tiot_xfer_direct_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len)
+{
+    int32_t ret;
+    const uint8_t *buff = data;
+    uint32_t remain_len = len;
+    while (remain_len) {
+        /* 板级接口可能有单次发送限制. */
+        (void)osal_mutex_lock(&xfer->dev_mutex);
+        if (xfer->xmit_state != TIOT_XMIT_STATE_OPEN) {
+            ret = -1;
+        } else {
+            ret = xfer->xmit_ops->write(&xfer->xmit, buff, remain_len);
+        }
+        (void)osal_mutex_unlock(&xfer->dev_mutex);
+        /* 阻塞式接口,发送结果为0情况时继续发送 */
+        if (ret < 0) {
+            return -1;
+        }
+
+        remain_len -= ret;
+        buff += ret;
+    }
+    return len;
+}
+
+int32_t tiot_xfer_read_store(tiot_circ_buf *cb, uint8_t *data, uint32_t len)
+{
+    int32_t ret;
+    if ((cb == NULL) || (circ_buf_query_free(cb) < len)) {
+        return -1;
+    }
+    ret = circ_buf_write(cb, data, len);
+    if (ret == 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static int tiot_xfer_read_out_check(const void *param)
+{
+    tiot_xfer_manager *xfer = (tiot_xfer_manager *)param;
+    if ((xfer->rx_wait_func(xfer) != 0) ||
+        ((xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (circ_buf_query_busy(&xfer->rx_buff) != 0))) {
+        return 1;
+    }
+    return 0;
+}
+
+int32_t tiot_xfer_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, uint32_t timeout_ms)
+{
+    int32_t read_len;
+    int32_t timeout = osal_wait_timeout_interruptible(&xfer->rx_wait, tiot_xfer_read_out_check,
+                                                      (const void *)xfer, timeout_ms);
+    /* 超时返回 0, 失败返回-1 */
+    if (timeout <= 0) {
+        return timeout;
+    }
+    osal_mutex_lock(&xfer->dev_mutex);
+
+    if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) {
+        uint32_t buff_data_len = circ_buf_query_busy(&xfer->rx_buff);
+        read_len = buff_data_len < len ? buff_data_len : len;
+        read_len = circ_buf_read(&xfer->rx_buff, buff, read_len);
+        if (read_len == 0) {
+            read_len = -1;
+        }
+    } else {
+        read_len = xfer->xmit_ops->read(&xfer->xmit, buff, len);
+    }
+
+    osal_mutex_unlock(&xfer->dev_mutex);
+    return read_len;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.h b/code/sdk/drivers/peripheral/gnss/driver/common/transfer/tiot_xfer_utils.h
new file mode 100644 (file)
index 0000000..748e53f
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-04-26, Create file. \n
+ */
+#ifndef TIOT_XFER_UTILS_H
+#define TIOT_XFER_UTILS_H
+
+#include "tiot_xfer.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_transfer_utils Transfer Utils
+ * @ingroup  tiot_common_transfer
+ * @{
+ */
+
+int32_t tiot_xfer_direct_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len);
+
+int32_t tiot_xfer_read_store(tiot_circ_buf *cb, uint8_t *data, uint32_t len);
+
+int32_t tiot_xfer_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, uint32_t timeout_ms);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/utils/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7f5d5bc
--- /dev/null
@@ -0,0 +1,15 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+set(
+    utils_header_lists
+    "${CMAKE_CURRENT_SOURCE_DIR}"
+    "${CMAKE_CURRENT_SOURCE_DIR}/circ_buf"
+    "${CMAKE_CURRENT_SOURCE_DIR}/list"
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${utils_header_lists}" CACHE INTERNAL "tiot header list" FORCE)
+add_subdirectory(circ_queue)
+add_subdirectory(fileops)
+add_subdirectory(misc)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h
new file mode 100644 (file)
index 0000000..d1e538d
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd.. 2019-2024. All rights reserved.
+ * Description: audio circle buffer function
+ * Author: audio
+ * Create: 2019-05-30
+ */
+
+#ifndef TIOT_CIRC_BUF_H
+#define TIOT_CIRC_BUF_H
+
+#include "securec.h"
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+typedef struct {
+    volatile uint32_t *write; /* circle buffer write pointer */
+    volatile uint32_t *read;  /* circle buffer read pointer */
+    uint8_t *data;            /* circle buffer data virtual address */
+    uint32_t size;            /* circle buffer size */
+} tiot_circ_buf;
+
+static inline uint32_t circ_buf_min(uint32_t x, uint32_t y)
+{
+    return (x <= y) ? x : y;
+}
+
+static inline uint32_t saturate_add(uint32_t x, uint32_t y, uint32_t saturation)
+{
+    /* add x and y, saturate to saturation */
+    uint32_t x_temp = x + y;
+
+    return (x_temp >= saturation) ? (x_temp - saturation) : x_temp;
+}
+
+static inline void circ_buf_init(tiot_circ_buf *cb, uint32_t *write, uint32_t *read, void *data, uint32_t len)
+{
+    cb->write = write;
+    cb->read = read;
+    cb->data = (uint8_t*)data;
+    cb->size = len;
+
+    *cb->write = 0;
+    *cb->read = 0;
+}
+
+static inline void circ_buf_flush(tiot_circ_buf *cb)
+{
+    *cb->read = 0;
+    *cb->write = 0;
+}
+
+static inline uint32_t circ_buf_data_size(uint32_t write, uint32_t read, uint32_t size)
+{
+    return (write >= read) ? (write - read) : (size - read + write);
+}
+
+static inline uint32_t circ_buf_free_size(uint32_t write, uint32_t read, uint32_t size)
+{
+    return size - circ_buf_data_size(write, read, size);
+}
+
+static inline uint32_t __circ_buf_read_data(const tiot_circ_buf *cb, uint8_t *to, uint32_t len, uint32_t off)
+{
+    if ((len == 0) || (memcpy_s(to, len * sizeof(uint8_t), cb->data + off, len) != EOK)) {
+        return 0;
+    }
+
+    return len;
+}
+
+/* read data from circle buffer */
+static inline uint32_t circ_buf_read_data(const tiot_circ_buf *cb, uint8_t *to, uint32_t len, uint32_t off)
+{
+    uint32_t l = circ_buf_min(len, cb->size - off);
+
+    if (to == NULL) {
+        /* dump data in circle buffer */
+        return len;
+    }
+
+    return __circ_buf_read_data(cb, to, l, off) + __circ_buf_read_data(cb, to + l, len - l, 0);
+}
+
+static inline uint32_t __circ_buf_write_zero(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off)
+{
+    if ((len == 0) || (memset_s(cb->data + off, len, 0, len) != EOK)) {
+        return 0;
+    }
+    (void)from;
+    return len;
+}
+
+static inline uint32_t __circ_buf_write_data(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off)
+{
+    if ((len == 0) || (memcpy_s(cb->data + off, cb->size - off, from, len) != EOK)) {
+        return 0;
+    }
+
+    return len;
+}
+
+/*
+ * circ_buf_write_data - puts some data from kernel space into the circle buffer
+ * @cb: address of the circle buffer to be used
+ * @from: pointer to the data to be added
+ * @len: the length of the data to be added
+ * @off: data write offset in circle buffer
+ *
+ * Note: Check free space in circle buffer before calling this function
+ */
+static inline uint32_t circ_buf_write_data(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off)
+{
+    uint32_t l = circ_buf_min(len, cb->size - off);
+
+    /* generate mute data if input buffer is NULL */
+    uint32_t (*action)(tiot_circ_buf *, const uint8_t *, uint32_t, uint32_t) =
+        (from == NULL) ? __circ_buf_write_zero : __circ_buf_write_data;
+
+    return action(cb, from, l, off) + action(cb, from + l, len - l, 0);
+}
+
+static inline uint32_t circ_buf_query_busy(const tiot_circ_buf *cb)
+{
+    return circ_buf_data_size(*cb->write, *cb->read, cb->size);
+}
+
+static inline uint32_t circ_buf_query_free(const tiot_circ_buf *cb)
+{
+    return circ_buf_free_size(*cb->write, *cb->read, cb->size);
+}
+
+/* read data from circle buffer */
+static inline uint32_t circ_buf_read(tiot_circ_buf *cb, uint8_t *to, uint32_t len)
+{
+    uint32_t read = *cb->read;
+
+    if ((len == 0) || (circ_buf_data_size(*cb->write, read, cb->size) < len) ||
+        (circ_buf_read_data(cb, to, len, read) != len)) {
+        return 0;
+    }
+
+    *cb->read = saturate_add(read, len, cb->size);
+    return len;
+}
+
+/* write data into circle buffer */
+static inline uint32_t circ_buf_write(tiot_circ_buf *cb, const uint8_t *from, uint32_t len)
+{
+    uint32_t write = *cb->write;
+
+    if ((len == 0) || (circ_buf_write_data(cb, from, len, write) != len)) {
+        return 0;
+    }
+
+    *cb->write = saturate_add(write, len, cb->size);
+    return len;
+}
+
+static inline uint32_t circ_buf_update_read_pos(tiot_circ_buf *cb, uint32_t len)
+{
+    *cb->read = saturate_add(*cb->read, len, cb->size);
+    return len;
+}
+
+static inline uint32_t circ_buf_update_write_pos(tiot_circ_buf *cb, uint32_t len)
+{
+    *cb->write = saturate_add(*cb->write, len, cb->size);
+    return len;
+}
+
+static inline uint32_t circ_buf_cast_read(const tiot_circ_buf *cb, uint32_t *data_offset, uint32_t len)
+{
+    uint32_t read = *cb->read;
+
+    if (circ_buf_data_size(*cb->write, read, cb->size) < len) {
+        *data_offset = 0;
+        return 0;
+    }
+
+    *data_offset = read;
+    return len;
+}
+
+static inline uint32_t circ_buf_cast_relese(tiot_circ_buf *cb, uint32_t len)
+{
+    uint32_t read = *cb->read;
+    uint32_t data_size = circ_buf_data_size(*cb->write, read, cb->size);
+    uint32_t len_temp;
+
+    len_temp = circ_buf_min(data_size, len);
+    *cb->read = saturate_add(read, len_temp, cb->size);
+
+    return len_temp;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4b0bdb4
--- /dev/null
@@ -0,0 +1,11 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+set(
+    tiot_circ_queue_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_circ_queue.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_circ_queue_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c b/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c
new file mode 100644 (file)
index 0000000..f56f4a6
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Tiot Circular queue header. \n
+ *
+ * History: \n
+ * 2023-04-18, Create file. \n
+ */
+#include "tiot_circ_queue.h"
+#ifdef __KERNEL__
+#include <linux/compiler.h>
+#endif
+#include "securec.h"
+
+#ifndef __KERNEL__
+#if (defined(__GNUC__))
+#define likely(_expr)      __builtin_expect(!!(_expr), 1)
+#define unlikely(_expr)    __builtin_expect(!!(_expr), 0)
+#else
+#define likely(_expr)   (_expr)
+#define unlikely(_expr) (_expr)
+#endif
+#endif
+
+static inline uint16_t tiot_circ_queue_mask(const tiot_circ_queue_t *queue)
+{
+    return (queue->size - 1);
+}
+
+static inline uintptr_t tiot_circ_queue_node(const tiot_circ_queue_t *queue, uint16_t idx)
+{
+    return (queue->mem_addr + ((idx & tiot_circ_queue_mask(queue)) * queue->node_bytes));
+}
+
+static inline uint16_t _tiot_circ_queue_space(tiot_circ_queue_t *queue)
+{
+    return ((queue->tail - (queue->head + 1)) & tiot_circ_queue_mask(queue));
+}
+
+void tiot_circ_queue_init(tiot_circ_queue_t *queue, uint16_t size, uint16_t node_bytes, uintptr_t mem_addr)
+{
+    if (unlikely((queue == NULL) || (size == 0) || (node_bytes == 0) || (mem_addr == 0))) {
+        return;
+    }
+
+    /* 队列大小应为2的幂次方 */
+    if ((size & (size - 1)) != 0) {
+        return;
+    }
+
+    osal_spin_lock_init(&queue->lock);
+
+    queue->head = 0;
+    queue->tail = 0;
+    queue->size = size;
+    queue->node_bytes = node_bytes;
+    queue->mem_addr = mem_addr;
+}
+
+/*
+ * 功能描述: 入队列一个节点
+ */
+int32_t tiot_circ_queue_enqueue(tiot_circ_queue_t *queue, uintptr_t src_node)
+{
+    uintptr_t dis_node;
+    unsigned long flags;
+
+    osal_spin_lock_irqsave(&queue->lock, &flags);
+
+    // 检查队列是否已满
+    if (_tiot_circ_queue_space(queue) == 0) {
+        osal_spin_unlock_irqrestore(&queue->lock, &flags);
+        return -1;
+    }
+
+    // 保存节点内容
+    dis_node = tiot_circ_queue_node(queue, queue->head);
+    if (memcpy_s((void *)dis_node, queue->node_bytes, (void *)src_node, queue->node_bytes) != EOK) {
+        osal_spin_unlock_irqrestore(&queue->lock, &flags);
+        return -1;
+    }
+
+    // 索引更新到下一位置
+    queue->head = (queue->head + 1) & tiot_circ_queue_mask(queue);
+
+    osal_spin_unlock_irqrestore(&queue->lock, &flags);
+    return 0;
+}
+
+/*
+ * 功能描述: 从循环队列中,取出最早入队列的节点
+ */
+uintptr_t tiot_circ_queue_dequeue(tiot_circ_queue_t *queue)
+{
+    uintptr_t node;
+    unsigned long flags;
+
+    osal_spin_lock_irqsave(&queue->lock, &flags);
+
+    // 检查是否为空
+    if (queue->head == queue->tail) {
+        osal_spin_unlock_irqrestore(&queue->lock, &flags);
+        return 0;
+    }
+
+    node = tiot_circ_queue_node(queue, queue->tail);
+
+    // 索引更新到下一位置
+    queue->tail = (queue->tail + 1) & tiot_circ_queue_mask(queue);
+
+    osal_spin_unlock_irqrestore(&queue->lock, &flags);
+    return node;
+}
+
+uint16_t tiot_circ_queue_space(tiot_circ_queue_t *queue)
+{
+    uint16_t space;
+    unsigned long flags;
+
+    osal_spin_lock_irqsave(&queue->lock, &flags);
+    space = _tiot_circ_queue_space(queue);
+    osal_spin_unlock_irqrestore(&queue->lock, &flags);
+    return space;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h
new file mode 100644 (file)
index 0000000..5d2d668
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Tiot Circular queue header. \n
+ *
+ * History: \n
+ * 2023-04-18, Create file. \n
+ */
+#ifndef TIOT_CIRC_QUEUE_H
+#define TIOT_CIRC_QUEUE_H
+
+#include "tiot_types.h"
+#include "tiot_osal.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_util_tiot_circ_queue Circular Queue
+ * @ingroup  tiot_common_util
+ * @{
+ */
+
+typedef struct {
+    uint16_t head; // 队列头索引,入队索引
+    uint16_t tail; // 队列尾索引,出队索引
+    uint16_t size; // 队列总大小,深度
+    uint16_t node_bytes; // 每个节点的长度
+    uintptr_t mem_addr; // 队列管理的内存空间(size * node_bytes)起始地址
+    osal_spinlock lock;
+} tiot_circ_queue_t;
+
+/**
+ * @brief  TIoT circ queue empty or not.
+ * @param  [in]  queue Circular queue.
+ * @return if empty return 1, else return 0.
+ */
+static inline int32_t tiot_circ_queue_empty(tiot_circ_queue_t *queue)
+{
+    int32_t ret;
+    unsigned long flags;
+    osal_spin_lock_irqsave(&queue->lock, &flags);
+    ret = (queue->head == queue->tail);
+    osal_spin_unlock_irqrestore(&queue->lock, &flags);
+    return ret;
+}
+
+/**
+ * @brief  TIoT circ queue clear.
+ * @param  queue Circular queue.
+ */
+static inline void tiot_circ_queue_clear(tiot_circ_queue_t *queue)
+{
+    unsigned long flags;
+    osal_spin_lock_irqsave(&queue->lock, &flags);
+    queue->head = 0;
+    queue->tail = 0;
+    osal_spin_unlock_irqrestore(&queue->lock, &flags);
+}
+
+/**
+ * @brief  TIoT circ queue init.
+ * @param  [in]  queue Circular queue.
+ * @param  [in]  size  Queue size, nodes number max is size - 1, must be power of 2.
+ * @param  [in]  node_bytes Fixed node size.
+ * @param  [in]  mem_addr   Queue memory start address, ensure has init outside, length should be size * node_bytes.
+ */
+void tiot_circ_queue_init(tiot_circ_queue_t *queue, uint16_t size, uint16_t node_bytes, uintptr_t mem_addr);
+
+/**
+ * @brief  TIoT circ queue enqueue.
+ * @param  [in]  queue Circular queue.
+ * @param  [in]  src_node Node to be enqueued, will be copyed in queue memory.
+ * @return if OK return 0, else return -1.
+ */
+int32_t tiot_circ_queue_enqueue(tiot_circ_queue_t *queue, uintptr_t src_node);
+
+/**
+ * @brief  TIoT circ queue dequeue.
+ * @param  [in]  queue Circular queue.
+ * @return Pointer to deequeued node.
+ */
+uintptr_t tiot_circ_queue_dequeue(tiot_circ_queue_t *queue);
+
+/**
+ * @brief  TIoT circ queue space.
+ * @param  [in]  queue Circular queue.
+ * @return Circ queue avalible space for nodes.
+ */
+uint16_t tiot_circ_queue_space(tiot_circ_queue_t *queue);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/CMakeLists.txt
new file mode 100644 (file)
index 0000000..40434cf
--- /dev/null
@@ -0,0 +1,11 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+set(
+    tiot_fileops_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_fileops.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_fileops_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.c b/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.c
new file mode 100644 (file)
index 0000000..c2179c1
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT file ops. \n
+ *
+ * History: \n
+ * 2023-04-13, Create file. \n
+ */
+
+#include "tiot_fileops.h"
+#include "tiot_board_log.h"
+#include "tiot_osal.h"
+#include "securec.h"
+#include "tiot_types.h"
+
+#ifdef CONFIG_FILE_BY_ARRAY
+tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode)
+{
+    unsigned int i;
+    const tiot_file *file_list;
+    /* 非只读文件 */
+    tiot_unused(mode);
+    if (flags != OSAL_O_RDONLY) {
+        tiot_print_dbg("[TIoT][file]rw file\n");
+        return NULL;
+    }
+    if (path == NULL) {
+        tiot_print_dbg("[TIoT][file]array file path is NULL\n");
+        return NULL;
+    }
+
+    file_list = path->file_list;  /* 文件数组生成保证不为NULL. */
+    for (i = 0; i < path->file_num; i++) {
+        if (strcmp(file_list->name, file_name) == 0) {
+            return (tiot_file *)file_list;
+        }
+        file_list++;
+    }
+    return NULL;
+}
+
+int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset)
+{
+    uint32_t remain_size;
+    uint32_t copy_size;
+    int ret;
+    if (buf == NULL) {
+        return -1;
+    }
+    /* 偏移值需在文件数据范围内. */
+    if ((offset < 0) || (offset > filp->len)) {
+        tiot_print_err("[TIoT][file]exceed file range!\n");
+        return -1;
+    }
+
+    remain_size = filp->len - offset;
+    copy_size = size > remain_size ? remain_size : size;
+    if (copy_size == 0) {
+        /* 处于文件末尾 */
+        return 0;
+    }
+    ret = memcpy_s(buf, copy_size, &filp->data[offset], copy_size);
+    if (ret != EOK) {
+        return -1;
+    }
+    return copy_size;
+}
+#else
+tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode)
+{
+    (void)path;
+    return (tiot_file *)osal_klib_fopen(file_name, flags, mode);
+}
+
+void tiot_file_close(tiot_file *filp)
+{
+    osal_klib_fclose((void *)filp);
+}
+
+int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset)
+{
+    if (buf == NULL) {
+        tiot_print_err("[TIoT][file]read buff is NULL!\n");
+        return -1;
+    }
+    if (osal_klib_fseek(offset, OSAL_SEEK_SET, (void *)filp) < 0) {
+        tiot_print_err("[TIoT][file]fseek error!\n");
+        return -1;
+    }
+    return osal_klib_fread(buf, size, (void *)filp);
+}
+#endif
+
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/fileops/tiot_fileops.h
new file mode 100644 (file)
index 0000000..131269c
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Tiot file types. \n
+ *
+ * History: \n
+ * 2023-04-12, Create file. \n
+ */
+#ifndef TIOT_FILEOPS_H
+#define TIOT_FILEOPS_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_utils_file_ops File Ops
+ * @ingroup  tiot_common_utils
+ * @{
+ */
+
+#ifdef CONFIG_FILE_BY_ARRAY
+#define TIOT_FILE_NAME_MAX  16
+
+/**
+ * @brief  TIoT file struct for file array, read only.
+ */
+typedef struct {
+    const char name[TIOT_FILE_NAME_MAX];
+    int len;
+    const char *data;
+} tiot_file;
+
+/**
+ * @brief  TIoT file search path, set for search file array, read only.
+ */
+typedef struct {
+    const tiot_file *file_list;   /* A list of file array, read only. */
+    const unsigned int file_num;  /* File array num, read only. */
+} tiot_file_path;
+#else
+typedef void *tiot_file;          /*!< Dummy type for filp when board has file system. */
+typedef char tiot_file_path;      /*!< Dummy type for path when board has file system. */
+#endif
+
+#ifdef CONFIG_FILE_BY_ARRAY
+#define tiot_file_close(filp)   /*!< No need to close for file array. */
+#else
+/**
+ * @brief  TIoT file open, redirect to osal_klib_fclose.
+ * @param  [in]  filp File handle.
+ */
+void tiot_file_close(tiot_file *filp);
+#endif
+
+/**
+ * @brief  TIoT file open, for file system see @ref osal_klib_fopen, path is ignored.
+ *                         for file array, search in file name in the tiot_file_path.
+ * @param  [in]  path File array path, ignore for file system.
+ * @param  [in]  file_name File name.
+ * @param  [in]  flags File flags, like: OSAL_O_RDONLY.
+ * @param  [in]  mode File rwx mode, like: 0644.
+ * @return if OK return file handle, else return NULL.
+ */
+tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode);
+
+/**
+ * @brief  TIoT file read, for file system read to buf->buff.
+ *                         for file array, only move the buff pointer to offset.
+ * @param  [in]  filp   TIoT file handle.
+ * @param  [in]  buf    TIoT file readbuf.
+ * @param  [in]  size   Required read size.
+ * @param  [in]  offset Read offset of file.
+ * @return The length that has been read, could less than required size, or -1 if fail.
+ */
+int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/list/tiot_list.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/list/tiot_list.h
new file mode 100644 (file)
index 0000000..717b5ba
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: TIoT list. \n
+ *
+ * History: \n
+ * 2023-08-03, Create file. \n
+ */
+#ifndef TIOT_LIST_H
+#define TIOT_LIST_H
+
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_util_tiot_list List
+ * @ingroup  tiot_common_util
+ * @{
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct tiot_list_head {
+    struct tiot_list_head *next, *prev;
+};
+
+#define tiot_list_head_init(name) \
+    {                             \
+        &(name), &(name)          \
+    }
+
+#define tiot_list_head_create(name) \
+    struct tiot_list_head name = tiot_list_head_init(name)
+
+static inline void tiot_init_list_head(struct tiot_list_head *list)
+{
+    if (list == NULL) {
+        return;
+    }
+    list->next = list;
+    list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void tiot___list_add(struct tiot_list_head *_new,
+    struct tiot_list_head *prev,
+    struct tiot_list_head *next)
+{
+    if (_new == NULL || prev == NULL || next == NULL) {
+        return;
+    }
+    next->prev = _new;
+    _new->next = next;
+    _new->prev = prev;
+    prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void tiot_list_add_tail(struct tiot_list_head *cur, struct tiot_list_head *head)
+{
+    tiot___list_add(cur, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void tiot___list_del(struct tiot_list_head *prev, struct tiot_list_head *next)
+{
+    if (prev == NULL || next == NULL) {
+        return;
+    }
+
+    next->prev = prev;
+    prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void tiot___list_del_entry(struct tiot_list_head *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+    tiot___list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void tiot_list_replace(struct tiot_list_head *old,
+    struct tiot_list_head *_new)
+{
+    _new->next = old->next;
+    _new->next->prev = _new;
+    _new->prev = old->prev;
+    _new->prev->next = _new;
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:    the &struct list_head pointer.
+ * @type:    the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define tiot_list_entry(ptr, type, member) \
+    tiot_container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry    -    iterate over list of given type
+ * @pos:    the type * to use as a loop cursor.
+ * @head:    the head for your list.
+ * @member:  the name of the list_struct within the struct.
+ * @pos_type:  type of the struct which the list_node in.
+ */
+#define tiot_list_for_each_entry(pos, head, member, pos_type)            \
+    for ((pos) = tiot_list_entry((head)->next, pos_type, member);        \
+         &(pos)->member != (head);                                         \
+         (pos) = tiot_list_entry((pos)->member.next, pos_type, member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:    the type * to use as a loop cursor.
+ * @n:        another type * to use as temporary storage
+ * @head:    the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ * @pos_type:  type of pos.
+ * @n_type:    type of n.
+ */
+#define tiot_list_for_each_entry_safe(pos, n, head, member, pos_type, n_type)         \
+    for ((pos) = tiot_list_entry((head)->next, pos_type, member),                     \
+        (n) = tiot_list_entry((pos)->member.next, pos_type, member);                  \
+         &(pos)->member != (head);                                                      \
+         (pos) = (n), (n) = tiot_list_entry((n)->member.next, n_type, member))
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d20f3a5
--- /dev/null
@@ -0,0 +1,11 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+#===============================================================================
+set(
+    tiot_misc_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_misc.c
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_misc_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.c b/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.c
new file mode 100644 (file)
index 0000000..2e2c61f
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. \n
+ *
+ * Description: TIoT miscellaneous file. \n
+ *
+ * History: \n
+ * 2024-06-20, Create file. \n
+ */
+
+#include "tiot_misc.h"
+
+#define TIOT_HEX_RADIX           16
+#define TIOT_CONVERT_BASIC_LEN   1
+#define TIOT_CONVERT_STR_MIN_LEN 4
+
+// For example, if 3200 is entered, 0xC80 is displayed.
+int32_t tiot_num_to_hex(uint32_t num, char* str_buff, uint32_t str_buff_len)
+{
+    int right = 0;
+    int str_num = 0;
+    uint32_t number = num;
+    int left = 2; // 跳过前两个字符"0x".
+    const char map[] = "0123456789ABCDEF";
+
+    if (str_buff == NULL || str_buff_len < TIOT_CONVERT_STR_MIN_LEN) {
+        return -1;
+    }
+
+    str_buff[str_num++] = '0';
+    str_buff[str_num++] = 'x';
+
+    // Conversion part.
+    do {
+        str_buff[str_num++] = map[number % TIOT_HEX_RADIX];
+        number /= TIOT_HEX_RADIX;
+
+        // 确保有空间存放结束符'\0'.
+        if ((uint32_t)(str_num + TIOT_CONVERT_BASIC_LEN) > str_buff_len) {
+            str_buff[0] = '\0';
+            return -1;
+        }
+    } while (number);
+
+    // Inverting Data
+    right = str_num - TIOT_CONVERT_BASIC_LEN;
+    while (right > left) {
+        char tmp = str_buff[left];
+        str_buff[left] = str_buff[right];
+        str_buff[right] = tmp;
+        left++;
+        right--;
+    }
+    str_buff[str_num++] = '\0';
+    return 0;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/misc/tiot_misc.h
new file mode 100644 (file)
index 0000000..4f7e441
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. \n
+ *
+ * Description: Tiot miscellaneous header file. \n
+ *
+ * History: \n
+ * 2024-06-20, Create file. \n
+ */
+#ifndef TIOT_MISC_H
+#define TIOT_MISC_H
+
+#include "tiot_types.h"
+#include "tiot_osal.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_common_utils_tiot_misc TIOT miscellaneous function
+ * @ingroup  tiot_common_utils
+ * @{
+ */
+
+/**
+ * @brief  TIoT converts a non-negative integer to a hexadecimal string.
+ * @param  [in]  num   Nonnegative integer.
+ * @param  [in]  str_buff   String after conversion num.
+ * @param  [in]  str_buff_len Length of str_buff.
+ * @return 0 is returned if Conversion succeeded. Otherwise, -1 is returned.
+ */
+int32_t tiot_num_to_hex(uint32_t num, char* str_buff, uint32_t str_buff_len);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/utils/tiot_types.h b/code/sdk/drivers/peripheral/gnss/driver/common/utils/tiot_types.h
new file mode 100644 (file)
index 0000000..4854c71
--- /dev/null
@@ -0,0 +1,66 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: TIoT types. \n\r
+ *\r
+ * History: \n\r
+ * 2023-06-01, Create file. \n\r
+ */\r
+#ifndef TIOT_TYPES_H\r
+#define TIOT_TYPES_H\r
+\r
+#ifdef __KERNEL__\r
+/* 内核类型可能与编译器stdint.h冲突. */\r
+#include <linux/kernel.h>\r
+#include <linux/version.h>\r
+#else\r
+#include <stdint.h>\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_common_interface_types TIoT types.\r
+ * @ingroup  tiot_common_interface\r
+ * @{\r
+ */\r
+#ifndef NULL\r
+#define NULL ((void*)0)\r
+#endif\r
+\r
+/* container */\r
+#undef tiot_offsetof\r
+#ifdef __compiler_offsetof\r
+#define tiot_offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)\r
+#else\r
+#define tiot_offsetof(TYPE, MEMBER) ((int)(unsigned long)&((TYPE *)0)->MEMBER)\r
+#endif\r
+\r
+#ifdef _MSC_VER\r
+#define tiot_container_of(ptr, type, member) ((type *)((char *)(const void *){ptr} - tiot_offsetof(type, member)))\r
+#else\r
+#define tiot_container_of(ptr, type, member) ({                 \\r
+    const __typeof__( ((type *)0)->member ) *__mptr = (ptr);    \\r
+    (type *)((char *)__mptr - tiot_offsetof(type, member)); })\r
+#endif\r
+\r
+#define tiot_unused(var) \\r
+    do {                 \\r
+        (void)(var);       \\r
+    } while (0)\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/CMakeLists.txt
new file mode 100644 (file)
index 0000000..adbe7fb
--- /dev/null
@@ -0,0 +1,31 @@
+#===============================================================================\r
+# @brief    cmake make file\r
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+#===============================================================================\r
+if(DEFINED CONFIG_DEV_GNSS)\r
+set(\r
+    device_include_list\r
+    "${CMAKE_CURRENT_SOURCE_DIR}"\r
+)\r
+\r
+set(\r
+    device_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/gnss_device_info.c\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/gnss_service.c\r
+)\r
+\r
+if(DEFINED CONFIG_FILE_BY_ARRAY)\r
+list(\r
+    APPEND device_src_list\r
+    ${CMAKE_CURRENT_SOURCE_DIR}/firmware/gnss_fw_file_array.c\r
+)\r
+\r
+list(\r
+    APPEND device_include_list\r
+    "${CMAKE_CURRENT_SOURCE_DIR}/firmware"\r
+)\r
+endif()\r
+\r
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${device_include_list}" CACHE INTERNAL "tiot header list" FORCE)\r
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${device_src_list}" CACHE INTERNAL "tiot src list" FORCE)\r
+endif()\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/Makefile b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/Makefile
new file mode 100644 (file)
index 0000000..fc03118
--- /dev/null
@@ -0,0 +1,16 @@
+# GNSS Makefile
+ifeq ($(CONFIG_DEV_GNSS), y)
+tiot-gnss-objs += gnss_device_info.o gnss_service.o
+
+ifeq ($(CONFIG_FILE_BY_ARRAY), y)
+ifneq (,$(wildcard $(TIOT_DRIVER_PATH)/device/gnss/firmware/gnss_fw_file_array.c))
+tiot-gnss-objs += firmware/gnss_fw_file_array.o
+TIOT_HEADER_LIST += -I$(TIOT_DRIVER_PATH)/device/gnss/firmware
+endif
+endif
+
+tiot-gnss-objs := $(addprefix device/gnss/,$(tiot-gnss-objs))
+tiot_driver-objs += $(tiot-gnss-objs)
+
+TIOT_HEADER_LIST += -I$(TIOT_DRIVER_PATH)/device/gnss
+endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg.bin b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg.bin
new file mode 100644 (file)
index 0000000..0840e76
--- /dev/null
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:10092e64998e841ab77ca1edc0eff585491da1b54084c6a7be46992d7b035d05
+size 86813
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg_h7s1.bin b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_cfg_h7s1.bin
new file mode 100644 (file)
index 0000000..112cc67
--- /dev/null
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6d7d87f5f81edbcb9647b7bdf27773fe9f43343a71345bebcd5a96d3534dd9b9
+size 55883
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c
new file mode 100644 (file)
index 0000000..bdf476a
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2024-2024. All rights reserved.
+ *
+ * Description:  gnss firmware file arrays.
+ * Author: @CompanyNameTag
+ * History:
+ * 2024-01-08, Create file.
+ */
+#include "gnss_fw_file_array.h"
+#include "tiot_types.h"
+
+/* 仅用于SDK,无文件系统使用文件数组时,替换此目录下文件. */
+
+#define GNSS_FW_ATTR 
+
+#if 1
+/** $Achilles,H7S1,Q35,F1P26.0,0*72 */
+#define GNSS_CFG_BIN  "gnss_cfg.bin"
+#else
+/** $Achilles,H7S1,Q35,F1P10.0,0*77 */
+#define GNSS_CFG_BIN  "gnss_cfg_h7s1.bin"
+#endif
+
+GNSS_FW_ATTR const char g_gnss_cfg_file[] = {
+#include GNSS_CFG_BIN
+};
+
+const tiot_file g_gnss_fw_files[] = {
+    { "cfg", sizeof(g_gnss_cfg_file), g_gnss_cfg_file },
+};
+
+const tiot_file_path g_gnss_fw_file_path = {
+    g_gnss_fw_files, sizeof(g_gnss_fw_files) / sizeof(tiot_file)
+};
+
+const tiot_file_path *gnss_fw_file_path_get(void)
+{
+    return &g_gnss_fw_file_path;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h
new file mode 100644 (file)
index 0000000..a13dc61
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2024-2024. All rights reserved.
+ *
+ * Description:  gnss firmware file arrays.
+ * Author: @CompanyNameTag
+ * History:
+ * 2024-01-08, Create file.
+ */
+
+#ifndef GNSS_FW_FILE_ARRAY_H
+#define GNSS_FW_FILE_ARRAY_H
+
+#include "tiot_fileops.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+const tiot_file_path *gnss_fw_file_path_get(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.c b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.c
new file mode 100644 (file)
index 0000000..38578d9
--- /dev/null
@@ -0,0 +1,157 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: GNSS device info. \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-25, Create file. \n\r
+ */\r
+\r
+#include "gnss_device_info.h"\r
+#include "tiot_pm_default.h"\r
+#include "tiot_board_uart_port.h"\r
+#include "tiot_board_log.h"\r
+#include "tiot_controller.h"\r
+#include "tiot_board_pin_port.h"\r
+#include "tiot_cfg_handle_priv.h"\r
+#include "tiot_sys_msg_handle.h"\r
+#ifdef CONFIG_FILE_BY_ARRAY\r
+#include "gnss_fw_file_array.h"\r
+#endif\r
+\r
+#define GNSS_POWERON_WAIT_MS      1      /* Wait time before power on. */\r
+#define GNSS_BOOT_TIME_MS         200    /* Power on ==> Boot time. */\r
+#define GNSS_INIT_TIME_MS         600    /* Boot ==> Init time. */\r
+#define GNSS_WAKEUP_PULSE_MS      1      /* GPIO wake up pulse. */\r
+#define GNSS_WAKEUP_WAIT_MS       50     /* Wake up wait ms. */\r
+#define GNSS_BAUD_CHANGE_WAIT_US  11000  /* Baudrate change wait μs. */\r
+\r
+#ifdef CONFIG_GNSS_TCXO_FREQ_38P4M\r
+#define GNSS_WAKEUP_PIN_INIT_LEVEL  TIOT_PIN_LEVEL_LOW\r
+#else\r
+#define GNSS_WAKEUP_PIN_INIT_LEVEL  TIOT_PIN_LEVEL_HIGH\r
+#endif\r
+\r
+#ifdef CONFIG_GNSS_UART_WITH_FLOWCTRL\r
+#define GNSS_UART_ATTR_FLOW_CTRL    TIOT_UART_ATTR_FLOW_CTRL_ENABLE\r
+#else\r
+#define GNSS_UART_ATTR_FLOW_CTRL    TIOT_UART_ATTR_FLOW_CTRL_DISABLE\r
+#endif\r
+\r
+#define GNSS_DEFAULT_UART_CONFIG                        \\r
+{                                                       \\r
+    115200,                                             \\r
+    { .data_bits = TIOT_UART_ATTR_DATABIT_8,            \\r
+      .parity    = TIOT_UART_ATTR_PARITY_NONE,          \\r
+      .stop_bits = TIOT_UART_ATTR_STOPBIT_1,            \\r
+      .flow_ctrl = GNSS_UART_ATTR_FLOW_CTRL             \\r
+    }                                                   \\r
+}\r
+\r
+static inline int32_t gnss_pin_set_level_if_exist(uint32_t pin, uint32_t pin_level)\r
+{\r
+    if (pin != TIOT_PIN_NONE) {\r
+        return tiot_board_pin_set_level(pin, pin_level);\r
+    }\r
+    return 0;\r
+}\r
+\r
+static tiot_pm_retcode gnss_pm_power_on(tiot_pm *pm)\r
+{\r
+    uint32_t wakeup_device_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE];\r
+    /* GNSS板级连接唤醒管脚时,上拉或下拉 */\r
+    if (gnss_pin_set_level_if_exist(wakeup_device_pin, GNSS_WAKEUP_PIN_INIT_LEVEL) != 0) {\r
+        tiot_print_err("[TIoT][pm]set wkup pin level %d fail.\n", GNSS_WAKEUP_PIN_INIT_LEVEL);\r
+        return TIOT_PM_EVTRET_FAIL;\r
+    }\r
+    if (tiot_pm_default_power_on(pm) == TIOT_PM_EVTRET_FAIL) {\r
+        return TIOT_PM_EVTRET_FAIL;\r
+    }\r
+    if (gnss_pin_set_level_if_exist(wakeup_device_pin, TIOT_PIN_LEVEL_LOW) != 0) {\r
+        tiot_print_err("[TIoT][pm]set wkup pin level low fail.\n");\r
+        return TIOT_PM_EVTRET_FAIL;\r
+    }\r
+    return TIOT_PM_EVTRET_NEXT_STATE;\r
+}\r
+\r
+static const tiot_pm_event_entry g_gnss_pm_event_map[TIOT_PM_EVENT_MAX] = {\r
+    { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_POWEROFF, tiot_pm_default_power_off },\r
+    /* 上电后等待init消息或业务消息才说明进入work状态 */\r
+    /* GNSS板级连接唤醒管脚时,上电特殊处理 */\r
+    { TIOT_PM_TAG_POWEROFF, TIOT_PM_STATE_INIT, gnss_pm_power_on },\r
+#ifdef CONFIG_GNSS_WAKEUP_TYPE_UART\r
+    /* 只有sleep态才需要唤醒 */\r
+    { TIOT_PM_TAG_CAN_WAKEUP, TIOT_PM_STATE_WAKING, tiot_pm_default_wakeup_device_by_uart },\r
+#else\r
+    /* 只有sleep态才需要唤醒 */\r
+    { TIOT_PM_TAG_CAN_WAKEUP, TIOT_PM_STATE_WAKING, tiot_pm_default_wakeup_device_by_gpio },\r
+#endif\r
+    /* 有device wakeup host管脚时,通过此管脚说明已唤醒,且需要下发disallow消息 */\r
+    { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_WORK, tiot_pm_default_wakeup_ack_handle },\r
+    /* 接收到request sleep消息,下发allow sleep消息 */\r
+    { TIOT_PM_TAG_CAN_ALLOW_SLEEP, TIOT_PM_STATE_SLEEPING, tiot_pm_default_request_sleep_handle },\r
+    /* 接收到dev wkup host gpio拉低,需要释放唤醒锁 */\r
+    { TIOT_PM_TAG_CAN_SLEEP, TIOT_PM_STATE_SLEEP, tiot_pm_default_sleep_ack_handle },\r
+    /* 非S3状态,下发allow sleep并释放唤醒锁 */\r
+    { TIOT_PM_TAG_CAN_ALLOW_SLEEP, TIOT_PM_STATE_SLEEP, tiot_pm_default_request_sleep_ack_handle },\r
+    /* 上报init消息或业务消息说明唤醒成功 */\r
+    { TIOT_PM_TAG_CAN_WORK, TIOT_PM_STATE_WORK, NULL },\r
+    { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_INVALID, tiot_pm_default_work_vote_up },\r
+    { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_INVALID, tiot_pm_default_work_vote_down }\r
+};\r
+\r
+static void gnss_firmware_before_load(tiot_fw *fw)\r
+{\r
+    /* 加载前设置为固件加载默认波特率 */\r
+    tiot_uart_config gnss_firmware_load_config = GNSS_DEFAULT_UART_CONFIG;\r
+    tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware);\r
+    tiot_xfer_manager *xfer = &ctrl->transfer;\r
+    if (tiot_xfer_set_config(xfer, &gnss_firmware_load_config) != 0) {\r
+        tiot_print_dbg("[TIoT:fw]config before load fail.\r\n");\r
+    }\r
+    /* 加载前先清掉rx_buff */\r
+#ifdef CONFIG_XFER_DEFAULT_RX_BUFF\r
+    if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) {\r
+        circ_buf_flush(&xfer->rx_buff);\r
+    }\r
+#endif\r
+}\r
+\r
+static void gnss_firmware_after_load(tiot_fw *fw)\r
+{\r
+    /* 加载过程中可能切换波特率,加载后设置为业务默认波特率 */\r
+    tiot_uart_config gnss_transfer_config = GNSS_DEFAULT_UART_CONFIG;\r
+    tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware);\r
+    tiot_xfer_manager *xfer = &ctrl->transfer;\r
+    if (tiot_xfer_set_config(xfer, &gnss_transfer_config) != 0) {\r
+        tiot_print_dbg("[TIoT:fw]config after load fail.\r\n");\r
+    }\r
+}\r
+\r
+static int gnss_rx_wait_func(const void *param)\r
+{\r
+    (void)param;\r
+    /* GNSS通过UART上报数据,不需要拉高管脚来通知读取 */\r
+    return 0;\r
+}\r
+\r
+static const tiot_device_info g_gnss_device_info = {\r
+    .pm_event_map = (tiot_pm_event_entry *)g_gnss_pm_event_map,\r
+    .pm_event_map_size = sizeof(g_gnss_pm_event_map) / sizeof(tiot_pm_event_entry),\r
+    .exec_cbs = { gnss_firmware_before_load, gnss_firmware_after_load, tiot_fw_ext_cmd_handle_priv, NULL },\r
+    .xfer_info = { TIOT_XMIT_TYPE_UART, gnss_rx_wait_func },\r
+    .pkt_sys_msg_handle = tiot_pkt_sys_msg_handle,\r
+    .timings = {\r
+        .power_on_wait_ms = GNSS_POWERON_WAIT_MS,\r
+        .boot_time_ms = GNSS_BOOT_TIME_MS,\r
+        .init_time_ms = GNSS_INIT_TIME_MS,\r
+        .wakeup_pulse_ms = GNSS_WAKEUP_PULSE_MS,\r
+        .wakeup_wait_ms = GNSS_WAKEUP_WAIT_MS,\r
+        .baud_change_wait_us = GNSS_BAUD_CHANGE_WAIT_US,\r
+    }\r
+};\r
+\r
+const tiot_device_info *gnss_device_get_info(void)\r
+{\r
+    return &g_gnss_device_info;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.h b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_device_info.h
new file mode 100644 (file)
index 0000000..5356fbd
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: GNSS device info header. \n
+ *
+ * History: \n
+ * 2023-06-13, Create file. \n
+ */
+#ifndef GNSS_DEVICE_INFO_H
+#define GNSS_DEVICE_INFO_H
+
+#include "tiot_device_info.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_device_gnss_device_info  GNSS Device Info
+ * @ingroup  tiot_device_gnss
+ * @{
+ */
+
+/**
+ * @brief  GNSS device get info, same for all GNSS devices.
+ * @return GNSS device info.
+ */
+const tiot_device_info *gnss_device_get_info(void);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.c b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.c
new file mode 100644 (file)
index 0000000..6a570e5
--- /dev/null
@@ -0,0 +1,434 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description:  \n\r
+ *\r
+ * History: \n\r
+ * 2023-03-31, Create file. \n\r
+ */\r
+#include "gnss_service.h"\r
+#include "gnss_device_info.h"\r
+#include "gnss_board_port.h"\r
+#include "tiot_board_log.h"\r
+#include "tiot_controller.h"\r
+#include "tiot_controller_helper.h"\r
+#include "tiot_packet.h"\r
+#include "tiot_sys_msg_types.h"\r
+#include "tiot_board_pin_port.h"\r
+#include "tiot_board_uart_port.h"\r
+#include "tiot_board_misc_port.h"\r
+#include "tiot_board.h"\r
+#include "tiot_service_interface.h"\r
+\r
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC\r
+/* 加载 & 数据收发复用buffer,不同时使用 */\r
+/* 数据收发需求 ~10K用于缓存数据. */\r
+/* 固件加载时 ~3K用于保存解析后命令, ~128字节用于加载回复接收. */\r
+#define GNSS_FW_LOAD_REUSE_BUFF_START 0U\r
+#define GNSS_FW_LOAD_RX_BUFF_START    GNSS_FW_LOAD_REUSE_BUFF_START\r
+#define GNSS_FW_LOAD_RX_BUFF_SIZE     128U\r
+\r
+#define GNSS_FW_LOAD_REUSE_BUFF_END   (GNSS_FW_LOAD_RX_BUFF_START + GNSS_FW_LOAD_RX_BUFF_SIZE)\r
+\r
+#define GNSS_COMMON_BUFF_MAX    ((CONFIG_GNSS_PACKET_BUFF_MAX > GNSS_FW_LOAD_REUSE_BUFF_END) ? \\r
+                                 CONFIG_GNSS_PACKET_BUFF_MAX : GNSS_FW_LOAD_REUSE_BUFF_END)\r
+#endif\r
+\r
+#define GNSS_PACKET_QUEUE_NODES    8\r
+\r
+typedef enum {\r
+    GNSS_RX_SUBSYS_0 = 0,\r
+    GNSS_RX_SUBSYS_MAX\r
+} gnss_rx_subsys_id;\r
+\r
+typedef enum {\r
+    GNSS_PLT_SWITCH_GUART_BPS = 0,\r
+    GNSS_PLT_SWITCH_DBGUART_BPS,\r
+    GNSS_PLT_SWITCH_UART_SELECT,\r
+    GNSS_PLT_SWITCH_HSO_OR_SDT,\r
+    GNSS_PLT_SWITCH_DBGUART_SKIP,\r
+    GNSS_PLT_CMD_MAXSIZE\r
+} gnss_plt_cmd;\r
+\r
+typedef struct {\r
+    uint32_t bps;\r
+    uint32_t cr_crg;\r
+} tiot_plt_guart_para;\r
+\r
+typedef struct {\r
+    uint8_t frame_start;\r
+    uint8_t func_type;\r
+    uint8_t prime_id;\r
+    uint8_t reserved;\r
+    uint16_t frame_len;\r
+    uint16_t sn;\r
+} tiot_plt_om_header;\r
+\r
+typedef struct {\r
+    uint16_t cmd;\r
+    uint16_t para_len;\r
+} tiot_plt_cmd_header;\r
+\r
+#pragma pack(push, 1)\r
+typedef struct {\r
+    tiot_plt_om_header om_header;\r
+    tiot_plt_cmd_header cmd_header;\r
+    tiot_plt_guart_para para;\r
+    uint8_t tail;\r
+} tiot_plt_guart_cmd;\r
+#pragma pack(pop)\r
+\r
+#define tiot_plat_guart_baud_cmd(bps, flow_ctrl)                                \\r
+{                                                                               \\r
+    .om_header = { 0x7e, 0x0c, 0x00, 0x00, 0x15, 0x00 },                        \\r
+    .cmd_header = { GNSS_PLT_SWITCH_GUART_BPS, sizeof(tiot_plt_guart_para) },   \\r
+    .para = { (bps),                                                            \\r
+              ((flow_ctrl) == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ? 0xC301 : 0x301 \\r
+    },                                                                          \\r
+    .tail = 0x7e                                                                \\r
+}\r
+\r
+static tiot_controller g_gnss_controllers[CONFIG_GNSS_DEV_NUM] = { 0 };\r
+static tiot_packet_context g_gnss_pkt_ctx[CONFIG_GNSS_DEV_NUM];\r
+static tiot_packet g_gnss_pkt_queue_nodes[CONFIG_GNSS_DEV_NUM][GNSS_PACKET_QUEUE_NODES];\r
+static tiot_packet_queue g_gnss_pkt_queues[CONFIG_GNSS_DEV_NUM][GNSS_RX_SUBSYS_MAX];\r
+\r
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC\r
+static uint8_t g_gnss_common_buff_mem[CONFIG_GNSS_DEV_NUM][GNSS_COMMON_BUFF_MAX];\r
+#endif\r
+\r
+static uint16_t gnss_packet_manager_match_func(uint32_t subsys_code)\r
+{\r
+    if ((subsys_code == GNSS_FIRST_MSG) || (subsys_code == GNSS_COMMON_MSG) ||\r
+        (subsys_code == GNSS_LAST_MSG) || (subsys_code == MSG_BUTT)) {\r
+        return GNSS_RX_SUBSYS_0;\r
+    }\r
+    return GNSS_RX_SUBSYS_MAX;\r
+}\r
+\r
+static void gnss_device_wakeup_host_cb(uint32_t pin)\r
+{\r
+    (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_DISABLE);\r
+    tiot_controller *cur_ctrl = tiot_find_controller_by_pin(g_gnss_controllers, CONFIG_GNSS_DEV_NUM,\r
+                                                            pin, GNSS_PIN_DEVICE_WAKEUP_HOST);\r
+    if (cur_ctrl != NULL) {\r
+        tiot_pm_set_event(&cur_ctrl->pm, TIOT_PM_EVENT_WAKEUP_ACK);\r
+    }\r
+    (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_ENABLE);\r
+}\r
+\r
+static int32_t gnss_change_uart_config(tiot_xfer_manager *xfer, tiot_uart_config *uart_cfg)\r
+{\r
+    tiot_plt_guart_cmd uart_cmd = tiot_plat_guart_baud_cmd(uart_cfg->baudrate, uart_cfg->attr.flow_ctrl);\r
+    tiot_xfer_tx_param param = { SUBSYS_OM };\r
+    int32_t ret = tiot_xfer_send(xfer, (const uint8_t *)&uart_cmd, sizeof(tiot_plt_guart_cmd), &param);\r
+    if (ret != sizeof(tiot_plt_guart_cmd)) {\r
+        tiot_print_err("[TIOT]set user baudrate cmd fail.\r\n");\r
+        return -1;\r
+    }\r
+    ret = tiot_xfer_set_config(xfer, uart_cfg);\r
+    if (ret != 0) {\r
+        tiot_print_err("[TIOT]set user baudrate fail.\r\n");\r
+        return -1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static inline int32_t gnss_send_host_need_wakeup(tiot_controller *ctrl)\r
+{\r
+    int32_t ret;\r
+    const uint8_t host_need_wakeup_cmd = SYS_PL_PM_SET_WAKEUP_HOST_VALID;\r
+    const tiot_xfer_tx_param param = { SUBSYS_SYS };\r
+    ret = tiot_xfer_send(&ctrl->transfer, &host_need_wakeup_cmd, sizeof(uint8_t), &param);\r
+    if (ret != sizeof(uint8_t)) {\r
+        tiot_print_err("[TIOT]set host need wakeup cmd fail.\r\n");\r
+        return -1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static int32_t gnss_send_change_buadrate(tiot_controller *ctrl, uint32_t new_buadrate)\r
+{\r
+    const tiot_device_timings *timings = &ctrl->dev_info->timings;\r
+    tiot_uart_config uart_config = { 0 };\r
+    (void)tiot_xfer_get_config(&ctrl->transfer, &uart_config);\r
+    /* 配置用户波特率 */\r
+    if (uart_config.baudrate == new_buadrate) {\r
+        return 0;\r
+    }\r
+    uart_config.baudrate = new_buadrate;\r
+    if (gnss_change_uart_config(&ctrl->transfer, &uart_config) != 0) {\r
+        tiot_print_err("[TIoT]send change buadrate fail\n");\r
+        return -1;\r
+    }\r
+    /* 切换波特率后等待波特率稳定,device或host? */\r
+    tiot_board_udelay(timings->baud_change_wait_us);\r
+    return 0;\r
+}\r
+\r
+static int32_t gnss_service_packet_init(tiot_controller *ctrl, uint8_t dev_id)\r
+{\r
+    int32_t ret;\r
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC\r
+    tiot_packet_buffer pkt_buff = { g_gnss_common_buff_mem[dev_id], CONFIG_GNSS_PACKET_BUFF_MAX, 0 };\r
+#endif\r
+    tiot_packet_context_param param = {\r
+        .flags = TIOT_PKT_FLAGS_SUPPORT_ASCII,\r
+        .rx_manager_info = { g_gnss_pkt_queues[dev_id], GNSS_RX_SUBSYS_MAX, gnss_packet_manager_match_func },\r
+        .buff = NULL\r
+    };\r
+#ifndef CONFIG_BOARD_DYNAMIC_ALLOC\r
+    param.buff = &pkt_buff;\r
+#endif\r
+    g_gnss_pkt_queues[dev_id][GNSS_RX_SUBSYS_0].queue_nodes = g_gnss_pkt_queue_nodes[dev_id];\r
+    g_gnss_pkt_queues[dev_id][GNSS_RX_SUBSYS_0].queue_size = GNSS_PACKET_QUEUE_NODES;\r
+    tiot_packet_context *pkt_ctx = &g_gnss_pkt_ctx[dev_id];\r
+    ret = tiot_packet_init(pkt_ctx, &ctrl->transfer, &param);\r
+    if (ret != 0) {\r
+        tiot_print_err("[TIOT]packet init fail.\r\n");\r
+    }\r
+    return ret;\r
+}\r
+\r
+static int32_t gnss_service_install_packet(tiot_controller *ctrl, uint8_t dev_id)\r
+{\r
+    tiot_xfer_packet_ops gnss_packet_ops = {\r
+        .read_out = tiot_packet_read_out,\r
+        .rx_data_store = tiot_packet_rx_data_store,\r
+        .tx_push = tiot_packet_tx_push,\r
+    };\r
+    const tiot_device_timings *timings = &ctrl->dev_info->timings;\r
+    /* 收发模块注册包格式 */\r
+    if (tiot_xfer_install_packet(&ctrl->transfer, (tiot_xfer_packet_ops *)&gnss_packet_ops,\r
+                                 (uintptr_t)&g_gnss_pkt_ctx[dev_id]) != 0) {\r
+        tiot_print_err("[TIOT]packet install fail.\r\n");\r
+        return -1;\r
+    }\r
+    /* 必须等待device UART初始化后才能接收消息, 待确认时间. */\r
+    osal_msleep(timings->init_time_ms);\r
+    tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK);\r
+    return 0;\r
+}\r
+\r
+static inline int32_t gnss_service_custom_msg_send(tiot_controller *ctrl, uint32_t dev_wkup_host_pin,\r
+                                                   uint32_t custom_buadrate)\r
+{\r
+    /* 通过管脚有无判断host是否需要唤醒 */\r
+    if (dev_wkup_host_pin != TIOT_PIN_NONE) {\r
+        if (gnss_send_host_need_wakeup(ctrl) != 0) {\r
+            return -1;\r
+        }\r
+    }\r
+    /* 切换波特率 */\r
+    if (gnss_send_change_buadrate(ctrl, custom_buadrate) != 0) {\r
+        return -1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static inline int32_t gnss_get_dev_id(tiot_controller *ctrl, uint8_t *dev_id)\r
+{\r
+    uint8_t i;\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        if (ctrl == &g_gnss_controllers[i]) {\r
+            *dev_id = i;\r
+            return 0;\r
+        }\r
+    }\r
+    tiot_print_err("[TIoT]invalid device\n");\r
+    return -1;\r
+}\r
+\r
+static inline void gnss_set_open_param(tiot_xfer_open_param *xfer_open_param, tiot_service_open_param *param)\r
+{\r
+    if (param == NULL) {\r
+        return;\r
+    }\r
+    xfer_open_param->rx_cbk_param.buff = param->buff;\r
+    xfer_open_param->rx_cbk_param.buff_len = param->buff_len;\r
+    xfer_open_param->rx_cbk_param.rx_callback = param->rx_callback;\r
+}\r
+\r
+static inline int32_t gnss_firmware_load(tiot_fw *firmware)\r
+{\r
+    int ret = -1;\r
+#ifdef CONFIG_FILE_BY_ARRAY\r
+    ret = tiot_firmware_load(firmware, gnss_fw_file_path_get(), TIOT_FW_FILE_ARRAY_CFG_NAME);\r
+#else\r
+    ret = tiot_firmware_load(firmware, NULL, gnss_board_get_info()->cfg_path);\r
+#endif\r
+    if (ret != 0) {\r
+        tiot_print_err("[TIoT]Gnss firmware load fail.\n");\r
+    }\r
+    return ret;\r
+}\r
+\r
+static int32_t gnss_service_open(tiot_controller *ctrl, void *param)\r
+{\r
+    int ret = -1;\r
+    uint8_t dev_id;\r
+    uint32_t dev_wkup_host_pin;\r
+    tiot_xfer_open_param xfer_open_param = { 0 };\r
+    if (gnss_get_dev_id(ctrl, &dev_id) != 0) {\r
+        return -1;\r
+    }\r
+    gnss_set_open_param(&xfer_open_param, param);\r
+    /* 传输启动 */\r
+    if (tiot_xfer_open(&ctrl->transfer, &xfer_open_param) != 0) {\r
+        /* 通信接口打开失败 */\r
+        tiot_print_err("[TIoT]Transfer port open fail\n");\r
+        goto xfer_open_fail;\r
+    }\r
+    /* 上电 */\r
+    if (tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWERON) != 0) {\r
+        /* 上电失败 */\r
+        tiot_print_err("[TIoT]Power on fail\n");\r
+        goto power_on_fail;\r
+    }\r
+    /* 加载固件 */\r
+    ret = gnss_firmware_load(&ctrl->firmware);\r
+    if (ret != 0) {\r
+        goto fw_load_fail;\r
+    }\r
+    /* 使能中断 */\r
+    dev_wkup_host_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];\r
+    tiot_pin_int_request(dev_wkup_host_pin, gnss_device_wakeup_host_cb);\r
+\r
+    ret = gnss_service_packet_init(ctrl, dev_id);\r
+    if (ret != 0) {\r
+        goto pkt_init_fail;\r
+    }\r
+    ret = gnss_service_install_packet(ctrl, dev_id);\r
+    if (ret != 0) {\r
+        goto pkt_install_fail;\r
+    }\r
+    ret = gnss_service_custom_msg_send(ctrl, dev_wkup_host_pin, CONFIG_GNSS_UART_BAUDRATE);\r
+    if (ret != 0) {\r
+        goto pkt_install_fail;\r
+    }\r
+    /* 打开OK */\r
+    tiot_print_suc("[TIoT]Controller open succ.\n");\r
+    return 0;\r
+\r
+pkt_install_fail:\r
+    tiot_packet_deinit(&g_gnss_pkt_ctx[dev_id]);\r
+pkt_init_fail:\r
+    tiot_pin_int_release(dev_wkup_host_pin);\r
+fw_load_fail:\r
+    (void)tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWEROFF);\r
+power_on_fail:\r
+    tiot_xfer_close(&ctrl->transfer);\r
+xfer_open_fail:\r
+    return ret;\r
+}\r
+\r
+static void gnss_service_close(tiot_controller *ctrl)\r
+{\r
+    uint8_t dev_id;\r
+    uint32_t dev_wkup_host_pin;\r
+    if (gnss_get_dev_id(ctrl, &dev_id) != 0) {\r
+        return;\r
+    }\r
+    dev_wkup_host_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST];\r
+    (void)tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWEROFF);\r
+    tiot_pin_int_release(dev_wkup_host_pin);\r
+    tiot_xfer_close(&ctrl->transfer);\r
+    tiot_xfer_uninstall_packet(&ctrl->transfer);\r
+    tiot_packet_deinit(&g_gnss_pkt_ctx[dev_id]);\r
+}\r
+\r
+static int32_t gnss_service_write(tiot_controller *ctrl, const uint8_t *data,\r
+                                  uint32_t len, const tiot_xfer_tx_param *param)\r
+{\r
+    tiot_unused(param);\r
+    uint8_t dev_id;\r
+    if (gnss_get_dev_id(ctrl, &dev_id) != 0) {\r
+        return -1;\r
+    }\r
+    const tiot_xfer_tx_param tx_param = { SUBSYS_GNSS };\r
+    tiot_pm *pm = &ctrl->pm;\r
+    (void)tiot_pm_set_event(pm, TIOT_PM_EVENT_WORK_VOTE_UP);\r
+    /* 尝试唤醒device */\r
+    int32_t ret = tiot_pm_set_event(pm, TIOT_PM_EVENT_WAKEUP);\r
+    if (ret != 0) {\r
+        tiot_print_err("[TIoT]wake up error\n");\r
+        goto vote_down;\r
+    }\r
+    /* 等待成功唤醒device */\r
+    ret = tiot_pm_wait_state(&ctrl->pm, TIOT_PM_STATE_WORK, ctrl->dev_info->timings.wakeup_wait_ms);\r
+    if (ret <= 0) {\r
+        tiot_print_warning("[TIoT]wakeup device fail, pm state is 0x%x.\n", pm->state);\r
+    }\r
+    ret = tiot_xfer_send(&ctrl->transfer, data, len, &tx_param);\r
+vote_down:\r
+    (void)tiot_pm_set_event(pm, TIOT_PM_EVENT_WORK_VOTE_DOWN);\r
+    return ret;\r
+}\r
+\r
+static int32_t gnss_service_read(tiot_controller *ctrl, uint8_t *buff, uint32_t buff_len,\r
+                                 const tiot_xfer_rx_param *param)\r
+{\r
+    uint8_t dev_id;\r
+    if (gnss_get_dev_id(ctrl, &dev_id) != 0) {\r
+        return -1;\r
+    }\r
+    return tiot_xfer_recv(&ctrl->transfer, buff, buff_len, param);\r
+}\r
+\r
+int32_t gnss_service_init(void)\r
+{\r
+    uint8_t i;\r
+    int32_t ret;\r
+    tiot_board_info per_board_info;\r
+    tiot_controller_info ctrl_info;\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        if (gnss_board_init(&i) != 0) {\r
+            tiot_print_err("[TIoT]board init fail\n");\r
+            return -1;\r
+        }\r
+    }\r
+    const gnss_board_info *board_info = gnss_board_get_info();\r
+    if (board_info == NULL) {\r
+        tiot_print_err("[TIoT]no board info.\n");\r
+        goto deinit;\r
+    }\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        per_board_info.hw_info.xmit_id = board_info->hw_infos[i].xmit_id;\r
+        per_board_info.hw_info.pm_info = board_info->hw_infos[i].pm_info;\r
+        ctrl_info.board_info = &per_board_info;\r
+        ctrl_info.dev_info = gnss_device_get_info();\r
+        ctrl_info.dev_cus = 0;\r
+        ret = tiot_controller_init(&g_gnss_controllers[i], &ctrl_info);\r
+        if (ret != 0) {\r
+            tiot_print_err("[TIoT]controller init fail\n");\r
+            goto deinit;\r
+        }\r
+    }\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        g_gnss_controllers[i].ops.open = gnss_service_open;\r
+        g_gnss_controllers[i].ops.close = gnss_service_close;\r
+        g_gnss_controllers[i].ops.write = gnss_service_write;\r
+        g_gnss_controllers[i].ops.read = gnss_service_read;\r
+        g_gnss_controllers[i].ops.pm_ctrl = NULL;\r
+    }\r
+    return 0;\r
+deinit:\r
+    gnss_service_deinit();\r
+    return -1;\r
+}\r
+\r
+void gnss_service_deinit(void)\r
+{\r
+    uint8_t i;\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        tiot_controller_deinit(&g_gnss_controllers[i]);\r
+    }\r
+    for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) {\r
+        gnss_board_deinit(&i);\r
+    }\r
+}\r
+\r
+uintptr_t gnss_service_get_ctrl(uint8_t dev_id)\r
+{\r
+    return (uintptr_t)&g_gnss_controllers[dev_id];\r
+}\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.h b/code/sdk/drivers/peripheral/gnss/driver/device/gnss/gnss_service.h
new file mode 100644 (file)
index 0000000..3d37a81
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: GNSS service interface. \n
+ *
+ * History: \n
+ * 2023-06-13, Create file. \n
+ */
+#ifndef GNSS_SERVICE_H
+#define GNSS_SERVICE_H
+
+#include "tiot_types.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+/**
+ * @defgroup tiot_device_gnss_service_if  GNSS Service Interface
+ * @ingroup  tiot_device_gnss
+ * @{
+ */
+
+/**
+ * @brief  GNSS service init.
+ * @return zero if OK, -1 if failed.
+ */
+int32_t gnss_service_init(void);
+
+/**
+ * @brief  GNSS service deinit.
+ */
+void gnss_service_deinit(void);
+
+/**
+ * @brief  GNSS service get ctrl.
+ * @param  dev_id Device id.
+ * @return Tiot controller instace.
+ */
+uintptr_t gnss_service_get_ctrl(uint8_t dev_id);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/product_porting/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7149394
--- /dev/null
@@ -0,0 +1,12 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+add_subdirectory(porting)  # 替换成对应porting目录
+
+set(
+    tiot_product_header_list
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_product_header_list}" CACHE INTERNAL "tiot header list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b5e1185
--- /dev/null
@@ -0,0 +1,19 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+#===============================================================================
+set(
+    tiot_product_src_list
+    ${CMAKE_CURRENT_SOURCE_DIR}/gnss_board_port.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_uart_port.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_pin_port.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_misc_port.c
+)
+
+set(
+    tiot_product_header_list
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_product_header_list}" CACHE INTERNAL "tiot header list" FORCE)
+set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_product_src_list}" CACHE INTERNAL "tiot src list" FORCE)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/gnss_board_port.c b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/gnss_board_port.c
new file mode 100644 (file)
index 0000000..fc14d54
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description:  \n
+ *
+ * History: \n
+ * 2023-06-13, Create file. \n
+ */
+
+#include "gnss_board_port.h"
+#include "tiot_board_pin_port.h"
+#include "gpio.h"
+#include "uart.h"
+#include "pinctrl.h"
+#include "soc_osal.h"
+
+/* 根据板级MCU与gnss两个芯片的硬件连接修改适配 */
+/* 1. MCU芯片连接到gnss芯片的UART bus编号, 
+如
+U8  UART_BUS_0
+L22,W9  UART_BUS_1
+*/
+/* 2. MCU芯片连接到gnss芯片PWREN管脚号, 。必须. 
+U8  GPS_1V8 S_AGPIO_L28   High  默认一直拉高
+    GPS_BAT_ON S_AGPIO_L23  High 默认一直拉高
+    PWREN S_AGPIO_L30   High  只需要控制PWREN
+*/
+/* 3. MCU芯片连接到gnss芯片GPIO9(host唤醒gnss)管脚号,
+      U8 当下悬空。
+      可选,如果板级未连接此管脚,必须设为TIOT_PIN_NONE宏.
+       */
+/* 4. MCU芯片连接到gnss芯片GPIO7(gnss唤醒host)管脚号,
+      U8 S_AGPIO_L31。
+      可选,如果板级未连接此管脚,必须设为TIOT_PIN_NONE宏.
+       */
+
+
+static const gnss_board_hw_info g_gnss_board_hw_info = { TIOT_UART_PORT, { TIOT_PIN_POWER,TIOT_PIN_WAKEUP_GNSS_NUM , TIOT_PIN_WAKEUP_HOST_NUM } };
+static const gnss_board_info g_gnss_board_info = {
+    .cfg_path = NULL,  /* 如果使用文件系统,此处填写固件cfg文件完整路径,
+                          例如 .cfg_path = "user/gnss_firmware/gnss_fw_cfg";
+                          否则, 填写NULL,并替换源码目录tiot_driver/device/gnss/firmware下的固件数组文件。 */
+    .hw_infos = (gnss_board_hw_info *)&g_gnss_board_hw_info
+};
+
+int32_t gnss_board_init(void *param)
+{
+    tiot_unused(param);
+    const uint32_t *gnss_pins = g_gnss_board_hw_info.pm_info;
+    /* power en */
+    uint32_t power_ctrl_pin = gnss_pins[GNSS_PIN_POWER_CTRL];
+    (void)uapi_pin_set_mode((pin_t)power_ctrl_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    (void)uapi_pin_set_pull((pin_t)power_ctrl_pin, PIN_PULL_DOWN);
+    (void)uapi_gpio_set_val((pin_t)power_ctrl_pin, GPIO_LEVEL_LOW);
+    (void)uapi_gpio_set_dir((pin_t)power_ctrl_pin, GPIO_DIRECTION_OUTPUT);
+    (void)uapi_pin_set_ds((pin_t)power_ctrl_pin, (pin_drive_strength_t)(PIN_DS_MAX - 1));
+
+    /* host wakeup dev */
+    uint32_t host_wakeup_device_pin = gnss_pins[GNSS_PIN_HOST_WAKEUP_DEVICE];
+    if (host_wakeup_device_pin != TIOT_PIN_NONE) {
+        (void)uapi_pin_set_mode((pin_t)host_wakeup_device_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+        (void)uapi_pin_set_ds((pin_t)host_wakeup_device_pin, (pin_drive_strength_t)(PIN_DS_MAX - 1));
+        (void)uapi_pin_set_pull((pin_t)host_wakeup_device_pin, PIN_PULL_DOWN);
+        (void)uapi_gpio_set_val((pin_t)host_wakeup_device_pin, GPIO_LEVEL_LOW);
+        (void)uapi_gpio_set_dir((pin_t)host_wakeup_device_pin, GPIO_DIRECTION_OUTPUT);
+    }
+
+    /* device wakeup host */
+    uint32_t device_wakeup_host_pin = gnss_pins[GNSS_PIN_DEVICE_WAKEUP_HOST];
+    if (device_wakeup_host_pin != TIOT_PIN_NONE) {
+        (void)uapi_pin_set_mode((pin_t)device_wakeup_host_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+        (void)uapi_pin_set_pull((pin_t)device_wakeup_host_pin, PIN_PULL_DOWN);
+        (void)uapi_gpio_set_val((pin_t)device_wakeup_host_pin, GPIO_LEVEL_LOW);
+        (void)uapi_gpio_set_dir((pin_t)device_wakeup_host_pin, GPIO_DIRECTION_INPUT);
+    }
+    /* UART1 pinmux已经在板级完成初始化, 或在UART open时进行初始化。 */
+    return 0;
+}
+
+void gnss_board_deinit(void *param)
+{
+    tiot_unused(param);
+    const uint32_t *gnss_pins = g_gnss_board_hw_info.pm_info;
+    /* 确保PWREN管脚下拉 */
+    (void)uapi_gpio_set_val((pin_t)gnss_pins[GNSS_PIN_POWER_CTRL], GPIO_LEVEL_LOW);
+}
+
+const gnss_board_info *gnss_board_get_info(void)
+{
+    return &g_gnss_board_info;
+}
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_log_port.h b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_log_port.h
new file mode 100644 (file)
index 0000000..8a87996
--- /dev/null
@@ -0,0 +1,46 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board log port. \n\r
+ *\r
+ * History: \n\r
+ * 2023-05-06, Create file. \n\r
+ */\r
+#ifndef BOARD_LOG_PORT_H\r
+#define BOARD_LOG_PORT_H\r
+\r
+#include <stdio.h>\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+/**\r
+ * @defgroup tiot_board_port_log LOG port\r
+ * @ingroup  tiot_board_port\r
+ * @{\r
+ */\r
+\r
+/* 通过printf直接打印,不需要日志时需要注释掉define后半部分. */\r
+#define BOARD_PRINT_FUNCTION_NAME           printf("%s\r\n", __func__)\r
+#define board_print_dbg(s, args...)         printf(s, ##args)\r
+#define board_print_info(s, args...)        printf(s, ##args)\r
+#define board_print_info(s, args...)        printf(s, ##args)\r
+#define board_print_suc(s, args...)         printf(s, ##args)\r
+#define board_print_warning(s, args...)     printf(s, ##args)\r
+#define board_print_err(s, args...)         printf(s, ##args)\r
+#define board_print_alter(s, args...)       printf(s, ##args)\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+#ifdef __cplusplus\r
+#if __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif /* __cplusplus */\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_misc_port.c b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_misc_port.c
new file mode 100644 (file)
index 0000000..a7a6e43
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
+ *
+ * Description: Board Misc port. \n
+ *
+ * History: \n
+ * 2023-12-04, Create file. \n
+ */
+#include "tiot_board_misc_port.h"
+#include "soc_osal.h"
+#include "pm_veto.h"
+
+#define TIOT_WAKEUP_LOCK_ID  PM_ID_SYS
+
+int32_t tiot_board_wake_lock_init(tiot_board_wakelock *lock)
+{
+    tiot_unused(lock);
+    return 0;
+}
+
+void tiot_board_wake_lock(tiot_board_wakelock *lock)
+{
+    tiot_unused(lock);
+#if ENABLE_LOW_POWER == YES
+    (void)uapi_pm_add_sleep_veto(TIOT_WAKEUP_LOCK_ID);
+#endif
+}
+
+void tiot_board_wake_unlock(tiot_board_wakelock *lock)
+{
+    tiot_unused(lock);
+#if ENABLE_LOW_POWER == YES
+    (void)uapi_pm_remove_sleep_veto(TIOT_WAKEUP_LOCK_ID);
+#endif
+}
+
+void tiot_board_wake_lock_destroy(tiot_board_wakelock *lock)
+{
+    tiot_unused(lock);
+}
+
+void tiot_board_udelay(uint32_t us)
+{
+    osal_udelay(us);
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_pin_port.c b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_pin_port.c
new file mode 100644 (file)
index 0000000..cb0f4d6
--- /dev/null
@@ -0,0 +1,112 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board PIN port. \n\r
+ *\r
+ * History: \n\r
+ * 2023-04-20, Create file. \n\r
+ */\r
+#include "tiot_board_pin_port.h"\r
+#include "gpio.h"\r
+\r
+#define uapi_err2ret(errcode)      (((errcode) == ERRCODE_SUCC) ? 0 : -1)\r
+\r
+/* TIoT驱动使用中断管脚个数,需要按实际板级情况适配修改。 */\r
+#define TIOT_INT_PIN_NUMBER    1\r
+typedef struct {\r
+    uint32_t pin;\r
+    tiot_pin_int_callback callback;\r
+} tiot_int_pin_map;\r
+/* TIoT驱动使用中断管脚配置,需要按实际使用的中断管脚适配修改。 */\r
+static tiot_int_pin_map g_tiot_int_pin_map[TIOT_INT_PIN_NUMBER] = {\r
+    /* 例如使用XXX唤醒MCU管脚,对应GPIO ID为S_AGPIO_R0. */\r
+    { TIOT_PIN_WAKEUP_HOST_NUM, NULL }\r
+};\r
+\r
+/**\r
+ * @brief  Board set pin level interface.\r
+ * @param  [in] pin   Pin id.\r
+ * @param  [in] level Pin level, see @ref tiot_pin_level.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_set_level(uint32_t pin, uint8_t level)\r
+{\r
+    errcode_t errcode;\r
+    gpio_level_t gpio_level = (level == TIOT_PIN_LEVEL_LOW) ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH;\r
+    errcode = uapi_gpio_set_val((pin_t)pin, gpio_level);\r
+    return uapi_err2ret(errcode);\r
+}\r
+\r
+/**\r
+ * @brief  Board get current pin level interface.\r
+ * @param  [in]  pin   Pin id.\r
+ * @param  [out] level Current pin level, see @ref tiot_pin_level.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_get_level(uint32_t pin, uint8_t *level)\r
+{\r
+    gpio_level_t gpio_level = uapi_gpio_get_val((pin_t)pin);\r
+    *level = (gpio_level == GPIO_LEVEL_LOW) ? TIOT_PIN_LEVEL_LOW : TIOT_PIN_LEVEL_HIGH;\r
+    return 0;\r
+}\r
+\r
+/**\r
+ * @brief  Board pin interrupt enable interface.\r
+ * @param  [in] pin         Pin id.\r
+ * @param  [in] int_enable  Interrupt enable or disable, see @ref tiot_pin_int_enable.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_enable_int(uint32_t pin, uint8_t int_enable)\r
+{\r
+    errcode_t errcode;\r
+    if (int_enable == TIOT_PIN_INT_ENABLE) {\r
+        errcode = uapi_gpio_enable_interrupt((pin_t)pin);\r
+    } else {\r
+        errcode = uapi_gpio_disable_interrupt((pin_t)pin);\r
+    }\r
+    return uapi_err2ret(errcode);\r
+}\r
+\r
+\r
+static void tiot_board_gpio_callback(pin_t pin, uintptr_t param)\r
+{\r
+    (void)param;\r
+    uapi_gpio_clear_interrupt(pin);\r
+    for (uint8_t index = 0; index < TIOT_INT_PIN_NUMBER; index++) {\r
+        if ((pin == g_tiot_int_pin_map[index].pin) && (g_tiot_int_pin_map[index].callback != NULL)) {\r
+            g_tiot_int_pin_map[index].callback(pin);\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+/**\r
+ * @brief  Board pin interrupt callback register interface.\r
+ * @note   Porting should ensure this callback is called when enters pin irq if interrupt enabled.\r
+ * @param  [in] pin     Pin id.\r
+ * @param  [in] int_cb  Registed interrupt callback, see @ref tiot_pin_int_callback.\r
+ * @return zero if OK;\r
+ *         non-zero if FAIL.\r
+ */\r
+int32_t tiot_board_pin_register_int_callback(uint32_t pin, tiot_pin_int_callback int_cb)\r
+{\r
+    errcode_t errcode;\r
+    if (int_cb != NULL) {\r
+        errcode = uapi_gpio_register_isr_func((pin_t)pin, GPIO_INTERRUPT_RISING_EDGE, tiot_board_gpio_callback);\r
+    } else {\r
+        errcode = uapi_gpio_unregister_isr_func((pin_t)pin);\r
+    }\r
+    if (errcode != ERRCODE_SUCC) {\r
+        return -1;\r
+    }\r
+    for (uint8_t index = 0; index < TIOT_INT_PIN_NUMBER; index++) {\r
+        if (pin == g_tiot_int_pin_map[index].pin) {\r
+            g_tiot_int_pin_map[index].callback = int_cb;\r
+            break;\r
+        }\r
+    }\r
+    return 0;\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_uart_port.c b/code/sdk/drivers/peripheral/gnss/driver/product_porting/porting/tiot_board_uart_port.c
new file mode 100644 (file)
index 0000000..1717c39
--- /dev/null
@@ -0,0 +1,196 @@
+/**\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.\r
+ *\r
+ * Description: Board UART port\n\r
+ *\r
+ * History: \n\r
+ * 2023-03-25, Create file. \n\r
+ */\r
+#include "tiot_board_uart_port.h"\r
+#include "tiot_board_pin_port.h"\r
+#include "tiot_board_log.h"\r
+\r
+#include "uart.h"\r
+#include "uart_porting.h"\r
+#include "pinctrl.h"\r
+#include "pinctrl_porting.h"\r
+\r
+#define TIOT_UAPI_RW_TIMEOUT    0xFFFFFFFF\r
+#define UART_RX_BUFFER_SIZE     56\r
+\r
+#define TIOT_UAPI_UART_RX_MAX   1024\r
+\r
+/* TIoT驱动使用MCU UART个数. */\r
+enum tiot_uart_port {\r
+    TIOT_UART_PORT0,\r
+    TIOT_UART_NUM,\r
+    TIOT_UART_NONE = TIOT_UART_NUM\r
+};\r
+\r
+enum tiot_uart_pin_type {\r
+    UART_PIN_TYPE_TX,\r
+    UART_PIN_TYPE_RX,\r
+    UART_PIN_TYPE_CTS,\r
+    UART_PIN_TYPE_RTS,\r
+    UART_PIN_TYPE_NUM\r
+};\r
+\r
+typedef struct {\r
+    tiot_xmit *xmit;\r
+    uint8_t flow_ctrl_bk;\r
+    uint8_t rx_buff[UART_RX_BUFFER_SIZE];\r
+    const uart_pin_config_t pin_config_orig;\r
+    uart_pin_config_t pin_config;\r
+    hal_pio_func_t pinmux[UART_PIN_TYPE_NUM];\r
+    uart_rx_callback_t rx_callback;\r
+} tiot_board_uart_port;\r
+\r
+static tiot_xmit_callbacks g_tiot_xmit_cbs;\r
+\r
+/* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加 */\r
+static void tiot_board_rx_callback0(const void *buff, uint16_t length, bool error);\r
+/* TIoT驱动使用的UART初始信息,需要按实际板级情况适配。 */\r
+static tiot_board_uart_port g_tiot_board_uart_port[TIOT_UART_NUM] = {\r
+    /* TIOT_UART_PORT0. */\r
+    {\r
+        .flow_ctrl_bk = TIOT_UART_ATTR_FLOW_CTRL_ENABLE,   /* MCU UART默认是否开启流控。 */\r
+        .rx_buff = { 0 },\r
+        .pin_config_orig = { TIOT_PIN_UART_TX, TIOT_PIN_UART_RX, TIOT_PIN_UART_CTS,TIOT_PIN_UART_RTS },   /* MCU UART管脚,按实际板级情况适配。 */\r
+        /* MCU UART管脚pinmux,按实际板级情况适配。 */\r
+        .pinmux = {\r
+            TIOT_PINMUX, TIOT_PINMUX,\r
+            TIOT_PINMUX, TIOT_PINMUX\r
+        },  \r
+        .rx_callback = tiot_board_rx_callback0             /* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加。 */\r
+    }\r
+    /* TIOT_UART_PORTx... */\r
+};\r
+\r
+/* MCU UART bus号与TIoT驱动使用的UART 对应关系,需要按实际情况适配。 */\r
+static inline enum tiot_uart_port tiot_board_uart_bus_convert_port(uart_bus_t bus)\r
+{\r
+    /* 例如 UART_BUS_0 对应 TIoT驱动使用的第一个UART。 */\r
+    if (bus == TIOT_UART_PORT)\r
+    {\r
+        return TIOT_UART_PORT0;\r
+    }\r
+    \r
+    return TIOT_UART_NONE;\r
+}\r
+\r
+static inline void tiot_board_rx_callback_common(tiot_board_uart_port *port, const void *buff, uint16_t length)\r
+{\r
+    g_tiot_xmit_cbs.rx_notify(port->xmit, (uint8_t *)buff, length);\r
+}\r
+\r
+/* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加 */\r
+static void tiot_board_rx_callback0(const void *buff, uint16_t length, bool error)\r
+{\r
+    if (error == false) {\r
+        tiot_board_rx_callback_common(&g_tiot_board_uart_port[TIOT_UART_PORT0], buff, length);\r
+    } else {\r
+        tiot_print_err("[TIoT]uart port0 receive error.\r\n");\r
+    }\r
+}\r
+\r
+static void tiot_board_uart_txrx_pinmux_init(tiot_board_uart_port *port)\r
+{\r
+    /* 防止板级未初始化. */\r
+    uapi_pin_set_mode(port->pin_config.tx_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_TX]);\r
+    uapi_pin_set_mode(port->pin_config.rx_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_RX]);\r
+}\r
+\r
+static void tiot_board_uart_switch_flowctrl(tiot_board_uart_port *port)\r
+{\r
+    /* 板级uart初始化不会初始化ctsrts pinmux... */\r
+    if (port->flow_ctrl_bk == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) {\r
+        port->pin_config.cts_pin = port->pin_config_orig.cts_pin;\r
+        port->pin_config.rts_pin = port->pin_config_orig.rts_pin;\r
+        uapi_pin_set_mode(port->pin_config.cts_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_CTS]);\r
+        uapi_pin_set_mode(port->pin_config.rts_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_RTS]);\r
+    } else {\r
+        port->pin_config.cts_pin = PIN_NONE;\r
+        port->pin_config.rts_pin = PIN_NONE;\r
+    }\r
+}\r
+\r
+static int32_t tiot_board_uart_reopen(uart_bus_t bus, tiot_board_uart_port *port, const uart_attr_t *attr)\r
+{\r
+    uart_buffer_config_t buff_cfg = { (uint8_t *)port->rx_buff, UART_RX_BUFFER_SIZE };\r
+    (void)uapi_uart_deinit(bus);\r
+    tiot_board_uart_txrx_pinmux_init(port);\r
+    tiot_board_uart_switch_flowctrl(port);\r
+    errcode_t ret = uapi_uart_init(bus, &(port->pin_config), attr, NULL, &buff_cfg);\r
+    if (ret != ERRCODE_SUCC) {\r
+        return -1;\r
+    }\r
+    uapi_uart_register_rx_callback(bus, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,\r
+                                   TIOT_UAPI_UART_RX_MAX, port->rx_callback);\r
+    return 0;\r
+}\r
+\r
+int32_t tiot_board_uart_open(tiot_xmit *xmit, tiot_xmit_callbacks *cbs)\r
+{\r
+    enum tiot_uart_port port_type = tiot_board_uart_bus_convert_port((uart_bus_t)xmit->id);\r
+    if (port_type == TIOT_UART_NONE) {\r
+        return -1;\r
+    }\r
+    tiot_board_uart_port *port = &g_tiot_board_uart_port[port_type];\r
+    const uart_attr_t init_attr = { 115200, UART_DATA_BIT_8, UART_STOP_BIT_1, UART_PARITY_NONE,\r
+                                    ((port->flow_ctrl_bk == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ?\r
+                                    UART_FLOW_CTRL_RTS_CTS : UART_FLOW_CTRL_NONE) };\r
+    port->pin_config.tx_pin = port->pin_config_orig.tx_pin;\r
+    port->pin_config.rx_pin = port->pin_config_orig.rx_pin;\r
+    if (tiot_board_uart_reopen((uart_bus_t)xmit->id, port, &init_attr) != 0) {\r
+        return -1;\r
+    }\r
+    g_tiot_xmit_cbs = *cbs;\r
+    port->xmit = xmit;\r
+    xmit->handle = port;\r
+    return 0;\r
+}\r
+\r
+void tiot_board_uart_close(tiot_xmit *xmit)\r
+{\r
+    uapi_uart_unregister_rx_callback(xmit->id);\r
+    (void)uapi_uart_deinit(xmit->id);\r
+}\r
+\r
+int32_t tiot_board_uart_write(tiot_xmit *xmit, const uint8_t *buff, uint32_t len)\r
+{\r
+    return uapi_uart_write(xmit->id, buff, len, TIOT_UAPI_RW_TIMEOUT);\r
+}\r
+\r
+int32_t tiot_board_uart_read(tiot_xmit *xmit, uint8_t *buff, uint32_t len)\r
+{\r
+    return uapi_uart_read(xmit->id, buff, len, TIOT_UAPI_RW_TIMEOUT);\r
+}\r
+\r
+int32_t tiot_board_uart_set_config(tiot_xmit *xmit, tiot_uart_config *config)\r
+{\r
+    errcode_t ret;\r
+    tiot_board_uart_port *port = xmit->handle;\r
+    if ((config == NULL) || (config->attr.data_bits >= TIOT_UART_ATTR_DATABIT_BUTT) ||\r
+        (config->attr.stop_bits >= TIOT_UART_ATTR_STOPBIT_BUTT) ||\r
+        (config->attr.parity >= TIOT_UART_ATTR_PARITY_BUTT)) {\r
+        return -1;\r
+    }\r
+    if (port == NULL) {\r
+        return -1;\r
+    }\r
+    /* 确保当前无数据正在FIFO内传输,才能修改配置. */\r
+    while (uapi_uart_has_pending_transmissions(xmit->id) == true) {;}\r
+\r
+    const uart_attr_t attr = { config->baudrate, UART_DATA_BIT_8, UART_STOP_BIT_1, UART_PARITY_NONE,\r
+                               ((config->attr.flow_ctrl == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ?\r
+                               UART_FLOW_CTRL_RTS_CTS : UART_FLOW_CTRL_NONE) };\r
+    /* 调整流控需要重新init. */\r
+    if (config->attr.flow_ctrl != port->flow_ctrl_bk) {\r
+        port->flow_ctrl_bk = config->attr.flow_ctrl;\r
+        if (tiot_board_uart_reopen((uart_bus_t)xmit->id, port, &attr) != 0) {\r
+            return -1;\r
+        }\r
+    }\r
+    ret = uapi_uart_set_attr(xmit->id, &attr);\r
+    return (ret == ERRCODE_SUCC) ? 0 : -1;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/readme.txt b/code/sdk/drivers/peripheral/gnss/driver/product_porting/readme.txt
new file mode 100644 (file)
index 0000000..53939af
--- /dev/null
@@ -0,0 +1,2 @@
+TCXO时钟26M + 硬件流控连接
+TCXO时钟26M + 硬件流控悬空 + 无文件系统及动态内存
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_autoconfig.h b/code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_autoconfig.h
new file mode 100644 (file)
index 0000000..fc27814
--- /dev/null
@@ -0,0 +1,27 @@
+/* Config 0/2 Common */
+#define CONFIG_DEV_GNSS 1
+#define CONFIG_GNSS_DEV_NUM 1
+#define CONFIG_GNSS_WAKEUP_TYPE_UART 1
+#define CONFIG_GNSS_TCXO_FREQ_26M 1
+#define CONFIG_GNSS_UART_BAUDRATE 115200
+#define CONFIG_FILE_BY_ARRAY 1
+#define CONFIG_FIRMWARE_CFG_HANDLE_PRIV 1
+#define CONFIG_FIRMWARE_FILE_READ_BUF_LEN 1029
+#define CONFIG_PM_WAKEUP_BY_UART 1
+#define CONFIG_PM_MANAGE_LOWPOWER 1
+#define CONFIG_XMIT_WITH_UART 1
+#define CONFIG_UART_RX_MODE_BUFFED 1
+#define CONFIG_XFER_PACKET_TIOT 1
+#define CONFIG_XFER_DEFAULT_RX_BUFF 1
+#define CONFIG_XFER_RX_BUFF_SIZE 512
+
+
+/**Config2   OSAL 已有, 安全应用已经实现, 动态申请内存*/
+#define CONFIG_OSAL_DEFINED 1
+#define CONFIG_LIBBOUNDSCHECK_IMPLEMENTED 1
+#define CONFIG_BOARD_DYNAMIC_ALLOC 1
+
+/* Config0 */
+#if (CONFIG_BOARD_DYNAMIC_ALLOC != 1)
+#define CONFIG_GNSS_PACKET_BUFF_MAX 10000
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_defconfig b/code/sdk/drivers/peripheral/gnss/driver/product_porting/tiot_defconfig
new file mode 100644 (file)
index 0000000..a84e7ea
--- /dev/null
@@ -0,0 +1,101 @@
+# Generated by HiCFBB Kconfig Tool.
+# Note: !!!This file can not be modify manually!!!
+
+#
+# Devices
+#
+
+#
+# Config the devices.
+#
+CONFIG_DEV_GNSS=y
+CONFIG_GNSS_DEV_NUM=1
+CONFIG_GNSS_WAKEUP_TYPE_UART=y
+# CONFIG_GNSS_WAKEUP_TYPE_GPIO is not set
+CONFIG_GNSS_TCXO_FREQ_26M=y
+# CONFIG_GNSS_TCXO_FREQ_38P4M is not set
+CONFIG_GNSS_UART_BAUDRATE=115200
+# CONFIG_GNSS_UART_WITH_FLOWCTRL is not set
+CONFIG_GNSS_PACKET_BUFF_MAX=10000
+# CONFIG_DEV_W33 is not set
+# CONFIG_DEV_CA01 is not set
+# end of Devices
+
+#
+# Common
+#
+
+#
+# Config common modules.
+#
+
+#
+# Misc
+#
+CONFIG_FILE_BY_ARRAY=y
+CONFIG_OSAL_DEFINED=y
+CONFIG_LIBBOUNDSCHECK_IMPLEMENTED=y
+CONFIG_BOARD_DYNAMIC_ALLOC=y
+# end of Misc
+
+#
+# Firmware Load
+#
+
+#
+# Firmware load module.
+#
+CONFIG_FIRMWARE_CFG_HANDLE_PRIV=y
+# CONFIG_FIRMWARE_CFG_HANDLE_XCI is not set
+CONFIG_FIRMWARE_FILE_READ_BUF_LEN=1029
+# end of Firmware Load
+
+#
+# Power Management
+#
+
+#
+# Power management module.
+#
+CONFIG_PM_WAKEUP_BY_UART=y
+CONFIG_PM_MANAGE_LOWPOWER=y
+# end of Power Management
+
+#
+# Transfer
+#
+
+#
+# Transfer module.
+#
+
+#
+# Transmit Type Support
+#
+
+#
+# Transmit type support.
+#
+CONFIG_XMIT_WITH_UART=y
+# CONFIG_XMIT_WITH_SPI is not set
+# CONFIG_XMIT_WITH_I2C is not set
+CONFIG_UART_RX_MODE_BUFFED=y
+# CONFIG_UART_RX_MODE_BLOCK is not set
+# end of Transmit Type Support
+
+#
+# Packet Handle Support
+#
+
+#
+# Pakcet handle support.
+#
+CONFIG_XFER_PACKET_TIOT=y
+# CONFIG_XFER_PACKET_NCI is not set
+# end of Packet Handle Support
+
+CONFIG_XFER_DEFAULT_RX_BUFF=y
+CONFIG_XFER_RX_BUFF_SIZE=512
+# CONFIG_XFER_TX_SUPPORT_TASK is not set
+# end of Transfer
+# end of Common
diff --git a/code/sdk/drivers/peripheral/gnss/inc/NMEA0183.h b/code/sdk/drivers/peripheral/gnss/inc/NMEA0183.h
new file mode 100644 (file)
index 0000000..ba7690c
--- /dev/null
@@ -0,0 +1,269 @@
+/*\r
+*                              GPS NMEA0183协议简要解析框架 \r
+*      \r
+*      支持解析 RMC、GGA、VTG、HDT等消息字段信息,由于解析框架比较明了,\r
+*   移植源码者可自行考虑添加新的解析代码。\r
+*   解析方式采用逐个字段解析的方式,能很大程度上节省消耗内存空间。 \r
+*   重新编写数据转换函数,不依赖外部库,移植时一般只需包含NMEA0183.h\r
+*   文件即可。 \r
+*\r
+*   代码示例:\r
+*      \r
+               char nmea[] = \\r
+               "$GNRMC,102219.00,A,2239.11578,N,11406.59325,E,0.009,,291018,,,D*62\r\n"\\r
+               "$GNVTG,,T,,M,0.009,N,0.017,K,D*37\r\n"\\r
+               "$GNGGA,102220.00,2239.11583,N,11406.59338,E,2,09,1.30,112.7,M,-2.3,M,,0000*52\r\n";\r
+               \r
+$GPGGA,,,,,,0,,,,,,,,*66\r
+\r
+$GPGLL,,,,,,V,N*64\r
+\r
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
+\r
+$GPRMC,,V,,,,,,,,,E,N,V*6C\r
+\r
+$GPVTG,,T,,M,,N,,K,N*2C\r
+\r
+$GPZDA,,,,,00,00*48\r
+\r
+$PNTH000,13,,-87,0,,,,,1,1*22\r
+\r
+$PNTH001,0.000000,0.00,0.00,300000.00,1,0,0*1D\r
+\r
+$PNTH002,,T,0.000000,0,200,0.000000,3,0.000000*4B\r
+\r
+\r
+               gps_nmea_t gps_nmea_temp;   /// 定义解析时用到的暂存状态数据,只供解析时使用 \r
+               gps_data_t gps_data1;       /// GPS解析得到的最终数据,用户可使用 \r
+               unsigned int index = 0;\r
+               \r
+               for(index=0; index<sizeof(nmea); ++index)\r
+               {\r
+                       if(nmea_decode(&gps_nmea_temp, &gps_data1, nmea[index])) ///调用解析函数\r
+                       {\r
+                               /// 解析消息段成功 \r
+                               ... \r
+                       } \r
+               } \r
+               \r
+*   NMEA0183解析代码思想来源于开源飞控代码(Ardupilot),所以该份代码开源,可免费使用。\r
+*   ( 如有Bug,望能反馈 ! QQ: 2281280195 ) \r
+*       \r
+*   作者: ouyanglei        时间:2018-11-16\r
+*/\r
+\r
+\r
+#ifndef NMEA0183_H\r
+#define NMEA0183_H\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+/*************** 宏定义  *******************/ \r
+#define current_time_ms() 1\r
+\r
+#define GPS_LEAPSECONDS_MILLIS 18000UL\r
+#define AP_SEC_PER_WEEK   (7UL * 86400UL)\r
+\r
+/* 检查字符串是否为数字0-9 */ \r
+#define IS_DIGITAL(x) ( ((x)>='0'&&(x)<='9')||(x)=='-'||(x)=='.' )\r
+#define CHAR_TO_DIGITAL(x) ((x)-'0')\r
+#define DIGITAL_TO_CHAR(x) ( (x)+'0' )\r
+\r
+/**************** 枚举量定义 ***************/\r
+    typedef enum _sentence_types \r
+       {   /* 每个枚举量表示该字段的起始位置,有些特殊字段需要10个字段域 */ \r
+        GPS_SENTENCE_RMC = 32,     /* RMC字段 推荐的最少专用导航数据。*/\r
+        GPS_SENTENCE_GGA = (32*2),             /* GGA字段 接收机定位数据。*/\r
+        GPS_SENTENCE_GSV = (32*3),             /* GSV字段 可见卫星数据。*/\r
+        GPS_SENTENCE_GSA = (32*4),             /* GSA字段 有效卫星与精度因子数据。*/\r
+        GPS_SENTENCE_GLL = (32*5),             /* GLL字段 接收机地理位置数据。*/\r
+        GPS_SENTENCE_VTG = (32*6),             /* VTG字段 对地速度与航向数据。*/\r
+        // GPS_SENTENCE_HDT = (32*7),    /* HDT字段 */\r
+        GPS_SENTENCE_ZDA = (32*7),             /* ZDA字段 时间与日期数据。*/\r
+               GPS_SENTENCE_TH000 = (32*8),    /* 接收机前端增益信息。*/\r
+               GPS_SENTENCE_TH001 = (32*9),    /* 接收机定位质量信息。*/\r
+               GPS_SENTENCE_TH002 = (32*10),   /* 接收机功耗模式信息。*/\r
+        GPS_SENTENCE_OTHER = 0     /* 默认没有字段 */\r
+    }sentence_types;\r
+\r
+/**************** 结构体定义 ***************/    \r
+    /* GPS定位状态枚举量 */ \r
+    typedef enum _gps_status\r
+       {\r
+        NO_GPS = 0,              /* 无GPS */\r
+        NO_FIX,                  /* 接收到GPS信息,但没有定位 */\r
+        GPS_OK_FIX_2D,           /* 2D定位 */\r
+        GPS_OK_FIX_3D,           /* 3D定位 */ \r
+        GPS_OK_FIX_3D_DGPS,      /* 优于3D定位 */ \r
+        GPS_OK_FIX_3D_RTK_FLOAT, /* RTK浮点解状态 */ \r
+        GPS_OK_FIX_3D_RTK_FIXED, /* RTK固定解状态 */\r
+    }gps_status;\r
+    \r
+\r
+/**\r
+ * \r
+BDS, //        GB\r
+GPS, //        GP\r
+Galileo,//     GA\r
+GLONASS,//     GL\r
+QZSS,//        GQ\r
+\r
+signal                         systemID                signalID\r
+GPS L1C/A              1                               1 \r
+GLONASS L1OF   2                               1 \r
+Galileo E1C    3                               7 \r
+BDS B1i                        4                               1 \r
+QZSS L1C/A             5                               1\r
+\r
+卫星编号\r
+\r
+GNSS                   "NMEA svid range" "GNSS PRN range" "PRN to svid"\r
+GPS L1C/A              1~32                          1~32                  PRN+0\r
+GLONASS L1OF   65~88                                 1~24                  PRN+64\r
+Galileo E1C    1~36                          1~36                  PRN+0\r
+BDS B1i                1~50                          1~50                  PRN+0\r
+QZSS L1C/A             1~4                           193~196               PRN-192\r
+\r
+*/\r
+       typedef enum _location_system\r
+       {\r
+               GNSS_,                  //GN\r
+               GPS_L1C_A=1,    //GP\r
+               GLONASS_L1OF,   //GL\r
+               Galileo_E1C,    //GA\r
+               BDS_Bli,                //GB\r
+               QZSS_L1C_A,     //GQ\r
+               MAX_LOCATION_SYSTEM\r
+       } location_system_t;\r
+\r
+       typedef struct _start\r
+       {\r
+               unsigned char starID;\r
+               unsigned char snr;\r
+       }start_stat_t;\r
+\r
+    /* GPS点位置 */ \r
+    typedef struct _location \r
+       {\r
+           int alt:24;         /* 海拔高度 meters * 100  单位为厘米 */\r
+           float lat;            /* 纬度 *  暂时不乘以10**7,原始保存*/\r
+           float lng;            /* 精度 *  暂时不乘以10**7,原始保存*/\r
+       }Location;\r
+    \r
+    /* 数据解析状态结构体定义 */\r
+    typedef struct _gps_nmea\r
+    {\r
+       /* 数据解析状态 */ \r
+       unsigned char parity;                      /* 校验计算和 */ \r
+       unsigned char is_checksum_term;    /* 当前字段域为校验字 */\r
+       char term[15];                             /* 当前字段域缓冲区,','为字段域分割符 */\r
+               unsigned char location_system;          /* 字段类别,location_system_t gps_type, 北斗,GPS,GNSS,GLONASS 等*/\r
+       unsigned char term_number;         /* 当前字段域序号 */\r
+       unsigned char term_offset;         /* 字段域数据偏移量 */\r
+       unsigned char gps_data_good;       /* GPS数据有效状态 */\r
+       unsigned int  sentence_type;       /* 字段类别,见枚举 sentence_types*/\r
+       /* 数据信号分析 */\r
+               unsigned char th001_errorcode; /**PNTH001 语句,定位错误码(第 6 字段)1:表示卫星跟踪数量不足,不满足定位条件;2:表示有效星历数量不足,不满足定位条件;3:定位精度不足,定位结果被拦截。*/\r
+               unsigned char th001_trace_star_count; /*实际跟踪卫星数量(第 7 字段)显示了当前实际跟踪的卫星数量。*/\r
+               unsigned char th001_valid_star_count; /*有效星历数量(第 8 字段)显示了当前有效的星历数量。*/\r
+               float th001_quality; /**PNTH001 语句,定位质量评估因子(第 5 字段)显示了当前评估出的定位精度,定位过程中,有效范围为 3~200,值越小定位精度越好。*/\r
+               unsigned char th000_signal_vga; /*PNTH000 语句,VGA 档位(第 2 字段)描述了当前的信号增益档位,有效范围为2~13,正常信号时,其档位值为 7~9;如果档位值显示为 2,说明可能存在强干扰,导致增益饱和;如果档位值为 13,说明信号特别弱,可能射频链路增益不足。。*/\r
+       /* 数据解析结果 */\r
+       unsigned int new_time;                  /* UTC时间 */\r
+       unsigned int new_date;                  /* UTC日期 */\r
+       float new_latitude;                             /* 纬度 */\r
+       float new_longitude;                            /* 经度 */\r
+       int new_altitude;                               /* 海拔高度 cm*/\r
+       float new_speed;                                /* 地速 km/h */\r
+       float new_course;                               /* RMC、VTG字段磁偏角信息*/\r
+       float new_gps_yaw;                              /* HDT航向信息 */\r
+       unsigned short new_hdop;                /* 水平精度 *100 */\r
+       unsigned char new_satellite_count;      /* 当前使用卫星的颗数 */\r
+       unsigned char new_quality_indicator;    /* 定位状态 */\r
+       unsigned int last_RMC_ms;                   /* 最后更新字段时间 */\r
+       unsigned int last_GGA_ms;\r
+       unsigned int last_VTG_ms;\r
+               unsigned int last_HDT_ms;\r
+               unsigned int last_GSV_ms;\r
+               unsigned int last_GSA_ms;\r
+               unsigned int last_GLL_ms;\r
+               unsigned int last_ZDA_ms;\r
+               start_stat_t starts[4];\r
+               unsigned char starcount;\r
+               unsigned char gsvpage_starcount; //单条卫星数\r
+               unsigned int gsvpagecount;\r
+               unsigned int gsvpage;\r
+       }gps_nmea_t;\r
+       \r
+       /* 时间结构体 */ \r
+       typedef struct _time\r
+       {\r
+               unsigned char year;\r
+               unsigned short int month : 4;\r
+               unsigned short int  : 4;\r
+               unsigned short int day : 5;\r
+               unsigned short int week : 3;\r
+               unsigned char hour;\r
+               unsigned char minute;\r
+               unsigned char second;\r
+       }DateTime;\r
+       \r
+       /* GPS数据区域,供上层应用调用 */ \r
+       typedef struct _gps_data {\r
+        unsigned char instance;                   /* GPS实例个数 */ \r
+        gps_status status;                 /* GPS定位状态 */\r
+        Location location;                 /* GPS定位到的当前位置 */\r
+        DateTime date_time; \r
+               start_stat_t startsB[5];\r
+               start_stat_t startsL[5];\r
+               start_stat_t startsP[5];\r
+               start_stat_t startsQ[5];\r
+               start_stat_t startsA[5];\r
+               start_stat_t startsN[5];\r
+               unsigned char starcountB;\r
+               unsigned char starcountL;\r
+               unsigned char starcountP;\r
+               unsigned char starcountQ;\r
+               unsigned char starcountA;\r
+               unsigned char starcountN;\r
+        float ground_speed;                /* 地速  m/s */\r
+        float ground_course;               /* 地速航向  度  顺时针 0-360 */ \r
+        float gps_yaw;                     /* GPHDT字段航向信息 一般用于双天线测向 */\r
+        unsigned short hdop;               /* 水平精度  cm */\r
+        unsigned short vdop;               /* 垂直精度  cm */\r
+        unsigned char num_sats;            /* 可见卫星颗数 */\r
+        unsigned char have_gps_yaw;        /* GPHDT航向字段有效 */\r
+        unsigned int last_gps_time_ms;     /* 最后获取GPS信息时的时间  ms */\r
+       /* 数据信号分析 */\r
+               unsigned char th001_errorcode; /**PNTH001 语句,定位错误码(第 6 字段)1:表示卫星跟踪数量不足,不满足定位条件;2:表示有效星历数量不足,不满足定位条件;3:定位精度不足,定位结果被拦截。*/\r
+               unsigned char th001_trace_star_count; /*实际跟踪卫星数量(第 7 字段)显示了当前实际跟踪的卫星数量。*/\r
+               unsigned char th001_valid_star_count; /*有效星历数量(第 8 字段)显示了当前有效的星历数量。*/\r
+               float th001_quality; /**PNTH001 语句,定位质量评估因子(第 5 字段)显示了当前评估出的定位精度,定位过程中,有效范围为 3~200,值越小定位精度越好。*/\r
+               unsigned char th000_signal_vga; /*PNTH000 语句,VGA 档位(第 2 字段)描述了当前的信号增益档位,有效范围为2~13,正常信号时,其档位值为 7~9;如果档位值显示为 2,说明可能存在强干扰,导致增益饱和;如果档位值为 13,说明信号特别弱,可能射频链路增益不足。。*/\r
+    }gps_data_t;\r
+    \r
+    /* NMEA0183结构体对象 */\r
+    typedef struct _nmea0183\r
+       {\r
+               gps_nmea_t gpsParse;\r
+               gps_data_t gpsData;\r
+               unsigned char (*nmea_decode)(struct _nmea0183* pnmea, char c);          \r
+       }NMEA0183; \r
+    \r
+/**************** 函数定义 ***************/\r
+\r
+unsigned char nmea_decode(NMEA0183* pnmea, char c);\r
+char* get_gps_status_str(gps_status status);\r
+char* get_gps_sentence_type_str(sentence_types sentencetype);\r
+void dump_location_data(gps_data_t *locationdata);\r
+void dump_location_data_to_buf(gps_data_t *locationdata,char* buf,int max_buflen);\r
+gps_data_t * getGPSGlobaldata(void);\r
+\r
+void dump_location_data_to_factory(gps_data_t *locationdata,char* buf,int max_buflen);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/gnss/inc/gnss_ctl.h b/code/sdk/drivers/peripheral/gnss/inc/gnss_ctl.h
new file mode 100644 (file)
index 0000000..de6cb52
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
+//
+// 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.
+
+#ifndef __CUSTOM_GNSS_CTL_H
+#define __CUSTOM_GNSS_CTL_H
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#include "stdint.h"
+#include "errcode.h"
+
+errcode_t gnss_power_on(void);
+errcode_t gnss_power_off(void);
+errcode_t gnss_start(void);
+errcode_t gnss_stop(void);
+uint8_t is_gnss_on(void);
+
+typedef enum {
+    SWITCH_TO_DOWNLOAD=0,
+    SWITCH_TO_GNSS=1,
+} DOWNLOAD_GPS_SWITCH_T;
+
+errcode_t download_gnss_switch(DOWNLOAD_GPS_SWITCH_T download_gps_switch);
+
+
+int is_GnssLogEnabled(void);
+int GnssLogEnable(bool enable);
+
+/**test only */
+uint32_t gnss_write_cmd(uint8_t * cmdbuf,uint16_t cmdlen);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/inc/uart_gnss.h b/code/sdk/drivers/peripheral/gnss/inc/uart_gnss.h
new file mode 100644 (file)
index 0000000..29c26f7
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
+//
+// 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.
+
+#ifndef __CUSTOM_GNSS_UART_H
+#define __CUSTOM_GNSS_UART_H
+
+#include "stdint.h"
+/**
+ * @brief init uart config and config uart as slip netif bridge
+ */
+int gnss_uart_init(void);
+
+#define GNSS_CMD_READDATA 0x01
+#define GNSS_CMD_WRITEDATA 0x02
+typedef enum
+{
+    GNSS_CMD_CFG_INIT=1,
+    GNSS_CMD_NMEA_CFG,
+    GNSS_CMD_START,
+    GNSS_CMD_STOP,
+    GNSS_CMD_MAX
+} gnss_cfg_cmd_type_t;
+
+void do_gnss_cmd(int cmd,uint8_t *buffer,uint32_t size);
+
+void gnss_receive_handler(uint8_t *buffer, int32_t size);
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5b80af7
--- /dev/null
@@ -0,0 +1,41 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "agnss_sample")
+
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/agnss_sample.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/agnss_encode.c
+)
+
+set(PRIVATE_HEADER
+)
+
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(PUBLIC_DEFINES
+CONFIG_AGNSS_SAMPLE
+)
+
+set(COMPONENT_CCFLAGS
+    -Wno-implicit-function-declaration
+)
+
+set(WHOLE_LINK
+true
+)
+
+set(BUILD_AS_OBJ
+false
+)
+
+set(MAIN_COMPONENT
+false
+)
+build_component()
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.c b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.c
new file mode 100644 (file)
index 0000000..9309437
--- /dev/null
@@ -0,0 +1,252 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: agnss encode\r
+ * Author:\r
+ * Create:\r
+ */\r
+#include "agnss_encode.h"\r
+#include <stdio.h>\r
+#include <dirent.h>\r
+#include <string.h>\r
+#include "securec.h"\r
+#include "gnss_datatypes.h"\r
+#include "tiot_service_interface.h"\r
+\r
+#define GNSS_ENCODE_BUFF_MAX_LEN 9300\r
+#define FILE_PATH_LEN            1024\r
+#define INJECT_SLEEP_MS_TIME     500\r
+#define REPORT_MAX_BYTES         10000\r
+#define LISTEN_TIME_THR          1000\r
+#define AGNSS_FILE_MAX_SIZE      1024000\r
+#define AGNSS_DATA_PATH          "/user/xgnss/AGNSS.dat" // 可自行配置路径\r
+\r
+// 监听消息\r
+static uint8_t g_ackBuff[REPORT_MAX_BYTES] = { 0 };\r
+\r
+/* 计算命令内容校准和 */\r
+static uint16_t CalcChecksum(uint8_t *buff, uint16_t len)\r
+{\r
+    uint16_t checksum = 0;\r
+    uint16_t i = 0;\r
+    while (i++ < len) {\r
+        checksum += *buff;\r
+        buff++;\r
+    }\r
+    return checksum;\r
+}\r
+\r
+/* AGNSS计算内容校准和, 校验和模256,与芯片侧的命令校验和计算不可混用 */\r
+uint8_t CalcAgnssCheckSum(uint8_t *data, uint16_t len)\r
+{\r
+    uint8_t sum = 0;\r
+    for (uint16_t i = 0; i < len; i++) {\r
+        sum += data[i];\r
+    }\r
+    return sum;\r
+}\r
+\r
+int32_t AgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime)\r
+{\r
+    uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN);\r
+    if (buff == NULL) {\r
+        printf("\nerror: malloc failed in AgnssInjectUtcTime\n");\r
+        return 0;\r
+    }\r
+    memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN);\r
+\r
+    GnssMsg *hdr = (GnssMsg *)buff;\r
+    hdr->cmd = CMD_XGNSS_INJECT_UTC_TIME;\r
+    hdr->sequence = 0;\r
+    errno_t copyRet = memcpy_s(hdr->data, (GNSS_ENCODE_BUFF_MAX_LEN - sizeof(GnssMsg)), utcTime, sizeof(GnssUtcTime));\r
+    if (copyRet != EOK) {\r
+        printf("\nmemcpy UtcTime failed! Errno is %d\n", copyRet);\r
+        free(buff);\r
+        return 0;\r
+    }\r
+    hdr->dataLength = sizeof(GnssUtcTime);\r
+    hdr->checkSum = CalcChecksum(hdr->data, hdr->dataLength);\r
+    int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + hdr->dataLength));\r
+    if (ret < 0) {\r
+        printf("\nerror: AgnssInjectUtcTime error: %d\n", ret);\r
+        free(buff);\r
+        return 0;\r
+    }\r
+\r
+    free(buff);\r
+    return 1;\r
+}\r
+\r
+static uint16_t FillGnssMessageData(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen)\r
+{\r
+    errno_t ret = memcpy_s(outBuff, outLen, inBuff, inLen);\r
+    if (ret != EOK) {\r
+        printf("memcpy XgnssData failed! Errno is %d", ret);\r
+        return 0;\r
+    }\r
+\r
+    return inLen;\r
+}\r
+\r
+static int32_t EncodeGnssMsg(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen)\r
+{\r
+    uint16_t len = FillGnssMessageData(inBuff, inLen, outBuff, outLen);\r
+    if (len > 0) {\r
+        return 1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static void ListenAck(tiot_handle handle)\r
+{\r
+    int32_t i = 0;\r
+    for (;;) {\r
+        // 监听\r
+        int32_t ret = tiot_service_read(handle, g_ackBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR);\r
+        if (ret > 0) {\r
+            uint16_t *type = (uint16_t *)g_ackBuff;\r
+            // 二进制消息类型\r
+            if (type[0] == 0) {\r
+                g_ackBuff[ret] = '\0';\r
+                printf("%s\n", (char *)&g_ackBuff[MSG_CONTENT_IDX]);\r
+            }\r
+            i++;\r
+        }\r
+        if (i >= 1) {\r
+            printf("\ncnt enough\n");\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+static int32_t EncodeAndInjectCmd(tiot_handle handle, GnssCmdType cmdType, uint8_t* inBuff, uint32_t inLen)\r
+{\r
+    // 获取GNSS业务消息头\r
+    int32_t len = 0;\r
+    uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN);\r
+    if (buff == NULL) {\r
+        printf("\nerror: malloc failed in EncodeAndInjectCmd\n");\r
+        return 0;\r
+    }\r
+    memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN);\r
+\r
+    GnssMsg *gnssHdr = (GnssMsg *)buff;\r
+    len += sizeof(GnssMsg);\r
+\r
+    gnssHdr->sequence = 0;\r
+\r
+    int32_t retLen = EncodeGnssMsg(inBuff, inLen, buff + len, (GNSS_ENCODE_BUFF_MAX_LEN - len));\r
+    if (retLen != 1) {\r
+        printf("\nerror: Encode Cmd failed: %d\n", cmdType);\r
+        free(buff);\r
+        return retLen;\r
+    }\r
+    gnssHdr->cmd = cmdType;\r
+    gnssHdr->dataLength = inLen;\r
+    gnssHdr->checkSum = CalcChecksum(gnssHdr->data, gnssHdr->dataLength);\r
+    int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + gnssHdr->dataLength));\r
+    if (ret < 0) {\r
+        printf("\nerror: Inject Cmd failed: %d\n", cmdType);\r
+        free(buff);\r
+        return 0;\r
+    }\r
+    ListenAck(handle);\r
+    printf("\nInject Cmd SUCCESS: %x\n", cmdType);\r
+    free(buff);\r
+    return 1;\r
+}\r
+\r
+void ProcAndInjectAgnssCmd(tiot_handle handle, uint16_t dataType, uint8_t *data, uint16_t dataLen)\r
+{\r
+    /* 1.根据AGNSS dataType类型,转换为芯片侧消息类型 */\r
+    const struct {\r
+        AgnssDataType agnssDataType;    // AGNSS type类型,\r
+        GnssCmdType innerType;            // 芯片侧消息类型\r
+    } table[] = {\r
+        {AGNSS_GPS_INJECT_EPH, CMD_AGNSS_INJECT_NAV},\r
+        {AGNSS_GPS_INJECT_UTC, CMD_AGNSS_INJECT_UTC},\r
+        {AGNSS_GPS_INJECT_ION, CMD_AGNSS_INJECT_IONO},\r
+        {AGNSS_GPS_INJECT_RTI, CMD_AGNSS_INJECT_RTI},\r
+        {AGNSS_GLO_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV},\r
+        {AGNSS_GLO_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI},\r
+        {AGNSS_GLO_INJECT_AUX, CMD_AGNSS_INJECT_GANSS_AUXI},\r
+        {AGNSS_BDS_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV},\r
+        {AGNSS_BDS_INJECT_ION, CMD_AGNSS_INJECT_GANSS_ADDL_IONO},\r
+        {AGNSS_BDS_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI},\r
+        {AGNSS_GAL_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV},\r
+        {AGNSS_GAL_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI}\r
+    };\r
+    uint16_t cmdType = 0;\r
+    // 2.遍历对应关系表\r
+    for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) {\r
+        if (dataType == table[i].agnssDataType) {\r
+            cmdType = (uint16_t)table[i].innerType;\r
+            // 3.找到对应芯片侧消息类型,并下发消息\r
+            EncodeAndInjectCmd(handle, cmdType, data, dataLen);\r
+            break;\r
+        }\r
+    }\r
+    osal_msleep(INJECT_SLEEP_MS_TIME);\r
+}\r
+\r
+void AgnssInjectAllContent(tiot_handle handle, uint8_t *buff, int32_t len)\r
+{\r
+    int32_t remainLen = len;\r
+    // tlv\r
+    while ((uint32_t)remainLen >= sizeof(AgnssDataHeader) + sizeof(AgnssDataTail)) {\r
+        AgnssDataHeader *header = (AgnssDataHeader *)buff;\r
+        uint16_t dataLen = header->len;\r
+        if ((uint32_t)remainLen < sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen) {\r
+            printf("AgnssInjectAllContent: remainLen %d and dataLen %d not match\n", remainLen, dataLen);\r
+            return;\r
+        }\r
+        uint8_t localCheckSum = CalcAgnssCheckSum((uint8_t *)header, (header->data - (uint8_t *)header) + dataLen);\r
+        uint8_t checkSum = ((AgnssDataTail *)(header->data + dataLen))->checkSum;\r
+        if (localCheckSum != checkSum) {\r
+            printf("AgnssInjectAllContent: local CheckSum %d and CheckSum %d not match\n", localCheckSum, checkSum);\r
+            return;\r
+        }\r
+        ProcAndInjectAgnssCmd(handle, header->dataType, header->data, dataLen);\r
+        buff += sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen;\r
+        remainLen -= sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen;\r
+    }\r
+}\r
+\r
+void ProcAgnssFileContent(tiot_handle handle)\r
+{\r
+    char fileName[] = AGNSS_DATA_PATH;\r
+    FILE *fp = fopen(fileName, "rb");\r
+    if (fp == NULL) {\r
+        printf("\nerror: open file failed: %s\n", fileName);\r
+        return;\r
+    }\r
+    fseek(fp, 0, SEEK_END);\r
+    int32_t len = ftell(fp);\r
+    fseek(fp, 0, SEEK_SET);\r
+    if (len < 0 || len > AGNSS_FILE_MAX_SIZE) {\r
+        fclose(fp);\r
+        printf("\nerror: get file len failed: %s\n", fileName);\r
+        return;\r
+    }\r
+    uint8_t *buff = (uint8_t *)malloc(len);\r
+    if (buff == NULL) {\r
+        fclose(fp);\r
+        printf("\nerror: malloc file len failed: %s\n", fileName);\r
+        return;\r
+    }\r
+    int32_t dataSize = fread(buff, len, 1, fp);\r
+    if (dataSize < 0) {\r
+        fclose(fp);\r
+        printf("\nerror: read file failed: %s\n", fileName);\r
+        free(buff);\r
+        return;\r
+    }\r
+    fclose(fp);\r
+    AgnssInjectAllContent(handle, buff, len);\r
+    free(buff);\r
+}\r
+\r
+void AgnssInject(tiot_handle handle)\r
+{\r
+    // 处理AGNSS文件,向芯片注入Agnss辅助数据\r
+    ProcAgnssFileContent(handle);\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.h b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_encode.h
new file mode 100644 (file)
index 0000000..bbef153
--- /dev/null
@@ -0,0 +1,15 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: agnss encode\r
+ * Author:\r
+ * Create:\r
+ */\r
+#ifndef AGNSS_ENCODE_H\r
+#define AGNSS_ENCODE_H\r
+\r
+#include "gnss_datatypes.h"\r
+#include "tiot_service_interface.h"\r
+\r
+int32_t AgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime);\r
+void AgnssInject(tiot_handle handle);\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.c b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.c
new file mode 100644 (file)
index 0000000..537608d
--- /dev/null
@@ -0,0 +1,193 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: agnss sample\r
+ * Author:\r
+ * Create:\r
+ */\r
+#include "agnss_sample.h"\r
+#include <stdio.h>\r
+#include "securec.h"\r
+#include "tiot_service_interface.h"\r
+#include "pm_definition.h"\r
+#include "gnss_datatypes.h"\r
+#include "agnss_encode.h"\r
+\r
+#define AGNSS_FIXMODEALL_NMEADEF_SAMPLE            0\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))\r
+#endif\r
+\r
+#define MSG_TYPE_BINRY              0\r
+#define MSG_TYPE_ASCII              1\r
+#define LISTEN_DATA_MAX_LINES       1000\r
+#define REPORT_MAX_BYTES            10000\r
+\r
+static FILE* g_gnssLogFp = NULL;\r
+static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 };\r
+\r
+typedef int32_t (*GnssCfgFunc)(tiot_handle handle);\r
+\r
+typedef struct {\r
+    uint16_t    sampleId;\r
+    GnssCfgFunc cfgHandle;\r
+} GnssSamplesCfgTable;\r
+\r
+static int32_t QryVersion(tiot_handle handle)\r
+{\r
+    const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};\r
+    // 查询版本号\r
+    int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion));\r
+    if (ret < 0) {\r
+        printf("error: QryVersion error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    return 1;\r
+}\r
+\r
+// 注入AGNSS,使用默认配置启动\r
+int32_t InjectAgnss(tiot_handle handle)\r
+{\r
+    const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03};\r
+\r
+    // 配置log级别:info级别。\r
+    int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo));\r
+    if (ret < 0) {\r
+        printf("error: cfgLogLevelInfo error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    // 注入UTC时间, 注入Agnss辅助数据前必须先注入参考时间\r
+    GnssUtcTime utcTime = {2024, 3, 22, 10, 0, 0, 0, 1}; // 需要用当前的UTC时间替换\r
+    ret = AgnssInjectUtcTime(handle, &utcTime);\r
+    if (ret == 0) {\r
+        printf("error: AgnssInjectUtcTime failed!\n");\r
+        return 0;\r
+    }\r
+    printf("AgnssInjectUtcTime success!\n");\r
+\r
+    // AGNSS注入\r
+    // 注意,默认AGNSS文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换\r
+    AgnssInject(handle);\r
+\r
+    return 1;\r
+}\r
+\r
+static const GnssSamplesCfgTable g_gnssSamplesCfg[] = {\r
+    {AGNSS_FIXMODEALL_NMEADEF_SAMPLE, InjectAgnss},\r
+};\r
+\r
+static int32_t StartGnss(tiot_handle handle)\r
+{\r
+    const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,\r
+        0x01, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+    // 启动GNSS\r
+    int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd));\r
+    if (ret < 0) {\r
+        printf("error: start gnss error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    printf("start gnss\n");\r
+    return 1;\r
+}\r
+\r
+static int32_t StopGnss(tiot_handle handle)\r
+{\r
+    const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+    // 停止GNSS\r
+    int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd));\r
+    if (ret < 0) {\r
+        printf("error: stop gnss error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    printf("stop gnss\n");\r
+    return 1;\r
+}\r
+\r
+static void ListenGnssData(tiot_handle handle)\r
+{\r
+    int32_t i = 0;\r
+    // 写日志\r
+    for (;;) {  // 写日志条件\r
+        // 监听\r
+        int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, 1000);\r
+        if (ret > 0) {\r
+            uint16_t *type = (uint16_t *)g_gnssServiceBuff;\r
+            if (type[0] == MSG_TYPE_ASCII) {\r
+                g_gnssServiceBuff[ret] = '\0';\r
+                printf("%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]);\r
+                fprintf(g_gnssLogFp, "%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]);\r
+            }\r
+            i++;\r
+        }\r
+        if (i >= LISTEN_DATA_MAX_LINES) {\r
+            printf("cnt enough\n");\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+void AgnssExecuteSamples(void)\r
+{\r
+    uapi_pm_add_sleep_veto(PM_ID_SYS);\r
+    printf("enter gnss samples\n");\r
+    // Step1: init\r
+    int32_t ret = tiot_service_init();\r
+    if (ret != 0) {\r
+        printf("tiot service init fail\n");\r
+    }\r
+\r
+    // 打开日志文件\r
+    g_gnssLogFp = fopen("/user/gnss.log", "w");\r
+    if (g_gnssLogFp == NULL) {\r
+        printf("error: open log file error\n");\r
+        return;\r
+    }\r
+    printf("before open tiot service\n");\r
+\r
+    // Step2: power on gnss\r
+    tiot_handle handle = tiot_service_open("gn71", NULL);\r
+    if (handle == 0) {\r
+        printf("open tiot service fail\n");\r
+        return;\r
+    }\r
+    printf("open tiot service success\n");\r
+\r
+    int32_t cfgRet;\r
+    // ---- loop ----------\r
+    for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) {\r
+        cfgRet = 0;\r
+        if (g_gnssSamplesCfg[i].sampleId == i) {\r
+            // Step3: config gnss\r
+            if (g_gnssSamplesCfg[i].cfgHandle != NULL) {\r
+                cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle);\r
+            }\r
+            if (cfgRet == 0) {\r
+                continue;\r
+            }\r
+            printf("cfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId);\r
+            QryVersion(handle);\r
+\r
+            // Step4: start gnss\r
+            if (StartGnss(handle) == 0) {\r
+                continue;\r
+            }\r
+            // Step5: listening gnss data\r
+            ListenGnssData(handle);\r
+            // Step6: stop gnss\r
+            if (StopGnss(handle) == 0) {\r
+                continue;\r
+            }\r
+        }\r
+    }\r
+    // ---------------------\r
+    // Step7: power off gnss\r
+    tiot_service_close(handle);\r
+    // 关日志文件\r
+    fclose(g_gnssLogFp);\r
+    g_gnssLogFp = NULL;\r
+    // Step8: deinit\r
+    tiot_service_deinit();\r
+    uapi_pm_remove_sleep_veto(PM_ID_SYS);\r
+    printf("finish gnss samples\n");\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.h b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/agnss_sample.h
new file mode 100644 (file)
index 0000000..8c8823b
--- /dev/null
@@ -0,0 +1,12 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: agnss sample\r
+ * Author:\r
+ * Create:\r
+ */\r
+#ifndef AGNSS_SAMPLE_H\r
+#define AGNSS_SAMPLE_H\r
+\r
+void AgnssExecuteSamples(void);\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/gnss_datatypes.h b/code/sdk/drivers/peripheral/gnss/sample/agnss_sample/gnss_datatypes.h
new file mode 100644 (file)
index 0000000..97607f9
--- /dev/null
@@ -0,0 +1,76 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: gnss datatypes\r
+ * Author:\r
+ * Create:\r
+ */\r
+#ifndef GNSS_DATATYPES_H\r
+#define GNSS_DATATYPES_H\r
+\r
+#include <stdint.h>\r
+\r
+#define MSG_CONTENT_IDX             2\r
+\r
+// 消息类型\r
+typedef enum {\r
+    CMD_AGNSS_INJECT_REF_LOC = 0x0302,         // 位置预测注入\r
+    CMD_AGNSS_INJECT_NAV = 0x0303,             // 星历数据注入\r
+    CMD_AGNSS_INJECT_IONO = 0x0304,            // 电离层参数注入\r
+    CMD_AGNSS_INJECT_UTC = 0x0305,             // UTC时间注入\r
+    CMD_AGNSS_INJECT_RTI = 0x0306,             // 完好性信息注入\r
+    CMD_AGNSS_INJECT_GANSS_ADDL_IONO = 0x0308, // 非GPS电离层参数注入\r
+    CMD_AGNSS_INJECT_GANSS_NAV = 0x0309,       // 非GPS星历数据注入\r
+    CMD_AGNSS_INJECT_GANSS_RTI = 0x030A,       // 非GPS完好性信息注入\r
+    CMD_AGNSS_INJECT_GANSS_AUXI = 0x030C,      // 频点对应关系注入,GLONASS\r
+    CMD_XGNSS_INJECT_UTC_TIME = 0x0404,        // 最开始注入的UTC时间\r
+    CMD_BUTT,\r
+} GnssCmdType;\r
+\r
+typedef enum {\r
+    AGNSS_GPS_INJECT_EPH = 0x0002,\r
+    AGNSS_GPS_INJECT_UTC = 0x0003,\r
+    AGNSS_GPS_INJECT_ION = 0x0004,\r
+    AGNSS_GPS_INJECT_RTI = 0x0005,\r
+    AGNSS_GLO_INJECT_EPH = 0x0022,\r
+    AGNSS_GLO_INJECT_RTI = 0x0025,\r
+    AGNSS_GLO_INJECT_AUX = 0x0026,\r
+    AGNSS_BDS_INJECT_EPH = 0x0042,\r
+    AGNSS_BDS_INJECT_ION = 0x0044,\r
+    AGNSS_BDS_INJECT_RTI = 0x0045,\r
+    AGNSS_GAL_INJECT_EPH = 0x0062,\r
+    AGNSS_GAL_INJECT_RTI = 0x0065\r
+} AgnssDataType;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+    uint16_t  cmd;          // 消息类型\r
+    uint16_t  checkSum;     // 校验和,只计算实际数据部分,不包含头\r
+    uint16_t  sequence;     // 序列号,host下发\r
+    uint16_t  dataLength;   // 数据长度,实际数据的长度,不包含头\r
+    uint8_t   data[0];\r
+} GnssMsg;\r
+\r
+typedef struct {\r
+    uint16_t year;          // YYYY\r
+    uint8_t  month;         // MM, 1~12\r
+    uint8_t  day;           // DD, 1~31\r
+    uint8_t  hour;          // hh, 0~23\r
+    uint8_t  minute;        // mm, 0~59\r
+    uint8_t  second;        // ss, 0~59\r
+    uint16_t ms;            // ms, 0~999\r
+    uint8_t  valid;         // 0: invalid, 1: valid\r
+} GnssUtcTime;\r
+\r
+typedef struct {\r
+    uint16_t dataType;\r
+    uint16_t len;\r
+    uint8_t data[0];\r
+} AgnssDataHeader;\r
+\r
+typedef struct {\r
+    uint8_t checkSum;\r
+} AgnssDataTail;\r
+\r
+#pragma pack()\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/CMakeLists.txt b/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/CMakeLists.txt
new file mode 100644 (file)
index 0000000..780a541
--- /dev/null
@@ -0,0 +1,41 @@
+#===============================================================================
+# @brief    cmake make file
+# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "gnss_sample")
+
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/gnss_sample.c
+)
+
+set(PRIVATE_HEADER
+    ${TIOT_HEADER_LIST}
+)
+
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(PUBLIC_DEFINES
+CONFIG_GNSS_SAMPLE
+)
+
+set(COMPONENT_CCFLAGS
+    -Wno-implicit-function-declaration
+)
+
+set(WHOLE_LINK
+true
+)
+
+set(BUILD_AS_OBJ
+false
+)
+
+set(MAIN_COMPONENT
+false
+)
+build_component()
diff --git a/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c b/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c
new file mode 100644 (file)
index 0000000..e59debb
--- /dev/null
@@ -0,0 +1,390 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2024. All rights reserved.\r
+ * Description: gnss sample\r
+ * Author:\r
+ * Create:\r
+ */\r
+#include "gnss_sample.h"\r
+#include <stdio.h>\r
+#include "securec.h"\r
+#include "tiot_service_interface.h"\r
+#include "pm_definition.h"\r
+#include "gnss_ctl.h"\r
+\r
+#define COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE        0\r
+#define AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE        1\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))\r
+#endif\r
+#define MSG_CONTENT_IDX             2\r
+#define MSG_TYPE_BINRY              0\r
+#define MSG_TYPE_ASCII              1\r
+#define LISTEN_DATA_MAX_LINES       10000\r
+#define REPORT_MAX_BYTES            10000\r
+#define LISTEN_TIME_THR             1000\r
+\r
+static FILE* g_gnssLogFp = NULL;\r
+static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 };\r
+\r
+typedef int32_t (*GnssCfgFunc)(tiot_handle handle);\r
+\r
+//配置使能 TRK 轨迹低功耗(芯片默认)。\r
+const uint8_t CFG_TRK_LPW_ENABLE[] = {0x03 ,0x00 ,0x0a ,0x00 ,0x00 ,0x00 ,0x06 ,0x00 ,0x05 ,0x00 ,0x02 ,0x00 ,0x01 ,0x02 };\r
+//配置禁用 TRK 轨迹低功耗。\r
+const uint8_t CFG_TRK_LPW_DISABLE[] = {0x03 ,0x00 ,0x07 ,0x00 ,0x00 ,0x00 ,0x06 ,0x00 ,0x05 ,0x00 ,0x02 ,0x00 ,0x00 ,0x00};\r
+\r
+//配置使能 ACQ 捕获低功耗(芯片默认)。\r
+const uint8_t CFG_ACQ_LPW_ENABLE[] = {0x03 ,0x00 ,0x09 ,0x00 ,0x00 ,0x00 ,0x06 ,0x00 ,0x04 ,0x00 ,0x02 ,0x00 ,0x01 ,0x02 };\r
+//配置禁用 ACQ 捕获低功耗。\r
+const uint8_t CFG_ACQ_LPW_DISABLE[] = {0x03 ,0x00 ,0x06 ,0x00 ,0x00 ,0x00 ,0x06 ,0x00 ,0x04 ,0x00 ,0x02 ,0x00 ,0x00 ,0x00};\r
+                                         \r
+\r
+//定位模式自动,冷启动,热启动\r
+const uint8_t cfgAutoStartCmd[] = {0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00};\r
+const uint8_t cfgAltCstrCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0x10, 0x01, 0x00, 0x00};\r
+const uint8_t cfgColdStartCmd[] = {0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};\r
+\r
+//配置定位使用的卫星系统,GPS\r
+const uint8_t cfgFixModeGpsCmd[] = {0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00};\r
+//配置定位使用的卫星系统,QZSS/GAL/BDS/GLO/GPS\r
+const uint8_t cfgFixModeAllCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00};\r
+\r
+//配置NMEA显示内容,默认显示, RMC/GGA\r
+const uint8_t cfgNmeaDefaultCmd[] = {0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0x11, 0x00};\r
+//配置NMEA显示内容,全部显示,PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA\r
+const uint8_t cfgNmeaAllCmd[] = {0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0xff, 0x00};  \r
+\r
+/*查询版本号*/\r
+const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};\r
+\r
+/*开始定位*/\r
+const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+/*停止定位*/\r
+const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+\r
+/*配置禁用抗干扰特性*/\r
+const uint8_t CFG_ANTIJAM_DISABLE[]={0x03, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+/*配置使能抗干扰特性(芯片默认)*/\r
+const uint8_t CFG_ANTIJAM_ENABLE[]={0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00};\r
+\r
+typedef struct {\r
+    uint16_t    sampleId;\r
+    GnssCfgFunc cfgHandle;\r
+} GnssSamplesCfgTable;\r
+\r
+\r
+/**NMEA解析变量*/\r
+#include "NMEA0183.h"\r
+static NMEA0183 g_nmeadata={0};\r
+gps_data_t g_global_gpsData={0};\r
+\r
+/**GPS状态位*/\r
+static int g_is_gnss_poweron=0;\r
+static int g_is_gnss_logon=0;\r
+static int g_gnss_stopflag=0;\r
+\r
+static int decode_nmea(char c)\r
+{\r
+    int ret=0;\r
+    ret=0;\r
+    if(nmea_decode(&g_nmeadata,c) ==1 ) ///调用解析函数\r
+    {\r
+        dump_nmea_str(&(g_nmeadata.gpsParse));\r
+        if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002 )\r
+        {\r
+            //一组数据最后一条\r
+            memcpy_s(&g_global_gpsData,sizeof(gps_data_t),&(g_nmeadata.gpsData),sizeof(gps_data_t));\r
+            ret = 1;\r
+            memset(&g_nmeadata,0,sizeof(g_nmeadata));\r
+        }\r
+    } \r
+\r
+    return ret;\r
+}\r
+\r
+gps_data_t * getGPSGlobaldata(void)\r
+{\r
+    return &g_global_gpsData;\r
+}\r
+\r
+\r
+int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle)\r
+{\r
+\r
+    // 配置启动模式:冷启动模式。\r
+    int32_t ret = tiot_service_write(handle, cfgColdStartCmd, sizeof(cfgColdStartCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgColdStartCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    // 配置使能的GNSS星座:GPS。\r
+    ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA。\r
+    ret = tiot_service_write(handle, cfgNmeaAllCmd, sizeof(cfgNmeaAllCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgNmeaAllCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE));\r
+    if (ret < 0) {\r
+        printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE));\r
+    if (ret < 0) {\r
+        printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    ret = tiot_service_write(handle, CFG_ANTIJAM_ENABLE, sizeof(CFG_ANTIJAM_ENABLE));\r
+    if (ret < 0) {\r
+        printf("\nerror: CFG_ANTIJAM_ENABLE error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    return 1;\r
+}\r
+\r
+// 如果有历史信息,自动模式启动会切换到热启动模式,如果无历史信息,则自动模式启动仍然为冷启动\r
+int32_t CfgAutoStartFixModeAllNmeaDefault(tiot_handle handle)\r
+{\r
+     \r
+\r
+    // 配置启动模式:自动模式。\r
+    int32_t ret = tiot_service_write(handle, cfgAutoStartCmd, sizeof(cfgAutoStartCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgAutoStartCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS。\r
+    ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    // 配置上报NMEA类型:RMC/GGA。\r
+    ret = tiot_service_write(handle, cfgNmeaDefaultCmd, sizeof(cfgNmeaDefaultCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE));\r
+    if (ret < 0) {\r
+        printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
+        return 0;\r
+    }\r
+\r
+    ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE));\r
+    if (ret < 0) {\r
+        printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    return 1;\r
+}\r
+\r
+static int32_t QryVersion(tiot_handle handle)\r
+{\r
+   \r
+    // 查询版本号\r
+    int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion));\r
+    if (ret < 0) {\r
+        printf("\nerror: QryVersion error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    return 1;\r
+}\r
+\r
+static const GnssSamplesCfgTable g_gnssSamplesCfg[] = {\r
+    {COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE,        CfgColdStartFixModeGpsNmeaAll},\r
+    // {AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE,        CfgAutoStartFixModeAllNmeaDefault}\r
+};\r
+\r
+static int32_t StartGnss(tiot_handle handle)\r
+{\r
+    \r
+    // 启动GNSS\r
+    int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: start gnss error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    printf("\nstart gnss\n");\r
+    return 1;\r
+}\r
+\r
+static int32_t StopGnss(tiot_handle handle)\r
+{\r
+    // 停止GNSS\r
+    int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd));\r
+    if (ret < 0) {\r
+        printf("\nerror: stop gnss error: %d\n", ret);\r
+        return 0;\r
+    }\r
+    printf("\nstop gnss\n");\r
+    return 1;\r
+}\r
+\r
+static void ListenGnssData(tiot_handle handle)\r
+{\r
+    int32_t i = 0;\r
+    // 写日志\r
+    for (;;) {  // 写日志条件\r
+\r
+        if (i >= LISTEN_DATA_MAX_LINES) {\r
+            printf("\ncnt enough\n");\r
+            break;\r
+        }\r
+        if (g_gnss_stopflag == 1)\r
+        {\r
+            break;\r
+        }\r
+        // 监听\r
+        int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR);\r
+        if (ret > 0) {\r
+            uint16_t *type = (uint16_t *)g_gnssServiceBuff;\r
+            if (type[0] == MSG_TYPE_ASCII) {\r
+                g_gnssServiceBuff[ret] = '\0';\r
+                char* pbuf=(char *)&g_gnssServiceBuff[MSG_CONTENT_IDX];\r
+                printf("%s\n", pbuf);\r
+                if (g_is_gnss_logon)\r
+                    fprintf(g_gnssLogFp, "%s\n", pbuf);\r
+                for (int index=0;index < ret ;index++)\r
+                {\r
+                    if (decode_nmea(pbuf[index])==1)\r
+                    {\r
+                        // dump_location_data(&g_global_gpsData);\r
+                        printf("decode_nmea done\r\n");\r
+                    }\r
+                }\r
+            }\r
+            i++;\r
+        }\r
+\r
+    }\r
+}\r
+void GnssServerStop(void)\r
+{\r
+    g_gnss_stopflag=1;\r
+}\r
+int getGnssServerStat(void)\r
+{\r
+    return g_is_gnss_poweron;\r
+}\r
+\r
+int is_GnssLogEnabled(void)\r
+{\r
+    return g_is_gnss_logon;\r
+}\r
+int GnssLogEnable(bool enable)\r
+{\r
+    if (enable)\r
+        g_is_gnss_logon = 1;\r
+    else\r
+        g_is_gnss_logon = 0;\r
+\r
+\r
+    return g_is_gnss_logon;\r
+}\r
+\r
+\r
+void GnssServerStart(void)\r
+{\r
+    printf("\nenter gnss samples\n");\r
+    if(g_is_gnss_poweron == 1)\r
+    {\r
+        printf("gnss already on\r\n");\r
+        return ;\r
+    }\r
+    uapi_pm_add_sleep_veto(PM_ID_SYS);\r
+\r
+    #ifdef DOWNLOAD_GNSS_SWITCH\r
+    download_gnss_switch(SWITCH_TO_GNSS);\r
+    #endif\r
+    g_is_gnss_poweron = 1;\r
+    g_gnss_stopflag = 0;\r
+    // Step1: init\r
+    int32_t ret = tiot_service_init();\r
+    if (ret != 0) {\r
+        printf("\ntiot service init fail\n");\r
+        g_is_gnss_poweron = 0;\r
+        g_gnss_stopflag = 1;\r
+    }\r
+\r
+    // 打开日志文件\r
+    if (g_is_gnss_logon)\r
+    {\r
+        g_gnssLogFp = fopen("/user/log/gnss.log", "w");\r
+        if (g_gnssLogFp == NULL) {\r
+            printf("\nerror: open log file error\n");\r
+            return;\r
+        }\r
+    }\r
+    printf("\nbefore open tiot service\n");\r
+\r
+    // Step2: power on gnss\r
+    tiot_handle handle = tiot_service_open("gn71", NULL);\r
+    if (handle == 0) {\r
+        printf("\nopen tiot service fail\n");\r
+        g_is_gnss_poweron = 0;\r
+        g_gnss_stopflag = 1;\r
+        return;\r
+    }\r
+    printf("\nopen tiot service success\n");\r
+\r
+    int32_t cfgRet;\r
+    // ---- loop ----------\r
+    for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) {\r
+        cfgRet = 0;\r
+        if (g_gnssSamplesCfg[i].sampleId == i) {\r
+            // Step3: config gnss\r
+            if (g_gnssSamplesCfg[i].cfgHandle != NULL) {\r
+                cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle);\r
+            }\r
+            if (cfgRet == 0) {\r
+                continue;\r
+            }\r
+            printf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId);\r
+            QryVersion(handle);\r
+\r
+            // Step4: start gnss\r
+            if (StartGnss(handle) == 0) {\r
+                continue;\r
+            }\r
+            // Step5: listening gnss data\r
+            ListenGnssData(handle);\r
+            // Step6: stop gnss\r
+            if (StopGnss(handle) == 0) {\r
+                continue;\r
+            }\r
+        }\r
+    }\r
+    // ---------------------\r
+    // Step7: power off gnss\r
+    tiot_service_close(handle);\r
+    // 关日志文件\r
+    if (g_is_gnss_logon)\r
+    {\r
+        fclose(g_gnssLogFp);\r
+        g_gnssLogFp = NULL;\r
+    }\r
+    // Step8: deinit\r
+    tiot_service_deinit();\r
+\r
+    #ifdef DOWNLOAD_GNSS_SWITCH\r
+    download_gnss_switch(SWITCH_TO_DOWNLOAD);\r
+    #endif\r
+    uapi_pm_remove_sleep_veto(PM_ID_SYS);\r
+    g_is_gnss_poweron=0;\r
+    printf("\nfinish gnss samples\n");\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.h b/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.h
new file mode 100644 (file)
index 0000000..72d28aa
--- /dev/null
@@ -0,0 +1,18 @@
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2024. All rights reserved.\r
+ * Description: gnss sample\r
+ * Author:\r
+ * Create:\r
+ */\r
+#ifndef GNSS_SAMPLE_H\r
+#define GNSS_SAMPLE_H\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif /* __cplusplus */\r
+void GnssServerStart(void);\r
+void GnssServerStop(void);\r
+int getGnssServerStat(void);\r
+#ifdef __cplusplus\r
+}\r
+#endif /* __cplusplus */\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/src/NMEA0183.c b/code/sdk/drivers/peripheral/gnss/src/NMEA0183.c
new file mode 100644 (file)
index 0000000..bf27cbe
--- /dev/null
@@ -0,0 +1,1445 @@
+\r
+#include "NMEA0183.h"\r
+#ifndef NOUTILS\r
+#include "custom_utils.h"\r
+#include <securec.h>\r
+#endif\r
+#include <stdio.h>\r
+\r
+static short int from_hex(char a);\r
+static unsigned char nmea_term_complete(gps_nmea_t* pnmea, gps_data_t* pdata);\r
+static int sring_to_int(const char* pstr, unsigned char* b);\r
+static int int_pow(int value, unsigned int count);\r
+static double double_pow(double value, unsigned int count);\r
+static unsigned char float_to_string(double value, char* pdest, unsigned int intgr, unsigned int dec);\r
+static unsigned char int_to_string(int value, char* pdest, unsigned int intgr) ;\r
+static double string_to_float(const char* pstr, unsigned char* b); \r
+static int sring_to_int(const char* pstr, unsigned char* b); \r
+static int make_date_time(gps_data_t* pdata, unsigned int date, unsigned int time);\r
+\r
+\r
+void add_start_to_gpsbuf(gps_nmea_t* pnmea, gps_data_t* pdata)\r
+{\r
+       if (pnmea==NULL ||  pdata == NULL ) return;\r
+       start_stat_t *p_data_star=NULL;\r
+       start_stat_t *p_nmea_star=NULL;\r
+                       \r
+       p_nmea_star = pnmea->starts;\r
+       \r
+       switch(pnmea->location_system)\r
+       {\r
+               case GNSS_: //GN\r
+                       p_data_star = pdata->startsN;\r
+                       pdata->starcountN = pnmea->starcount;\r
+                       break;\r
+               case GPS_L1C_A:         //GP\r
+                       p_data_star = pdata->startsP;\r
+                       pdata->starcountP = pnmea->starcount;\r
+                       break;\r
+               case GLONASS_L1OF:      //GL\r
+                       p_data_star = pdata->startsL;\r
+                       pdata->starcountL = pnmea->starcount;\r
+                       break;\r
+               case Galileo_E1C:       //GA\r
+                       p_data_star = pdata->startsA;\r
+                       pdata->starcountA = pnmea->starcount;\r
+                       break;\r
+               case BDS_Bli:           //GB\r
+                       p_data_star = pdata->startsB;\r
+                       pdata->starcountB = pnmea->starcount;\r
+                       break;\r
+               case QZSS_L1C_A:        //GQ\r
+                       p_data_star = pdata->startsQ;\r
+                       pdata->starcountQ = pnmea->starcount;\r
+                       break;\r
+       }\r
+\r
+\r
+\r
+       start_stat_t tmp={0};\r
+       for (int i = 0;i < pnmea->gsvpage_starcount ; i++)\r
+       {\r
+               for (int j=0;j<5;j++)\r
+               {\r
+                       //找到空位直接赋值\r
+                       if(p_data_star[j].snr==0 && p_data_star[j].starID==0)\r
+                       {\r
+                               p_data_star[j].snr = p_nmea_star[i].snr;\r
+                               p_data_star[j].starID = p_nmea_star[i].starID;\r
+                               break;\r
+                       }else\r
+                       {\r
+                               if (p_data_star[j].snr < p_nmea_star[i].snr)\r
+                               {\r
+                                       tmp.snr=p_data_star[j].snr;\r
+                                       tmp.starID=p_data_star[j].starID;\r
+                                       p_data_star[j].snr = p_nmea_star[i].snr;\r
+                                       p_data_star[j].starID = p_nmea_star[i].starID;\r
+                                       p_nmea_star[i].snr = tmp.snr;\r
+                                       p_nmea_star[i].starID = tmp.starID;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+}\r
+/* GPS数据解析 */ \r
+unsigned char nmea_decode(NMEA0183* nmea, char c)\r
+{\r
+    unsigned char valid_sentence = 0;\r
+    \r
+       if((void*)0==nmea) return 0;\r
+\r
+    switch (c) \r
+       {\r
+           case ',':  /* 字段域分割符号 */ \r
+               nmea->gpsParse.parity ^= c;\r
+               /* no break */\r
+           case '\r':\r
+           case '\n':\r
+           case '*':\r
+               if (nmea->gpsParse.term_offset < sizeof(nmea->gpsParse.term)) \r
+                       {\r
+                   nmea->gpsParse.term[nmea->gpsParse.term_offset] = 0;\r
+                   valid_sentence = nmea_term_complete(&nmea->gpsParse, &nmea->gpsData);\r
+               }\r
+               ++nmea->gpsParse.term_number;\r
+               nmea->gpsParse.term_offset = 0;\r
+               nmea->gpsParse.is_checksum_term = (c == '*');   /* 后面两个字节为校验字段 */ \r
+               return valid_sentence;\r
+       \r
+           case '$': /* 字段信息开始 */ \r
+               nmea->gpsParse.term_number = nmea->gpsParse.term_offset = 0;\r
+               nmea->gpsParse.parity = 0;\r
+               nmea->gpsParse.sentence_type = GPS_SENTENCE_OTHER;\r
+               nmea->gpsParse.is_checksum_term = 0;\r
+               nmea->gpsParse.gps_data_good = 0;\r
+               return valid_sentence;\r
+    }\r
+\r
+    /* 保存字段域数据 */\r
+    if (nmea->gpsParse.term_offset < sizeof(nmea->gpsParse.term) - 1)\r
+        nmea->gpsParse.term[nmea->gpsParse.term_offset++] = c;\r
+    if (!nmea->gpsParse.is_checksum_term)\r
+        nmea->gpsParse.parity ^= c;\r
+\r
+    return valid_sentence;\r
+}\r
+\r
+/* 单个十六进制字符转换为十进制 */\r
+static short int from_hex(char a)\r
+{\r
+    if (a >= 'A' && a <= 'F')\r
+        return a - 'A' + 10;\r
+    else if (a >= 'a' && a <= 'f')\r
+        return a - 'a' + 10;\r
+    else\r
+        return a - '0';\r
+}\r
+\r
+/* 处理单个字段域数据 */\r
+static unsigned char nmea_term_complete(gps_nmea_t* pnmea, gps_data_t* pdata)\r
+{\r
+       if((void*)0==pnmea || (void*)0==pdata) return 0;\r
+    // handle the last term in a message\r
+    if (pnmea->is_checksum_term)\r
+       {\r
+        unsigned char checksum = 16 * from_hex(pnmea->term[0]) + from_hex(pnmea->term[1]);\r
+        \r
+        /* 检验信息段是否完整无错,如果校验通过,则将解析得到的数据保存,并提供给用户调用*/\r
+        if (checksum == pnmea->parity) \r
+               {\r
+            if (pnmea->gps_data_good) \r
+                       {\r
+                unsigned int now = 1 ;\r
+#ifndef NOUTILS\r
+                               uapi_get_timestampe_ms(&now);\r
+#endif\r
+                switch (pnmea->sentence_type) \r
+                               {\r
+                       case GPS_SENTENCE_RMC:\r
+                           pnmea->last_RMC_ms = now;\r
+                           //time                        = _new_time;\r
+                           //date                        = _new_date;\r
+                           pdata->location.lat     = pnmea->new_latitude;\r
+                           pdata->location.lng     = pnmea->new_longitude;\r
+                           pdata->ground_speed     = pnmea->new_speed;\r
+                           pdata->ground_course    = pnmea->new_course;\r
+                                               make_date_time(pdata, pnmea->new_date, pnmea->new_time);\r
+                           \r
+                           break;\r
+                       case GPS_SENTENCE_GGA:\r
+                           pnmea->last_GGA_ms = now;\r
+                           pdata->location.alt  = pnmea->new_altitude;\r
+                           pdata->location.lat  = pnmea->new_latitude;\r
+                           pdata->location.lng  = pnmea->new_longitude;\r
+                           pdata->num_sats      = pnmea->new_satellite_count;\r
+                           pdata->hdop          = pnmea->new_hdop;\r
+\r
+                           switch(pnmea->new_quality_indicator) {\r
+                                                       case 0: // Fix not available or invalid\r
+                                                               pdata->status = NO_FIX;\r
+                                                               break;\r
+                                                       case 1: // GPS SPS Mode, fix valid\r
+                                                               pdata->status = GPS_OK_FIX_3D;\r
+                                                               break;\r
+                                                       case 2: // Differential GPS, SPS Mode, fix valid\r
+                                                               pdata->status = GPS_OK_FIX_3D_DGPS;\r
+                                                               break;\r
+                                                       case 3: // GPS PPS Mode, fix valid\r
+                                                               pdata->status = GPS_OK_FIX_3D;\r
+                                                               break;\r
+                                                       case 4: // Real Time Kinematic. System used in RTK mode with fixed integers\r
+                                                               pdata->status = GPS_OK_FIX_3D_RTK_FIXED;\r
+                                                               break;\r
+                                                       case 5: // Float RTK. Satellite system used in RTK mode, floating integers\r
+                                                               pdata->status = GPS_OK_FIX_3D_RTK_FLOAT;\r
+                                                               break;\r
+                                                       case 6: // Estimated (dead reckoning) Mode\r
+                                                               pdata->status = NO_FIX;\r
+                                                               break;\r
+                                                       default://to maintain compatibility with MAV_GPS_INPUT and others\r
+                                                               pdata->status = GPS_OK_FIX_3D;\r
+                                                               break;\r
+                                               }\r
+                           break;\r
+                       case GPS_SENTENCE_VTG:\r
+                           pnmea->last_VTG_ms = now;\r
+                           pdata->ground_speed  = pnmea->new_speed;\r
+                           pdata->ground_course = pnmea->new_course;\r
+\r
+                           // VTG has no fix indicator, can't change fix status\r
+                           break;\r
+//                     case GPS_SENTENCE_HDT:\r
+//                                              pnmea->last_HDT_ms = now;\r
+// //                                           pdata->gps_yaw = wrap_360(pnmea->new_gps_yaw*0.01f);\r
+//                                              pdata->have_gps_yaw = 1;\r
+//                                              break;\r
+                                       case GPS_SENTENCE_GSA:\r
+                           pnmea->last_GSA_ms = now;\r
+                           //time                        = _new_time;\r
+                           //date                        = _new_date;\r
+                           // pdata->location.lat     = pnmea->new_latitude;\r
+                           // pdata->location.lng     = pnmea->new_longitude;\r
+                           // pdata->ground_speed     = pnmea->new_speed;\r
+                           // pdata->ground_course    = pnmea->new_course;\r
+                                               // make_date_time(pdata, pnmea->new_date, pnmea->new_time);\r
+                           // pdata->last_gps_time_ms = now;\r
+                                               break;\r
+                                       case GPS_SENTENCE_GSV:\r
+                           pnmea->last_GSV_ms = now;\r
+                                               // for (int j=0;j<20;j++)\r
+                                               // {\r
+                                               //      pdata->starts[j].snr=pnmea->starts[j].snr;\r
+                                               //      pdata->starts[j].starID=pnmea->starts[j].starID;\r
+                                               // }\r
+                                               // pdata->starcount = pnmea->starcount;\r
+                                               add_start_to_gpsbuf(pnmea,pdata);\r
+                                               printf("gsv starcount copy to pdata \r\n");\r
+                                               \r
+                                               break;\r
+                                       case GPS_SENTENCE_GLL:\r
+                           pnmea->last_GLL_ms = now;\r
+                                               break;\r
+                                       case GPS_SENTENCE_ZDA:\r
+                           pnmea->last_ZDA_ms = now;\r
+                                               break;\r
+                                       case GPS_SENTENCE_TH000:\r
+                                               pdata->th000_signal_vga = pnmea->th000_signal_vga;\r
+                           pdata->last_gps_time_ms = now;\r
+                                               printf("th000 copy to pdata \r\n" );\r
+                                               break;\r
+                                       case GPS_SENTENCE_TH001:\r
+                                               pdata->th001_errorcode = pnmea->th001_errorcode;\r
+                                               pdata->th001_quality = pnmea->th001_quality;\r
+                                               pdata->th001_trace_star_count = pnmea->th001_trace_star_count;\r
+                                               pdata->th001_valid_star_count = pnmea->th001_valid_star_count;\r
+                           pdata->last_gps_time_ms = now;\r
+                                               printf("th001 copy to pdata \r\n" );\r
+                                       case GPS_SENTENCE_TH002:\r
+                           pdata->last_gps_time_ms = now;\r
+                                               break;\r
+                }\r
+            } else {\r
+                switch (pnmea->sentence_type) {\r
+                case GPS_SENTENCE_RMC:\r
+                case GPS_SENTENCE_GGA:\r
+                    // Only these sentences give us information about\r
+                    // fix status.\r
+                    pdata->status = NO_FIX;\r
+                }\r
+            }\r
+            // see if we got a good message\r
+            //return _have_new_message();\r
+            return 1;\r
+        }\r
+        // we got a bad message, ignore it\r
+        return 0;\r
+    }\r
+\r
+    // the first term determines the sentence type\r
+    if (pnmea->term_number == 0) {\r
+        /*\r
+          The first two letters of the NMEA term are the talker\r
+          ID. The most common is 'GP' but there are a bunch of others\r
+          that are valid. We accept any two characters here.\r
+         */\r
+        if (pnmea->term[0] < 'A' || pnmea->term[0] > 'Z' ||\r
+            pnmea->term[1] < 'A' || pnmea->term[1] > 'Z') {\r
+            pnmea->sentence_type = GPS_SENTENCE_OTHER;\r
+            return 0;\r
+        }\r
+               switch(pnmea->term[1])\r
+               {\r
+                       case 'B':\r
+                               pnmea->location_system = BDS_Bli;\r
+                               break;\r
+                       case 'L':\r
+                               pnmea->location_system = GLONASS_L1OF;\r
+                               break;\r
+                       case 'P':\r
+                               pnmea->location_system = GPS_L1C_A;\r
+                               break;\r
+                       case 'Q':\r
+                               pnmea->location_system = QZSS_L1C_A;\r
+                               break;\r
+                       case 'A':\r
+                               pnmea->location_system = Galileo_E1C;\r
+                               break;\r
+                       case 'N':\r
+                               pnmea->location_system = GNSS_;\r
+                               break;\r
+                       default:\r
+                               pnmea->location_system = MAX_LOCATION_SYSTEM;\r
+                               break;\r
+               }\r
+\r
+\r
+        const char *term_type = &pnmea->term[2];\r
+        if (strcmp(term_type, "RMC") == 0) {\r
+            pnmea->sentence_type = GPS_SENTENCE_RMC;\r
+        } else if (strcmp(term_type, "GGA") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_GGA;\r
+        } else if (strcmp(term_type, "GSV") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_GSV;\r
+        } else if (strcmp(term_type, "GSA") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_GSA;\r
+        } else if (strcmp(term_type, "GLL") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_GLL;\r
+        } else if (strcmp(term_type, "ZDA") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_ZDA;\r
+        } else if (strcmp(term_type, "TH000") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_TH000;\r
+        } else if (strcmp(term_type, "TH001") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_TH001;\r
+        } else if (strcmp(term_type, "TH002") == 0) {;\r
+            pnmea->sentence_type = GPS_SENTENCE_TH002;\r
+        }else if (strcmp(term_type, "VTG") == 0) {\r
+            pnmea->sentence_type = GPS_SENTENCE_VTG;\r
+            // VTG may not contain a data qualifier, presume the solution is good\r
+            // unless it tells us otherwise.\r
+            pnmea->gps_data_good = 1;\r
+        } else {\r
+            pnmea->sentence_type = GPS_SENTENCE_OTHER;\r
+        }\r
+        return 0;\r
+    }\r
+       \r
+       \r
+       unsigned char startindex;\r
+    // 32 = RMC, 64 = GGA, 96 = VTG\r
+    if (pnmea->sentence_type != GPS_SENTENCE_OTHER && pnmea->term[0]) {\r
+        switch (pnmea->sentence_type + pnmea->term_number) {\r
+        // operational status\r
+        //\r
+        case GPS_SENTENCE_RMC + 2: // validity (RMC)\r
+            pnmea->gps_data_good = pnmea->term[0] == 'A';\r
+            break;\r
+        case GPS_SENTENCE_GGA + 6: // Fix data (GGA)\r
+            pnmea->gps_data_good = pnmea->term[0] > '0';\r
+            pnmea->new_quality_indicator = pnmea->term[0] - '0';\r
+            break;\r
+        case GPS_SENTENCE_VTG + 9: // validity (VTG) (we may not see this field)\r
+            pnmea->gps_data_good = pnmea->term[0] != 'N';\r
+            break;\r
+        case GPS_SENTENCE_GGA + 7: // satellite count (GGA)\r
+            pnmea->new_satellite_count = (unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+            break;\r
+        case GPS_SENTENCE_GGA + 8: // HDOP (GGA)\r
+            pnmea->new_hdop = (unsigned short)(string_to_float((const char*)pnmea->term, (void*)0)*100);\r
+            break;\r
+               case GPS_SENTENCE_GSV + 1: // GSV numMsg 2 GSV 语句总数。\r
+                       pnmea->gsvpagecount =  (unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv pagecount %d\r\n",pnmea->gsvpagecount );\r
+                       pnmea->gps_data_good=1;\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 2: // GSV msgNo GSV 语句编号。\r
+                       pnmea->gsvpage =  (unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv gsvpage %d\r\n",pnmea->gsvpage );\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 3: // GSV numSV 可见卫星总数。\r
+                       {\r
+                               pnmea->starcount =  (unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                               printf("gsv starcount %d\r\n",pnmea->starcount );\r
+                               if (pnmea->gsvpage==pnmea->gsvpagecount)\r
+                               {       //最后一页星的数量\r
+                                       //非最后一页的中间任意一页一定是4颗星\r
+                                       pnmea->gsvpage_starcount = pnmea->starcount - (pnmea->gsvpagecount -1) * 4;   \r
+                               }else\r
+                               {\r
+                                       pnmea->gsvpage_starcount =  4;   \r
+                               }\r
+                       }\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 4: // GSV svid  卫星编号\r
+                       startindex=4*(pnmea->gsvpage-1);\r
+                       pnmea->starts[0].starID=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 0 startindex %d startid %d\r\n",startindex ,pnmea->starts[0].starID);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 7: // GSV cn0 载噪比:0~99,无效时为空\r
+                       startindex=4*(pnmea->gsvpage-1);\r
+                       pnmea->starts[0].snr=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 0 startindex %d snr %d\r\n",startindex ,pnmea->starts[0].snr);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 8: // GSV svid  卫星编号 N*4\r
+                       startindex=4*(pnmea->gsvpage-1)+1;\r
+                       if (1>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[1].starID=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 1 startindex %d startid %d\r\n",startindex ,pnmea->starts[1].starID);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 11: // GSV cn0 载噪比:0~99,无效时为空\r
+                       startindex=4*(pnmea->gsvpage-1)+1;\r
+                       if (1>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[1].snr=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 1 startindex %d snr %d\r\n",startindex ,pnmea->starts[1].snr);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 12: // GSV svid  卫星编号\r
+                       startindex=4*(pnmea->gsvpage-1)+2;\r
+                       if (2>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[2].starID=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 2 startindex %d startid %d\r\n",startindex ,pnmea->starts[2].starID);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 15: // GSV cn0 载噪比:0~99,无效时为空\r
+                       startindex=4*(pnmea->gsvpage-1)+2;\r
+                       if (2>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[2].snr=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 2 startindex %d snr %d\r\n",startindex ,pnmea->starts[2].snr);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 16: // GSV svid  卫星编号\r
+                       startindex=4*(pnmea->gsvpage-1)+3;\r
+                       if (3>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[3].starID=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 3 startindex %d startid %d\r\n",startindex ,pnmea->starts[3].starID);\r
+                       break;\r
+               case GPS_SENTENCE_GSV + 19: // GSV cn0 载噪比:0~99,无效时为空\r
+                       startindex=4*(pnmea->gsvpage-1)+3;\r
+                       if (3>=pnmea->gsvpage_starcount) break;\r
+                       pnmea->starts[3].snr=(unsigned char)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("gsv 3 startindex %d snr %d\r\n",startindex ,pnmea->starts[3].snr);\r
+                       break;\r
+        // time and date\r
+        //\r
+        case GPS_SENTENCE_RMC + 1: // Time (RMC)\r
+        case GPS_SENTENCE_GGA + 1: // Time (GGA)\r
+            pnmea->new_time = (unsigned int)(string_to_float((const char*)pnmea->term, (void*)0)*1000);  /* ms */ \r
+            break;\r
+        case GPS_SENTENCE_RMC + 9: // Date (GPRMC)\r
+            pnmea->new_date = (unsigned int)sring_to_int((const char*)pnmea->term, (void*)0);\r
+            break;\r
+\r
+        // location\r
+        //\r
+        case GPS_SENTENCE_RMC + 3: // Latitude\r
+        case GPS_SENTENCE_GGA + 2:\r
+            pnmea->new_latitude = string_to_float((const char*)pnmea->term, (void*)0)/100.0;   //dd.mmmm\r
+                       pnmea->new_latitude = (float)( ((unsigned int)pnmea->new_latitude) + (pnmea->new_latitude-((unsigned int)pnmea->new_latitude))/0.6 );  //deg\r
+            break;\r
+        case GPS_SENTENCE_RMC + 4: // N/S\r
+        case GPS_SENTENCE_GGA + 3:\r
+            if (pnmea->term[0] == 'S')\r
+                pnmea->new_latitude = -pnmea->new_latitude;\r
+            break;\r
+        case GPS_SENTENCE_RMC + 5: // Longitude\r
+        case GPS_SENTENCE_GGA + 4:\r
+            pnmea->new_longitude = string_to_float((const char*)pnmea->term, (void*)0)/100.0;  //dd.mmmmmm   \r
+                       pnmea->new_longitude = (float)(( (unsigned int)pnmea->new_longitude) + (pnmea->new_longitude-((unsigned int)pnmea->new_longitude))/0.6);  //deg\r
+            break;\r
+        case GPS_SENTENCE_RMC + 6: // E/W\r
+        case GPS_SENTENCE_GGA + 5:\r
+            if (pnmea->term[0] == 'W')\r
+                pnmea->new_longitude = -pnmea->new_longitude;\r
+            break;\r
+        case GPS_SENTENCE_GGA + 9: // Altitude (GPGGA)\r
+            pnmea->new_altitude = (int)(string_to_float((const char*)pnmea->term, (void*)0)*100);  /* cm */ \r
+            break;\r
+\r
+        // course and speed\r
+        //\r
+        //case GPS_SENTENCE_RMC + 7: // Speed (GPRMC)\r
+        //case GPS_SENTENCE_VTG + 5: // Speed (VTG)\r
+        //    pnmea->new_speed = (_parse_decimal_100(pnmea->term) * 514) / 1000;       // knots-> m/sec, approximiates * 0.514\r
+        //    break;\r
+        \r
+        case GPS_SENTENCE_VTG + 7: // Speed (VTG)\r
+               pnmea->new_speed = string_to_float((const char*)pnmea->term, (void*)0);       //km/h\r
+           break;\r
+        \r
+        // case GPS_SENTENCE_HDT + 1: // Course (HDT)\r
+               //       pnmea->new_gps_yaw = string_to_float((const char*)pnmea->term, (void*)0);\r
+               //       break;\r
+        case GPS_SENTENCE_RMC + 8: // Course (GPRMC)\r
+        case GPS_SENTENCE_VTG + 1: // Course (VTG)\r
+            pnmea->new_course = string_to_float((const char*)pnmea->term, (void*)0);\r
+            break;\r
+               case GPS_SENTENCE_TH000 + 1:/*VGA 档位(第 2 字段)描述了当前的信号增益档位,有效范围为2~13,正常信号时,其档位值为 7~9;如果档位值显示为 2,说明可能存在强干扰,导致增益饱和;如果档位值为 13,说明信号特别弱,可能射频链路增益不足*/\r
+                       pnmea->th000_signal_vga = (unsigned int)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       printf("th000 signal_vga %d,%s\n",pnmea->th000_signal_vga,pnmea->term);\r
+                       pnmea->gps_data_good = 1;\r
+            break;\r
+               case GPS_SENTENCE_TH001 + 4:\r
+               /*$PNTH001,0.000000,0.00,0.00,0.00,1,0,0*2E*/\r
+                       /***PNTH001 语句,定位质量评估因子(第 5 字段)显示了当前评估出的定位精度,定位过程中,有效范围为 3~200,值越小定位精度越好。*/\r
+                       pnmea->th001_quality = string_to_float((const char*)pnmea->term, (void*)0);\r
+                       // printf("th001 quality 5 %f,%s\n",pnmea->th001_quality,pnmea->term);\r
+                       break;\r
+               case GPS_SENTENCE_TH001 + 5:\r
+                       /**PNTH001 语句,定位错误码(第 6 字段) 1:表示卫星跟踪数量不足,不满足定位条件;2:表示有效星历数量不足,不满足定位条件;3:定位精度不足,定位结果被拦截。*/\r
+                       pnmea->th001_errorcode = (unsigned int)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       // printf("th001 th001_errorcode 6 %d,%s\n",pnmea->th001_errorcode,pnmea->term);\r
+                       break;\r
+               case GPS_SENTENCE_TH001 + 6:\r
+                       /**PNTH001 语句,实际跟踪卫星数量(第 7 字段)显示了当前实际跟踪的卫星数量。**/\r
+                       pnmea->th001_trace_star_count = (unsigned int)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       // printf("th001 th001_trace_star_count 7 %d,%s\n",pnmea->th001_trace_star_count,pnmea->term);\r
+                       break;\r
+               case GPS_SENTENCE_TH001 + 7:\r
+                       /**PNTH001 语句,有效星历数量(第 8 字段)显示了当前有效的星历数量*/\r
+                       pnmea->th001_valid_star_count = (unsigned int)sring_to_int((const char*)pnmea->term, (void*)0);\r
+                       // printf("th001 th001_valid_star_count 8 %d,%s\n",pnmea->th001_valid_star_count,pnmea->term);\r
+                       pnmea->gps_data_good = 1;\r
+                       break;\r
+        }\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+/* 多次方 */\r
+static int int_pow(int value, unsigned int count)\r
+{\r
+       int v = 1;\r
+       \r
+       while(count--)\r
+               v = v*value;\r
+       return v;\r
+} \r
+\r
+static double double_pow(double value, unsigned int count)\r
+{\r
+       double v = 1;\r
+       \r
+       while(count--)\r
+               v = v*value;\r
+       return v;\r
+}\r
+\r
+/* 检查字符串是否为数字字符串,是返回1,否则返回0 */ \r
+static unsigned char string_check_digital(const char* pc)\r
+{\r
+       const char* p;\r
+       if((void*)0==pc || '\0'==*pc) return 0; \r
+       \r
+       p = pc;\r
+       while('\0'!=*p)\r
+       {\r
+               if(!IS_DIGITAL(*p)) return 0;\r
+               ++p;\r
+       }\r
+       return 1;       \r
+} \r
+\r
+/* 数字字符串处理函数,识别符号并且不检查溢出\r
+*  如果是小数,则只返回整数部分,如果转换出错,返回0 \r
+*  传入参数: 原始字符串, 转换成功标志 0-错误  1-正确 \r
+*/\r
+static int sring_to_int(const char* pstr, unsigned char* b)\r
+{\r
+       char nega = 1;    /* 负数为1, 正数为1 */ \r
+       const char* psrc = (void*)0;\r
+       int value = 0;\r
+       \r
+       if( (void*)0==pstr ) \r
+       {\r
+               *b = 0; \r
+               return 0;\r
+       }\r
+       \r
+       if( !string_check_digital(pstr) ) \r
+       {\r
+               *b = 0; \r
+               return 0;\r
+       }\r
+       \r
+       psrc = pstr;\r
+       if('-'==*psrc)  /* 符号位 */ \r
+       {\r
+               nega = -1;\r
+               ++psrc;\r
+       }       \r
+       \r
+       while('\0'!=*psrc)\r
+       {\r
+               if('.'==*psrc || '-'==*psrc ) return value;\r
+               value = 10*value + CHAR_TO_DIGITAL(*psrc);      \r
+               ++psrc;\r
+       } \r
+       if( -1==nega )\r
+               value = -value;\r
+               \r
+       return value;\r
+} \r
+\r
+/* 字符串转换成小数 */\r
+static double string_to_float(const char* pstr, unsigned char* b) \r
+{\r
+       char nega = 1;    /* 负数为1, 正数为1 */ \r
+       const char* psrc = (void*)0;\r
+       double value = 0.0;\r
+       double lvalue = 0.0; /* 小数点后面数字 */ \r
+       unsigned char dotflag = 0;  /* 小数点标记  1为之前出现过小数点 */ \r
+       unsigned char j = 0;\r
+       \r
+       if( (void*)0==pstr ) \r
+       {\r
+               *b = 0; \r
+               return 0;\r
+       }\r
+       \r
+       psrc = pstr;\r
+       if( !string_check_digital(psrc) ) \r
+       {\r
+               *b = 0; \r
+               return 0;\r
+       }\r
+       \r
+       if('-'==*psrc)  /* 符号位 */ \r
+       {\r
+               nega = -1;\r
+               ++psrc;\r
+       }       \r
+       \r
+       while('\0'!=*psrc)\r
+       {\r
+               if('-'==*psrc ) return value;\r
+               if('.'==*psrc ) \r
+               {\r
+                       dotflag = 1;\r
+                       ++psrc;\r
+                       continue;\r
+               }\r
+               \r
+               if(!dotflag) \r
+               {\r
+                       value = 10*value + CHAR_TO_DIGITAL(*psrc);      \r
+               }else\r
+               {\r
+                       ++j;\r
+                       lvalue = lvalue + CHAR_TO_DIGITAL(*psrc)*double_pow(0.1, j);\r
+               }       \r
+               ++psrc;\r
+       } \r
+       if( -1==nega )\r
+               value = -(value+lvalue);\r
+       else value = value+lvalue;\r
+               \r
+       return value;\r
+}\r
+\r
+/* 浮点数转换为字符串,包括整数转换为字符串 \r
+*  intgr指定整数位个数,dec指定小数位个数 \r
+*  自动去除前面的0,小数点后面的0不会舍去 \r
+*/ \r
+static unsigned char float_to_string(double value, char* pdest, unsigned int intgr, unsigned int dec)\r
+{\r
+       char* pstr = (void*)0;\r
+       double fvalue = 0.0;\r
+       char c = 0;\r
+       unsigned int tvalue = 0;\r
+       unsigned char zeroflag = 0;\r
+       unsigned int tm = 0;\r
+       \r
+       if( (void*)0==pdest || 0==intgr ) return 0;\r
+       \r
+       if(dec>9) dec = 9;\r
+       \r
+       if(1==intgr) zeroflag = 1;\r
+       \r
+       pstr = pdest;\r
+       if(value<-0.000000000000000001)\r
+       {\r
+               *pstr = '-';\r
+               ++pstr;\r
+               value = -value;\r
+       }\r
+       \r
+       tvalue = (int)value%int_pow(10,intgr);\r
+       while(intgr)\r
+       {\r
+               c = DIGITAL_TO_CHAR(tvalue/int_pow(10,intgr-1));\r
+               \r
+               if( !zeroflag  && '0'==c )\r
+               {\r
+                       tvalue = tvalue%int_pow(10,intgr-1);\r
+                       --intgr;\r
+                       continue;\r
+               }\r
+               \r
+               zeroflag = 1;\r
+               \r
+               *pstr = c;\r
+               tvalue = tvalue%int_pow(10,intgr-1);\r
+               --intgr;\r
+               ++pstr;\r
+       }\r
+       \r
+       if( !zeroflag ) *pstr++ = '0';\r
+               \r
+               \r
+       /* 如果小数位数为0,则返回整数部分 */\r
+       if(0==dec)\r
+       {\r
+               *pstr = '\0';\r
+               return 1;               \r
+       }\r
+       \r
+       *pstr++ = '.';  \r
+       tm = (unsigned int)int_pow(10,dec);\r
+       tvalue = (unsigned int)( ( (unsigned int)((value-(unsigned int)value)*tm) )%tm );\r
+       while(dec)\r
+       {\r
+               tm = int_pow(10,dec-1);\r
+               *pstr = DIGITAL_TO_CHAR(tvalue/tm);\r
+               tvalue = tvalue%tm;\r
+               --dec;\r
+               ++pstr;\r
+       }\r
+       *pstr = '\0';\r
+       return 1;       \r
+} \r
+\r
+\r
+/* 整数转换成字符串,内部其实调用了 float_to_string */\r
+static unsigned char int_to_string(int value, char* pdest, unsigned int intgr) \r
+{\r
+       return float_to_string((double)value, pdest, intgr,0);\r
+}\r
+\r
+/* 时间处理  传入参数为日月年和毫秒*/ \r
+static int make_date_time(gps_data_t* pdata, unsigned int date, unsigned int time)\r
+{\r
+       \r
+       unsigned char year, mon, day, hour, min, sec;\r
+    unsigned short int msec;\r
+    unsigned int v,ret;\r
+    char rmon;\r
+    \r
+    if((void*)0==pdata) return 0;\r
+\r
+    year = date % 100;\r
+    mon  = (date / 100) % 100;\r
+    day  = date / 10000;\r
+    \r
+    pdata->date_time.year = year;\r
+    pdata->date_time.month = mon;\r
+    pdata->date_time.day = day;\r
+\r
+    v = time;\r
+    msec = v % 1000; v /= 1000;\r
+    sec  = v % 100; v /= 100;\r
+    min  = v % 100; v /= 100;\r
+    hour = v % 100; v /= 100;\r
+\r
+    rmon = mon - 2;\r
+    if (0 >= rmon) {    \r
+        rmon += 12;\r
+        year -= 1;\r
+    }\r
+\r
+    // get time in seconds since unix epoch\r
+    ret = (year/4) - (GPS_LEAPSECONDS_MILLIS / 1000UL) + 367*rmon/12 + day;\r
+    ret += year*365 + 10501;\r
+    ret = ret*24 + hour;\r
+    ret = ret*60 + min;\r
+    ret = ret*60 + sec;\r
+\r
+    // convert to time since GPS epoch\r
+    ret -= 272764785UL;\r
+\r
+    // get GPS week and time\r
+    pdata->date_time.week = ret / AP_SEC_PER_WEEK;\r
+    pdata->date_time.hour=hour;\r
+       pdata->date_time.minute=min;\r
+       pdata->date_time.second=sec;\r
+    return 1;\r
+} \r
+char* get_gps_status_str(gps_status status)\r
+{\r
+       char* ret="NO_GPS";\r
+       switch(status)\r
+       {\r
+               case NO_GPS:\r
+                       ret = "无卫星";\r
+                       break;\r
+               case NO_FIX:\r
+                       ret = "接收到GPS信息,但没有定位";\r
+                       break;\r
+               case GPS_OK_FIX_2D:\r
+                       ret = "2D定位";\r
+                       break;\r
+               case GPS_OK_FIX_3D:\r
+                       ret = "3D定位";\r
+                       break;\r
+               case GPS_OK_FIX_3D_DGPS:\r
+                       ret = "优于3D定位";\r
+                       break;\r
+               case GPS_OK_FIX_3D_RTK_FLOAT:\r
+                       ret = "RTK浮点解状态";\r
+                       break;\r
+               case GPS_OK_FIX_3D_RTK_FIXED:\r
+                       ret = "RTK固定解状态";\r
+                       break;\r
+               \r
+               default:\r
+                       ret = "未知卫星状态";\r
+       }\r
+       return ret;\r
+}\r
+\r
+char* get_gps_sentence_type_str(sentence_types sentencetype)\r
+{\r
+   switch(sentencetype)\r
+   {\r
+               case GPS_SENTENCE_RMC:\r
+                       return "RMC字段 推荐的最少专用导航数据。";\r
+               case GPS_SENTENCE_GGA:\r
+                       return "GGA字段 接收机定位数据。";\r
+               case GPS_SENTENCE_GSV:\r
+                       return "GSV字段 可见卫星数据。";\r
+               case GPS_SENTENCE_GSA:\r
+                       return "GSA字段 有效卫星与精度因子数据。";\r
+               case GPS_SENTENCE_GLL:\r
+                       return "GLL字段 接收机地理位置数据。";\r
+               case GPS_SENTENCE_VTG:\r
+                       return "VTG字段 对地速度与航向数据。";\r
+               // case GPS_SENTENCE_HDT:\r
+               //      return "HDT字段";\r
+               case GPS_SENTENCE_ZDA:\r
+                       return "ZDA字段 时间与日期数据";\r
+               case GPS_SENTENCE_TH000:\r
+                       return "接收机前端增益信息。";\r
+               case GPS_SENTENCE_TH001:\r
+                       return "接收机定位质量信息。";\r
+               case GPS_SENTENCE_TH002:\r
+                       return "接收机功耗模式信息。";\r
+               case GPS_SENTENCE_OTHER:\r
+                       return "其他字段";\r
+               default:\r
+                       return "unknown_type";\r
+   } \r
+}\r
+char* get_gps_location_system_str(location_system_t lsystem)\r
+{\r
+switch(lsystem)\r
+   {\r
+               case GNSS_:\r
+                       return "全球导航卫星系统";\r
+               case GPS_L1C_A:\r
+                       return "全球定位系统";\r
+               case GLONASS_L1OF:\r
+                       return "全球导航卫星系统(俄)";\r
+               case Galileo_E1C:\r
+                       return "伽利略卫星定位系统";\r
+               case BDS_Bli:\r
+                       return "北斗卫星导航系统";\r
+               case QZSS_L1C_A:\r
+                       return "准天顶卫星系统";\r
+               default:\r
+                       return "未知定位系统或自定义系统指令";\r
+   } \r
+}\r
+\r
+void dump_nmea_str(gps_nmea_t *nmeadata)\r
+{\r
+\r
+       printf("\r\n");\r
+       printf("%s\r\n",get_gps_location_system_str(nmeadata->location_system));\r
+       printf("%s\r\n",get_gps_sentence_type_str(nmeadata->sentence_type));\r
+       printf("gps_data_good %d\r\n",nmeadata->gps_data_good);\r
+\r
+       printf("\r\n");\r
+}\r
+#define DUMP_BUF_SIZE 1024\r
+void dump_location_data_to_buf(gps_data_t *locationdata,char* buf,int max_buflen)\r
+{\r
+       \r
+       char *tmpbuf=(char*)malloc(DUMP_BUF_SIZE);\r
+       if (tmpbuf == NULL) return;\r
+#ifndef NOUTILS\r
+       memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+       sprintf_s(tmpbuf,DUMP_BUF_SIZE,"20%02d-%02d-%02d %02d:%02d:%02d,\n定位状态(%s)\n",\r
+    locationdata->date_time.year,\r
+    locationdata->date_time.month,\r
+    locationdata->date_time.day,\r
+    locationdata->date_time.hour,\r
+    locationdata->date_time.minute,\r
+    locationdata->date_time.second,\r
+    get_gps_status_str(locationdata->status)\r
+    );\r
+       strcat_s(buf,max_buflen,tmpbuf);\r
+       memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+       sprintf_s(tmpbuf,DUMP_BUF_SIZE,"可见卫星颗数(%d),\n坐标(%f,%f,%d),\nhdop(%d),vdop(%d)\n",\r
+       locationdata->num_sats,\r
+    locationdata->location.lat,\r
+    locationdata->location.lng,\r
+    locationdata->location.alt,\r
+       locationdata->hdop,\r
+       locationdata->vdop\r
+    );\r
+       strcat_s(buf,max_buflen,tmpbuf);\r
+       sprintf_s(tmpbuf,DUMP_BUF_SIZE,"xx卫星[卫星数](strid,snr):\n");\r
+       if (locationdata->starcountP>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"GPS_L1C_A[%d]",\r
+               locationdata->starcountP);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsP[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsP[i].starID,\r
+                                       locationdata->startsP[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+       }\r
+       if (locationdata->starcountB>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"BDS_Bli[%d]",\r
+               locationdata->starcountB);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsB[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsB[i].starID,\r
+                                       locationdata->startsB[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+       }\r
+       if (locationdata->starcountN>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"GNSS[%d]",\r
+               locationdata->starcountN);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsN[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsN[i].starID,\r
+                                       locationdata->startsN[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+       }\r
+       if (locationdata->starcountL>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"GLONASS_L1OF[%d]",\r
+               locationdata->starcountL);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsL[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsL[i].starID,\r
+                                       locationdata->startsL[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+       }\r
+       if (locationdata->starcountQ>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"QZSS_L1C_A[%d]",\r
+               locationdata->starcountQ);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsQ[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsQ[i].starID,\r
+                                       locationdata->startsQ[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+       }\r
+       if (locationdata->starcountA>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"Galileo_E1C[%d]",\r
+               locationdata->starcountA);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsA[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",(%d,%d)",\r
+                                       locationdata->startsA[i].starID,\r
+                                       locationdata->startsA[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+               strcat_s(buf,max_buflen,"\n");\r
+\r
+       }\r
+       if ((locationdata->starcountA+locationdata->starcountB+locationdata->starcountL+locationdata->starcountN+locationdata->starcountP+locationdata->starcountQ) == 0)\r
+       {\r
+               strcat_s(buf,max_buflen,"无卫星数据\n");\r
+       }\r
+       memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+       sprintf_s(tmpbuf,DUMP_BUF_SIZE,"定位质量信息,信号增益(%d),失败原因(%s),精度(%f),跟踪星(%d),有效星(%d)\n",\r
+               locationdata->th000_signal_vga,\r
+               locationdata->th001_errorcode==1?"跟踪数量不足":(locationdata->th001_errorcode==2?"有效星历数量不足":(locationdata->th001_errorcode==3?"定位精度不足":"无")),\r
+               locationdata->th001_quality,\r
+               locationdata->th001_trace_star_count,\r
+               locationdata->th001_valid_star_count\r
+       );\r
+       strcat_s(buf,max_buflen,tmpbuf);\r
+       \r
+#else\r
+       strcat(buf,"\r\n");\r
+       memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+       sprintf(tmpbuf,"20%02d-%02d-%02d %02d:%02d:%02d,\r\n定位状态(%s)\r\n",\r
+    locationdata->date_time.year,\r
+    locationdata->date_time.month,\r
+    locationdata->date_time.day,\r
+    locationdata->date_time.hour,\r
+    locationdata->date_time.minute,\r
+    locationdata->date_time.second,\r
+    get_gps_status_str(locationdata->status)\r
+    );\r
+       strcat(buf,tmpbuf);\r
+\r
+       memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+       sprintf(tmpbuf,"可见卫星颗数(%d),\r\n坐标(%f,%f,%d),\r\nhdop(%d),vdop(%d)\r\n",\r
+       locationdata->num_sats,\r
+    locationdata->location.lat,\r
+    locationdata->location.lng,\r
+    locationdata->location.alt,\r
+       locationdata->hdop,\r
+       locationdata->vdop\r
+    );\r
+       strcat(buf,tmpbuf);\r
+       \r
+       sprintf(tmpbuf,"xx卫星[卫星数](strid,snr):\n");\r
+       if (locationdata->starcountP>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"GPS_L1C_A[%d]",\r
+               locationdata->starcountP);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsP[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsP[i].starID,\r
+                                       locationdata->startsP[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+       }\r
+       if (locationdata->starcountB>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"BDS_Bli[%d]",\r
+               locationdata->starcountB);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsB[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsB[i].starID,\r
+                                       locationdata->startsB[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+       }\r
+       if (locationdata->starcountN>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"GNSS[%d]",\r
+               locationdata->starcountN);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsN[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsN[i].starID,\r
+                                       locationdata->startsN[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+       }\r
+       if (locationdata->starcountL>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"GLONASS_L1OF[%d]",\r
+               locationdata->starcountL);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsL[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsL[i].starID,\r
+                                       locationdata->startsL[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+       }\r
+       if (locationdata->starcountQ>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"QZSS_L1C_A[%d]",\r
+               locationdata->starcountQ);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsQ[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsQ[i].starID,\r
+                                       locationdata->startsQ[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+       }\r
+       if (locationdata->starcountA>0)\r
+       {\r
+               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+               sprintf(tmpbuf,"Galileo_E1C[%d]",\r
+               locationdata->starcountA);\r
+               strcat(buf,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       if (i< locationdata->startsA[i].starID>0)\r
+                       {\r
+                               memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+                               sprintf(tmpbuf,",(%d,%d)",\r
+                                       locationdata->startsA[i].starID,\r
+                                       locationdata->startsA[i].snr);\r
+                               strcat(buf,tmpbuf);\r
+                       }\r
+               }\r
+               strcat(buf,"\n");\r
+\r
+       }\r
+       if ((locationdata->starcountA+locationdata->starcountB+locationdata->starcountL+locationdata->starcountN+locationdata->starcountP+locationdata->starcountQ) == 0)\r
+       {\r
+               strcat(buf,"无卫星数据\n");\r
+       }\r
+\r
+       // strcat(buf,"\r\n");\r
+       memset(tmpbuf,0,DUMP_BUF_SIZE);\r
+       sprintf(tmpbuf,"定位质量信息,失败原因(%s),精度(%f),跟踪星(%d),有效星(%d)\n",\r
+               locationdata->th001_errorcode==1?"跟踪数量不足":(locationdata->th001_errorcode==2?"有效星历数量不足":(locationdata->th001_errorcode==3?"定位精度不足":"无")),\r
+               locationdata->th001_quality,\r
+               locationdata->th001_trace_star_count,\r
+               locationdata->th001_valid_star_count\r
+       );\r
+       strcat(buf,tmpbuf);\r
+#endif\r
+       free(tmpbuf);\r
+}\r
+\r
+void dump_location_data_to_factory(gps_data_t *locationdata,char* buf,int max_buflen)\r
+{\r
+       \r
+       char *tmpbuf=(char*)malloc(DUMP_BUF_SIZE);\r
+       if (tmpbuf == NULL) return;\r
+#ifndef NOUTILS\r
+\r
+       // memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+       // sprintf_s(tmpbuf,DUMP_BUF_SIZE,"xx卫星[卫星数](strid,snr):\n");\r
+\r
+       if (locationdata->starcountP>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"G,%d",\r
+               locationdata->starcountP);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsP[i].starID : %d \n",i,locationdata->startsP[i].starID);\r
+                       if (i< locationdata->startsP[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsP[i].starID,\r
+                                       locationdata->startsP[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"G,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+\r
+       strcat_s(buf,max_buflen,";");\r
+\r
+\r
+       if (locationdata->starcountB>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"B,%d",\r
+               locationdata->starcountB);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsB[i].starID : %d \n",i,locationdata->startsB[i].starID);\r
+                       if (i< locationdata->startsB[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsB[i].starID,\r
+                                       locationdata->startsB[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"B,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+       \r
+       strcat_s(buf,max_buflen,";");\r
+\r
+       if (locationdata->starcountN>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,";N,%d",\r
+               locationdata->starcountN);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsN[i].starID : %d \n",i,locationdata->startsN[i].starID);\r
+                       if (i< locationdata->startsN[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsN[i].starID,\r
+                                       locationdata->startsN[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"N,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+\r
+       strcat_s(buf,max_buflen,";");\r
+\r
+       if (locationdata->starcountL>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"L,%d",\r
+               locationdata->starcountL);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsL[i].starID : %d \n",i,locationdata->startsL[i].starID);\r
+                       if (i< locationdata->startsL[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsL[i].starID,\r
+                                       locationdata->startsL[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"L,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+\r
+       strcat_s(buf,max_buflen,";");\r
+\r
+       if (locationdata->starcountQ>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"Q,%d",\r
+               locationdata->starcountQ);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsQ[i].starID : %d \n",i,locationdata->startsQ[i].starID);\r
+                       if (i< locationdata->startsQ[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsQ[i].starID,\r
+                                       locationdata->startsQ[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"Q,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+\r
+       strcat_s(buf,max_buflen,";");\r
+       \r
+       if (locationdata->starcountA>0)\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"A,%d",\r
+               locationdata->starcountA);\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+               for(int i=0;i<5;i++)\r
+               {\r
+                       // printf("i : %d locationdata->startsA[i].starID : %d \n",i,locationdata->startsA[i].starID);\r
+                       if (i< locationdata->startsA[i].starID>0)\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",%d,%d",\r
+                                       locationdata->startsA[i].starID,\r
+                                       locationdata->startsA[i].snr);\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+                       else\r
+                       {\r
+                               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+                               sprintf_s(tmpbuf,DUMP_BUF_SIZE,",0,0");\r
+                               strcat_s(buf,max_buflen,tmpbuf);\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               memset_s(tmpbuf,DUMP_BUF_SIZE,0,DUMP_BUF_SIZE);\r
+               sprintf_s(tmpbuf,DUMP_BUF_SIZE,"A,0,0,0,0,0,0,0,0,0,0,0");\r
+               strcat_s(buf,max_buflen,tmpbuf);\r
+       }\r
+       strcat_s(buf,max_buflen,";");\r
+#endif\r
+       free(tmpbuf);\r
+}\r
+\r
+\r
+#define MSGBUF_LEN 1024\r
+void dump_location_data(gps_data_t*locationdata)\r
+{\r
+       char* msgbuf=(char*)malloc(MSGBUF_LEN);\r
+       if (msgbuf == NULL) return ;\r
+       dump_location_data_to_buf(locationdata,msgbuf,MSGBUF_LEN);\r
+       printf("%s",msgbuf);\r
+       free(msgbuf);\r
+}\r
+\r
+\r
+\r
+// NMEA0183 g_nmeadata={0};\r
+\r
+// int decode_nmea(char c)\r
+// {\r
+//     if(nmea_decode(&g_nmeadata,c) ) ///调用解析函数\r
+//     {\r
+//         dump_nmea_str(&(g_nmeadata.gpsParse));\r
+//         if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002)\r
+//         {\r
+//             //一组数据最后一条\r
+//             dump_location_data(&(g_nmeadata.gpsData));\r
+//             memset(&g_nmeadata,0,sizeof(g_nmeadata));\r
+//         }\r
+//     } \r
+\r
+\r
+//     return 0;\r
+// }\r
diff --git a/code/sdk/drivers/peripheral/gnss/src/decodenmea.c b/code/sdk/drivers/peripheral/gnss/src/decodenmea.c
new file mode 100644 (file)
index 0000000..b45018b
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+ * 
+ * gcc decodenmea.c NMEA0183.c -DNOUTILS -I../inc
+ * 
+$GPGGA,,,,,,0,,,,,,,,*66
+
+$GPGLL,,,,,,V,N*64
+
+$GPGSA,A,1,,,,,,,,,,,,,,,*1E
+
+$GPRMC,,V,,,,,,,,,E,N,V*6C
+
+$GPVTG,,T,,M,,N,,K,N*2C
+
+$GPZDA,,,,,00,00*48
+
+$PNTH000,13,,-87,0,,,,,1,1*22
+
+$PNTH001,0.000000,0.00,0.00,300000.00,1,0,0*1D
+
+$PNTH002,,T,0.000000,0,200,0.000000,3,0.000000*4B
+*/
+
+
+#include "NMEA0183.h"
+#include <string.h>
+#include <stdio.h>
+
+char* nmealines[]={
+    "$GPGGA,,,,,,0,,,,,,,,*66\r\n",
+    "$GPGLL,,,,,,V,N*64\r\n",
+    "$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r\n",
+    "$GPRMC,,V,,,,,,,,,E,N,V*6C\r\n",
+    "$GPVTG,,T,,M,,N,,K,N*2C\r\n",
+    "$GPZDA,,,,,00,00*48\r\n",
+    "$PNTH000,13,,-87,0,,,,,1,1*22\r\n",
+    "$PNTH001,0.000000,0.00,0.00,300000.00,1,0,0*1D\r\n",
+    "$PNTH002,,T,0.000000,0,200,0.000000,3,0.000000*4B\r\n"
+};
+char nmealines1[]={
+    "$GBGSV,3,1,11,07,75,129,27,08,68,213,28,10,88,303,26,11,58,322,26,1*7D\r\n"\
+    "$GBGSV,3,2,11,13,51,216,31,25,43,237,33,34,62,011,26,38,81,201,30,1*75\r\n"\
+    "$GBGSV,3,3,11,40,64,107,30,42,17,157,29,43,38,289,27,1*47\r\n"\
+    "$GNGSA,A,3,7,8,10,11,13,25,34,38,40,42,43,,1.5,0.8,1.2,4*39\r\n"\
+    "$GNRMC,102219.00,A,2239.11578,N,11406.59325,E,0.009,,291018,,,D*62\r\n"\
+    "$GNVTG,,T,,M,0.009,N,0.017,K,D*37\r\n"\
+    "$GNGLL,3412.433366,N,10852.420048,E,094345.00,A,A*7F\r\n"\
+    "$GNZDA,094343.00,24,03,2022,00,00*76\r\n"\
+    "$GNGGA,094343.00,3412.431698,N,10852.419449,E,1,22,0.8,378.8,M,,M,,0000*67\r\n"\
+    "$PNTH000,13,,-87,0,,,,,1,1*22\r\n"\
+    "$PNTH001,0.000000,0.00,0.00,300000.00,1,0,0*1D\r\n"\
+    "$PNTH002,,T,0.000000,0,200,0.000000,3,0.000000*4B\r\n"
+};
+
+
+NMEA0183 g_nmeadata={0};
+
+
+char tmpbuf[1024]={0};
+int count = 0;
+int decode_nmea(char c)
+{
+    tmpbuf[count]=c;
+    count++;
+        // printf("%c",c);
+    if(nmea_decode(&g_nmeadata,c) ==1) ///调用解析函数
+    {
+        printf("%s\r\n",tmpbuf);
+        memset(tmpbuf,0,sizeof(tmpbuf));
+        count=0;
+        dump_nmea_str(&(g_nmeadata.gpsParse));
+        if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002)
+        {
+            //一组数据最后一条
+            dump_location_data(&(g_nmeadata.gpsData));
+            memset(&g_nmeadata,0,sizeof(g_nmeadata));
+        }
+    } 
+
+
+    return 0;
+}
+
+int main(int argc, char** argv)
+{
+
+    char tmpc=0;
+    FILE *fp = NULL;
+   fp = fopen("nmealist.txt", "r");
+   while (fread(&tmpc, 1,1, (FILE*)fp))
+   {
+        decode_nmea(tmpc);
+        // printf("%c",tmpc);
+   }
+   fclose(fp);
+    
+}
+
+int main1(int argc, char** argv)
+{
+
+    for(int i=0; i<sizeof(nmealines1); ++i)
+    {
+        decode_nmea(nmealines1[i]);
+    } 
+    
+    return 0;
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/src/gnss_config_array.c b/code/sdk/drivers/peripheral/gnss/src/gnss_config_array.c
new file mode 100644 (file)
index 0000000..a90dd5a
--- /dev/null
@@ -0,0 +1,1035 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2024-2024. All rights reserved.
+ *
+ * Description: config array.
+ * Author: @CompanyNameTag
+ * History:
+ * 2024-01-08, Create file.
+ */
+
+#include "stdint.h"
+#include "stdlib.h"
+#include "errcode.h"
+
+struct cfg_cmd {
+    const uint8_t *content;
+    int len;
+};
+
+/*
+46 49 4c 45 53 20 30 78 30 30 30 39 38 30 30 30 20
+*/
+const uint8_t g_cfg_cmd0[] = {
+    0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x30, 0x78, 0x30, 0x30, 0x30, 0x39, 0x38, 0x30, 0x30, 0x30,
+    0x20
+};
+
+/*
+01 01 fe ef b2 c8 63 c0 99 32 89 ef 02 d9 0d d1 b7 00 00 ef 82 04 47 d0 99 37 e5 00 00 00 00 ef
+02 92 00 ef 22 52 7e dc 9a 13 01 82 80 00 00 ef 02 c4 2c 70 6e 00 00 ef 92 91 27 ef 72 14 39 40
+99 ef b0 82 80 00 00 ef 72 c5 74 ef 92 86 59 37 55 03 20 ef 92 06 5a 37 55 03 20 ef 32 c5 30 40
+98 22 a0 3c 99 00 00 ef 12 c6 76 ef 12 96 21 44 99 08 08 ef e2 92 43 05 66 2a 96 a0 99 00 00 ef
+e2 41 3b 20 99 00 00 ef e2 c1 33 00 00 00 00 ef e2 01 22 20 99 00 00 ef e2 81 16 ef 92 81 25 40
+9e b2 89 ef 92 41 03 5c 9e 13 01 20 99 00 00 ef 82 d1 1c ef a2 41 15 40 9a b2 89 ef 22 c3 05 85
+65 33 06 82 80 00 00 ef a2 d2 07 ef a2 42 6c c4 99 22 a4 a4 99 00 00 ef a2 d2 09 82 80 00 00 ef
+72 06 11 ef 42 c6 14 83 45 25 00 00 00 00 00 ef 32 96 78 3f f9 00 00 ef d2 15 28 ef e2 85 00 93
+06 b0 12 00 00 00 00 ef e2 05 1b ef e2 c5 19 13 06 30 11 00 00 00 00 ef d2 95 19 ef e2 45 35 aa
+86 03 47 00 00 00 00 ef 42 86 60 ef 42 56 78 5c 98 79 71 82 80 00 00 ef c2 c3 16 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 e3 62
+*/
+const uint8_t g_cfg_cmd1[] = {
+    0x01, 0x01, 0xfe, 0xef, 0xb2, 0xc8, 0x63, 0xc0, 0x99, 0x32, 0x89, 0xef, 0x02, 0xd9, 0x0d, 0xd1,
+    0xb7, 0x00, 0x00, 0xef, 0x82, 0x04, 0x47, 0xd0, 0x99, 0x37, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xef,
+    0x02, 0x92, 0x00, 0xef, 0x22, 0x52, 0x7e, 0xdc, 0x9a, 0x13, 0x01, 0x82, 0x80, 0x00, 0x00, 0xef,
+    0x02, 0xc4, 0x2c, 0x70, 0x6e, 0x00, 0x00, 0xef, 0x92, 0x91, 0x27, 0xef, 0x72, 0x14, 0x39, 0x40,
+    0x99, 0xef, 0xb0, 0x82, 0x80, 0x00, 0x00, 0xef, 0x72, 0xc5, 0x74, 0xef, 0x92, 0x86, 0x59, 0x37,
+    0x55, 0x03, 0x20, 0xef, 0x92, 0x06, 0x5a, 0x37, 0x55, 0x03, 0x20, 0xef, 0x32, 0xc5, 0x30, 0x40,
+    0x98, 0x22, 0xa0, 0x3c, 0x99, 0x00, 0x00, 0xef, 0x12, 0xc6, 0x76, 0xef, 0x12, 0x96, 0x21, 0x44,
+    0x99, 0x08, 0x08, 0xef, 0xe2, 0x92, 0x43, 0x05, 0x66, 0x2a, 0x96, 0xa0, 0x99, 0x00, 0x00, 0xef,
+    0xe2, 0x41, 0x3b, 0x20, 0x99, 0x00, 0x00, 0xef, 0xe2, 0xc1, 0x33, 0x00, 0x00, 0x00, 0x00, 0xef,
+    0xe2, 0x01, 0x22, 0x20, 0x99, 0x00, 0x00, 0xef, 0xe2, 0x81, 0x16, 0xef, 0x92, 0x81, 0x25, 0x40,
+    0x9e, 0xb2, 0x89, 0xef, 0x92, 0x41, 0x03, 0x5c, 0x9e, 0x13, 0x01, 0x20, 0x99, 0x00, 0x00, 0xef,
+    0x82, 0xd1, 0x1c, 0xef, 0xa2, 0x41, 0x15, 0x40, 0x9a, 0xb2, 0x89, 0xef, 0x22, 0xc3, 0x05, 0x85,
+    0x65, 0x33, 0x06, 0x82, 0x80, 0x00, 0x00, 0xef, 0xa2, 0xd2, 0x07, 0xef, 0xa2, 0x42, 0x6c, 0xc4,
+    0x99, 0x22, 0xa4, 0xa4, 0x99, 0x00, 0x00, 0xef, 0xa2, 0xd2, 0x09, 0x82, 0x80, 0x00, 0x00, 0xef,
+    0x72, 0x06, 0x11, 0xef, 0x42, 0xc6, 0x14, 0x83, 0x45, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef,
+    0x32, 0x96, 0x78, 0x3f, 0xf9, 0x00, 0x00, 0xef, 0xd2, 0x15, 0x28, 0xef, 0xe2, 0x85, 0x00, 0x93,
+    0x06, 0xb0, 0x12, 0x00, 0x00, 0x00, 0x00, 0xef, 0xe2, 0x05, 0x1b, 0xef, 0xe2, 0xc5, 0x19, 0x13,
+    0x06, 0x30, 0x11, 0x00, 0x00, 0x00, 0x00, 0xef, 0xd2, 0x95, 0x19, 0xef, 0xe2, 0x45, 0x35, 0xaa,
+    0x86, 0x03, 0x47, 0x00, 0x00, 0x00, 0x00, 0xef, 0x42, 0x86, 0x60, 0xef, 0x42, 0x56, 0x78, 0x5c,
+    0x98, 0x79, 0x71, 0x82, 0x80, 0x00, 0x00, 0xef, 0xc2, 0xc3, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0xe3, 0x62
+};
+
+/*
+01 02 fd 00 00 00 00 00 80 09 00 27 00 00 00 09 d0 00 00 31 7d 00 00 e9 09 05 00 79 8e 07 00 e1
+65 07 00 a9 8d 05 00 99 01 08 00 d1 13 05 00 09 16 04 00 d1 f0 02 00 21 f1 02 00 d1 5a 04 00 39
+72 03 00 09 70 03 00 e9 a5 06 00 91 b4 07 00 71 b5 07 00 f1 b6 07 00 11 b8 07 00 91 07 08 00 a9
+0a 08 00 71 14 08 00 71 fb 07 00 59 71 06 00 c9 ec 06 00 61 eb 06 00 f1 eb 06 00 31 16 03 00 29
+46 03 00 41 48 03 00 99 b0 03 00 d1 ab 03 00 41 a9 03 00 31 a9 03 00 81 b2 03 00 59 a9 03 00 79
+42 03 00 e9 39 03 00 e9 cf 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 98 ef f0 66 ee 37 25 00 40 83 55 c5 54 85 89 89
+c5 23 1a 05 60 23 ae 01 26 99 45 23 a0 b1 3c 13 85 81 f7 05 46 23 13 c5 00 23 17 c5 00 23 1b b5
+00 20 98 00 00 00 00 c0 99 32 89 ae 84 2a 84 ef f0 56 9b 22 85 a6 85 4a 86 ef 30 37 e4 2a 84 ef
+f0 16 98 22 85 a0 99 00 00 00 00 37 55 03 20 03 45 c5 d9 b7 a5 09 00 83 c5 c5 0b 4d 8d 11 cd 7b
+25 00 81 0b 4f 05 03 7b 26 09 f6 37 05 23 00 13 05 e5 17 b7 b5 02 16 05 a0 7b 25 00 81 09 46 7b
+66 cf 2e 0b 47 05 03 7b 26 09 f6 37 05 23 00 13 05 e5 17 b7 b5 02 14 93 85 25 4c 6f 60 17 af 82
+80 00 00 37 55 03 20 03 45 c5 d9 b7 a5 09 00 83 c5 c5 0b 7d 15 33 35 a0 00 fd 15 b3 35 b0 00 6d
+8d 0d ed 37 f5 01 20 93 05 85 ad 03 85 65 00 7b 26 00 81 85 46 d4 c9 05 05 23 83 a5 00 0b 41 16
+03 08 92 fb 26 09 f6 37 05 23 00 13 05 e5 17 b7 b5 02 20 93 85 25 4c 6f 60 d7 ae 7b 25 00 81 09
+46 7b 66 cf 2e 0b 47 05 03 7b 26 09 f6 37 05 23 00 13 05 e5 17 b7 b5 02 23 93 85 25 4c 6f 60 f7
+a6 82 80 00 00 00 00 7d 15 08 91 8b 54 05 02 03 45 86 00 0b 15 05 01 33 35 b0 00 82 80 a3 15 06
+00 93 05 d6 00 21 a0 1a 12 93 05 b6 00 05 45 82 11 82 80 00 00 00 00 83 45 25 00 8b dc 05 06 05
+46 b3 15 b6 00 93 f5 55 02 95 c1 83 05 05 07 fd 15 8c 91 8b d4 05 02 83 45 d5 03 13 f6 35 00 19
+ce 5e 1d 39 a0 3e 1d a3 1e 05 02 39 a0 83 45 d5 03 93 f5 75 0e a3 0e b5 02 01 45 82 80 83 45 c5
+03 e5 fd 03 45 b5 03 13 35 15 00 82 80 00 00 40 99 2a 84 83 44 25 00 ef c0 89 82 0b 0a 15 01 03
+25 44 09 83 25 44 08 83 06 04 07 a3 0c 04 06 13 06 15 00 03 25 04 0b fd 16 94 92 23 2a c4 08 8b
+df 06 02 ef 34
+*/
+const uint8_t g_cfg_cmd2[] = {
+    0x01, 0x02, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x27, 0x00, 0x00, 0x00, 0x09,
+    0xd0, 0x00, 0x00, 0x31, 0x7d, 0x00, 0x00, 0xe9, 0x09, 0x05, 0x00, 0x79, 0x8e, 0x07, 0x00, 0xe1,
+    0x65, 0x07, 0x00, 0xa9, 0x8d, 0x05, 0x00, 0x99, 0x01, 0x08, 0x00, 0xd1, 0x13, 0x05, 0x00, 0x09,
+    0x16, 0x04, 0x00, 0xd1, 0xf0, 0x02, 0x00, 0x21, 0xf1, 0x02, 0x00, 0xd1, 0x5a, 0x04, 0x00, 0x39,
+    0x72, 0x03, 0x00, 0x09, 0x70, 0x03, 0x00, 0xe9, 0xa5, 0x06, 0x00, 0x91, 0xb4, 0x07, 0x00, 0x71,
+    0xb5, 0x07, 0x00, 0xf1, 0xb6, 0x07, 0x00, 0x11, 0xb8, 0x07, 0x00, 0x91, 0x07, 0x08, 0x00, 0xa9,
+    0x0a, 0x08, 0x00, 0x71, 0x14, 0x08, 0x00, 0x71, 0xfb, 0x07, 0x00, 0x59, 0x71, 0x06, 0x00, 0xc9,
+    0xec, 0x06, 0x00, 0x61, 0xeb, 0x06, 0x00, 0xf1, 0xeb, 0x06, 0x00, 0x31, 0x16, 0x03, 0x00, 0x29,
+    0x46, 0x03, 0x00, 0x41, 0x48, 0x03, 0x00, 0x99, 0xb0, 0x03, 0x00, 0xd1, 0xab, 0x03, 0x00, 0x41,
+    0xa9, 0x03, 0x00, 0x31, 0xa9, 0x03, 0x00, 0x81, 0xb2, 0x03, 0x00, 0x59, 0xa9, 0x03, 0x00, 0x79,
+    0x42, 0x03, 0x00, 0xe9, 0x39, 0x03, 0x00, 0xe9, 0xcf, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+    0x98, 0xef, 0xf0, 0x66, 0xee, 0x37, 0x25, 0x00, 0x40, 0x83, 0x55, 0xc5, 0x54, 0x85, 0x89, 0x89,
+    0xc5, 0x23, 0x1a, 0x05, 0x60, 0x23, 0xae, 0x01, 0x26, 0x99, 0x45, 0x23, 0xa0, 0xb1, 0x3c, 0x13,
+    0x85, 0x81, 0xf7, 0x05, 0x46, 0x23, 0x13, 0xc5, 0x00, 0x23, 0x17, 0xc5, 0x00, 0x23, 0x1b, 0xb5,
+    0x00, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x99, 0x32, 0x89, 0xae, 0x84, 0x2a, 0x84, 0xef,
+    0xf0, 0x56, 0x9b, 0x22, 0x85, 0xa6, 0x85, 0x4a, 0x86, 0xef, 0x30, 0x37, 0xe4, 0x2a, 0x84, 0xef,
+    0xf0, 0x16, 0x98, 0x22, 0x85, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0x37, 0x55, 0x03, 0x20, 0x03,
+    0x45, 0xc5, 0xd9, 0xb7, 0xa5, 0x09, 0x00, 0x83, 0xc5, 0xc5, 0x0b, 0x4d, 0x8d, 0x11, 0xcd, 0x7b,
+    0x25, 0x00, 0x81, 0x0b, 0x4f, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13,
+    0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x16, 0x05, 0xa0, 0x7b, 0x25, 0x00, 0x81, 0x09, 0x46, 0x7b,
+    0x66, 0xcf, 0x2e, 0x0b, 0x47, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13,
+    0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x14, 0x93, 0x85, 0x25, 0x4c, 0x6f, 0x60, 0x17, 0xaf, 0x82,
+    0x80, 0x00, 0x00, 0x37, 0x55, 0x03, 0x20, 0x03, 0x45, 0xc5, 0xd9, 0xb7, 0xa5, 0x09, 0x00, 0x83,
+    0xc5, 0xc5, 0x0b, 0x7d, 0x15, 0x33, 0x35, 0xa0, 0x00, 0xfd, 0x15, 0xb3, 0x35, 0xb0, 0x00, 0x6d,
+    0x8d, 0x0d, 0xed, 0x37, 0xf5, 0x01, 0x20, 0x93, 0x05, 0x85, 0xad, 0x03, 0x85, 0x65, 0x00, 0x7b,
+    0x26, 0x00, 0x81, 0x85, 0x46, 0xd4, 0xc9, 0x05, 0x05, 0x23, 0x83, 0xa5, 0x00, 0x0b, 0x41, 0x16,
+    0x03, 0x08, 0x92, 0xfb, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7,
+    0xb5, 0x02, 0x20, 0x93, 0x85, 0x25, 0x4c, 0x6f, 0x60, 0xd7, 0xae, 0x7b, 0x25, 0x00, 0x81, 0x09,
+    0x46, 0x7b, 0x66, 0xcf, 0x2e, 0x0b, 0x47, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23,
+    0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x23, 0x93, 0x85, 0x25, 0x4c, 0x6f, 0x60, 0xf7,
+    0xa6, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x15, 0x08, 0x91, 0x8b, 0x54, 0x05, 0x02, 0x03,
+    0x45, 0x86, 0x00, 0x0b, 0x15, 0x05, 0x01, 0x33, 0x35, 0xb0, 0x00, 0x82, 0x80, 0xa3, 0x15, 0x06,
+    0x00, 0x93, 0x05, 0xd6, 0x00, 0x21, 0xa0, 0x1a, 0x12, 0x93, 0x05, 0xb6, 0x00, 0x05, 0x45, 0x82,
+    0x11, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x83, 0x45, 0x25, 0x00, 0x8b, 0xdc, 0x05, 0x06, 0x05,
+    0x46, 0xb3, 0x15, 0xb6, 0x00, 0x93, 0xf5, 0x55, 0x02, 0x95, 0xc1, 0x83, 0x05, 0x05, 0x07, 0xfd,
+    0x15, 0x8c, 0x91, 0x8b, 0xd4, 0x05, 0x02, 0x83, 0x45, 0xd5, 0x03, 0x13, 0xf6, 0x35, 0x00, 0x19,
+    0xce, 0x5e, 0x1d, 0x39, 0xa0, 0x3e, 0x1d, 0xa3, 0x1e, 0x05, 0x02, 0x39, 0xa0, 0x83, 0x45, 0xd5,
+    0x03, 0x93, 0xf5, 0x75, 0x0e, 0xa3, 0x0e, 0xb5, 0x02, 0x01, 0x45, 0x82, 0x80, 0x83, 0x45, 0xc5,
+    0x03, 0xe5, 0xfd, 0x03, 0x45, 0xb5, 0x03, 0x13, 0x35, 0x15, 0x00, 0x82, 0x80, 0x00, 0x00, 0x40,
+    0x99, 0x2a, 0x84, 0x83, 0x44, 0x25, 0x00, 0xef, 0xc0, 0x89, 0x82, 0x0b, 0x0a, 0x15, 0x01, 0x03,
+    0x25, 0x44, 0x09, 0x83, 0x25, 0x44, 0x08, 0x83, 0x06, 0x04, 0x07, 0xa3, 0x0c, 0x04, 0x06, 0x13,
+    0x06, 0x15, 0x00, 0x03, 0x25, 0x04, 0x0b, 0xfd, 0x16, 0x94, 0x92, 0x23, 0x2a, 0xc4, 0x08, 0x8b,
+    0xdf, 0x06, 0x02, 0xef, 0x34
+};
+
+/*
+01 03 fc 2b 86 b5 be ab 35 b6 be 15 46 ef c0 29 b6 b7 a5 09 00 93 85 85 f0 ab 85 95 04 8c 41 23
+28 a4 0a 63 60 b5 02 23 08 04 06 0d 45 a3 0c a4 06 23 28 04 0a 23 2a 04 08 3a 1c 20 99 01 c5 23
+28 04 0a 20 99 8b 4e 06 32 22 85 ef c0 c9 8a 75 f9 09 45 23 08 a4 06 37 a5 09 00 13 05 85 f0 2b
+05 95 04 08 41 85 45 03 06 d4 03 a3 0c b4 06 05 81 23 28 a4 0a 13 65 06 02 a3 0e a4 02 20 99 23
+08 04 06 20 99 00 00 40 99 ae 84 2a 84 13 05 00 20 2a c0 0a 85 ef b0 79 9d 03 45 04 07 8b 03 15
+02 0b 12 35 01 82 45 13 05 90 6c 2e 86 83 26 84 09 77 96 a4 c4 13 07 00 40 33 45 e6 02 36 95 05
+66 13 06 d6 24 ae 86 f7 96 c4 c4 03 26 c4 09 23 2c a4 08 b3 c6 e6 02 36 95 32 95 23 2e a4 08 19
+66 13 06 66 1e f7 95 c4 c4 a1 a8 82 45 13 05 90 6c 2e 86 77 96 a4 c4 03 25 84 09 85 66 13 87 06
+a0 33 46 e6 02 32 95 23 2c a4 08 13 86 d6 24 ae 86 f7 96 c4 c4 13 06 00 40 b3 c6 c6 02 36 95 83
+26 c4 09 0a 05 29 47 33 45 e5 02 36 95 23 2e a4 08 99 66 93 86 66 1e f7 95 d4 c4 b3 c5 c5 02 8a
+05 b3 c5 e5 02 50 48 2e 95 93 55 f6 41 c2 05 ab a5 c5 60 93 16 06 01 ab 85 a5 be 2b 05 c5 20 33
+36 d5 00 b2 95 08 cc 4c cc 20 99 00 00 00 00 5c 98 79 71 37 a5 09 00 93 05 45 f2 28 00 13 06 20
+0a ef 80 76 b9 37 65 02 20 13 05 a5 e3 93 05 20 0a 30 00 93 06 20 0a ef 50 47 92 ef a0 99 ff 01
+45 ef f0 f8 f2 45 61 3c 98 00 00 c0 98 37 54 03 20 03 45 c4 d9 8b 18 15 01 ef a0 3a e5 37 05 03
+20 83 45 05 24 8b 91 15 01 23 00 05 24 13 06 05 24 37 05 03 20 13 05 05 2a 93 05 00 06 93 06 00
+06 ef 50 a7 8d fb 25 00 81 2a 86 13 35 15 00 93 b5 15 00 4d 8d 19 e9 37 05 23 00 13 05 e5 17 b7
+b5 03 2d 93 85 25 44 ef 60 47 fa 23 0e 04 d8 37 a5 09 00 23 0e 05 0a 37 55 03 20 a3 0e 05 d8 a0
+98 00 00 44 99 37 a5 09 00 85 45 23 0e b5 0a 08 08 ef c0 3a 95 ef e0 29 b5 ef e0 e9 e6 ef e0 e9
+af 37 54 03 20 03 26 44 db b7 54 03 20 03 a5 c4 db 83 25 44 db 63 64 c5 00 0d 8d 19 a0 33 85 a5
+40 93 05 00 10 63 6a b5 02 37 55 03 20 03 25 85 db 03 26 44 db 83 25 44 db 63 67 a6 00 33 85 a5
+40 0b 53 05 3c 11 a8 0d 8d 0b 44 05 3c ef 20 a9 e3 03 25 44 db 23 ae a4 da ef e0 e9 cf 68 00 ef
+c0 5a 8e 42 45 b2 45 ef c0 9a 92 b7 55 03 20 93 85 85 e0 90 4d 63 73 a6 00 88 cd b7 55 03 20 03
+a6 85 df 32 95 23 ac a5 de 24 99 00 00 00 00 40 99 2e 84 aa 84 ef 40 2c a7 03 45 c5 0e 93 05 60
+0e 13 06 30 11 2b e6 a5 20 23 90 c4 00 09 45 23 10 a4 00 20 99 00 00 40 99 2e 84 aa 84 ef 40 ac
+a4 03 45 c5 0e 93 05 60 0e 13 06 00 14 2b e6 a5 20 23 90 c4 00 0d 45 23 10 a4 00 20 99 00 00 c0
+99 5d c9 2a 84 03 05 05 07 03 29 c4 2a 7d 15 88 91 13 05 f0 0f 8b ca 05 02 83 44 a4 03 ef 40 ac
+a0 03 45 c5 0e 93 35 15 00 13 06 60 0e 8b 92 04 01 13 05 30 11 19 a0 13 05 00 14 2b 65 b6 22 83
+55 44 27 63 6c b5 02 03 45 14 03 0b 1c 05 01 03 45 04 2a 0b 1a 05 01 03 45 14 2a 05 e1 03 25 44
+08 ab 05 a5 be 2b b5 a5 be 95 65 93 85 65 55 23 20 04 0a 63 64 b5 00 23 22 04 08 03 45 c4 07 0b
+19 05 01 09 45 23 0e a4 06 23 20 04 08 23 22 04 08 13 05 44 23 93 05 40 03 93 06 40 03 01 46 ef
+50 47 d1 63 0a 09 00 03 45 39 00 0b 13 05 05 23 20 04 08 23 22 04 08 a0 99 00 00 c0 99 32 84 ae
+84 93 05 40 15 13 09 a0 0f 0b 05 05 03 ef 40 ac 95 03 45 c5 0e 93 05 e0 15 ab 65 a9 20 23 10 b4
+00 0b 96 89 8c
+*/
+const uint8_t g_cfg_cmd3[] = {
+    0x01, 0x03, 0xfc, 0x2b, 0x86, 0xb5, 0xbe, 0xab, 0x35, 0xb6, 0xbe, 0x15, 0x46, 0xef, 0xc0, 0x29,
+    0xb6, 0xb7, 0xa5, 0x09, 0x00, 0x93, 0x85, 0x85, 0xf0, 0xab, 0x85, 0x95, 0x04, 0x8c, 0x41, 0x23,
+    0x28, 0xa4, 0x0a, 0x63, 0x60, 0xb5, 0x02, 0x23, 0x08, 0x04, 0x06, 0x0d, 0x45, 0xa3, 0x0c, 0xa4,
+    0x06, 0x23, 0x28, 0x04, 0x0a, 0x23, 0x2a, 0x04, 0x08, 0x3a, 0x1c, 0x20, 0x99, 0x01, 0xc5, 0x23,
+    0x28, 0x04, 0x0a, 0x20, 0x99, 0x8b, 0x4e, 0x06, 0x32, 0x22, 0x85, 0xef, 0xc0, 0xc9, 0x8a, 0x75,
+    0xf9, 0x09, 0x45, 0x23, 0x08, 0xa4, 0x06, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x05, 0x85, 0xf0, 0x2b,
+    0x05, 0x95, 0x04, 0x08, 0x41, 0x85, 0x45, 0x03, 0x06, 0xd4, 0x03, 0xa3, 0x0c, 0xb4, 0x06, 0x05,
+    0x81, 0x23, 0x28, 0xa4, 0x0a, 0x13, 0x65, 0x06, 0x02, 0xa3, 0x0e, 0xa4, 0x02, 0x20, 0x99, 0x23,
+    0x08, 0x04, 0x06, 0x20, 0x99, 0x00, 0x00, 0x40, 0x99, 0xae, 0x84, 0x2a, 0x84, 0x13, 0x05, 0x00,
+    0x20, 0x2a, 0xc0, 0x0a, 0x85, 0xef, 0xb0, 0x79, 0x9d, 0x03, 0x45, 0x04, 0x07, 0x8b, 0x03, 0x15,
+    0x02, 0x0b, 0x12, 0x35, 0x01, 0x82, 0x45, 0x13, 0x05, 0x90, 0x6c, 0x2e, 0x86, 0x83, 0x26, 0x84,
+    0x09, 0x77, 0x96, 0xa4, 0xc4, 0x13, 0x07, 0x00, 0x40, 0x33, 0x45, 0xe6, 0x02, 0x36, 0x95, 0x05,
+    0x66, 0x13, 0x06, 0xd6, 0x24, 0xae, 0x86, 0xf7, 0x96, 0xc4, 0xc4, 0x03, 0x26, 0xc4, 0x09, 0x23,
+    0x2c, 0xa4, 0x08, 0xb3, 0xc6, 0xe6, 0x02, 0x36, 0x95, 0x32, 0x95, 0x23, 0x2e, 0xa4, 0x08, 0x19,
+    0x66, 0x13, 0x06, 0x66, 0x1e, 0xf7, 0x95, 0xc4, 0xc4, 0xa1, 0xa8, 0x82, 0x45, 0x13, 0x05, 0x90,
+    0x6c, 0x2e, 0x86, 0x77, 0x96, 0xa4, 0xc4, 0x03, 0x25, 0x84, 0x09, 0x85, 0x66, 0x13, 0x87, 0x06,
+    0xa0, 0x33, 0x46, 0xe6, 0x02, 0x32, 0x95, 0x23, 0x2c, 0xa4, 0x08, 0x13, 0x86, 0xd6, 0x24, 0xae,
+    0x86, 0xf7, 0x96, 0xc4, 0xc4, 0x13, 0x06, 0x00, 0x40, 0xb3, 0xc6, 0xc6, 0x02, 0x36, 0x95, 0x83,
+    0x26, 0xc4, 0x09, 0x0a, 0x05, 0x29, 0x47, 0x33, 0x45, 0xe5, 0x02, 0x36, 0x95, 0x23, 0x2e, 0xa4,
+    0x08, 0x99, 0x66, 0x93, 0x86, 0x66, 0x1e, 0xf7, 0x95, 0xd4, 0xc4, 0xb3, 0xc5, 0xc5, 0x02, 0x8a,
+    0x05, 0xb3, 0xc5, 0xe5, 0x02, 0x50, 0x48, 0x2e, 0x95, 0x93, 0x55, 0xf6, 0x41, 0xc2, 0x05, 0xab,
+    0xa5, 0xc5, 0x60, 0x93, 0x16, 0x06, 0x01, 0xab, 0x85, 0xa5, 0xbe, 0x2b, 0x05, 0xc5, 0x20, 0x33,
+    0x36, 0xd5, 0x00, 0xb2, 0x95, 0x08, 0xcc, 0x4c, 0xcc, 0x20, 0x99, 0x00, 0x00, 0x00, 0x00, 0x5c,
+    0x98, 0x79, 0x71, 0x37, 0xa5, 0x09, 0x00, 0x93, 0x05, 0x45, 0xf2, 0x28, 0x00, 0x13, 0x06, 0x20,
+    0x0a, 0xef, 0x80, 0x76, 0xb9, 0x37, 0x65, 0x02, 0x20, 0x13, 0x05, 0xa5, 0xe3, 0x93, 0x05, 0x20,
+    0x0a, 0x30, 0x00, 0x93, 0x06, 0x20, 0x0a, 0xef, 0x50, 0x47, 0x92, 0xef, 0xa0, 0x99, 0xff, 0x01,
+    0x45, 0xef, 0xf0, 0xf8, 0xf2, 0x45, 0x61, 0x3c, 0x98, 0x00, 0x00, 0xc0, 0x98, 0x37, 0x54, 0x03,
+    0x20, 0x03, 0x45, 0xc4, 0xd9, 0x8b, 0x18, 0x15, 0x01, 0xef, 0xa0, 0x3a, 0xe5, 0x37, 0x05, 0x03,
+    0x20, 0x83, 0x45, 0x05, 0x24, 0x8b, 0x91, 0x15, 0x01, 0x23, 0x00, 0x05, 0x24, 0x13, 0x06, 0x05,
+    0x24, 0x37, 0x05, 0x03, 0x20, 0x13, 0x05, 0x05, 0x2a, 0x93, 0x05, 0x00, 0x06, 0x93, 0x06, 0x00,
+    0x06, 0xef, 0x50, 0xa7, 0x8d, 0xfb, 0x25, 0x00, 0x81, 0x2a, 0x86, 0x13, 0x35, 0x15, 0x00, 0x93,
+    0xb5, 0x15, 0x00, 0x4d, 0x8d, 0x19, 0xe9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7,
+    0xb5, 0x03, 0x2d, 0x93, 0x85, 0x25, 0x44, 0xef, 0x60, 0x47, 0xfa, 0x23, 0x0e, 0x04, 0xd8, 0x37,
+    0xa5, 0x09, 0x00, 0x23, 0x0e, 0x05, 0x0a, 0x37, 0x55, 0x03, 0x20, 0xa3, 0x0e, 0x05, 0xd8, 0xa0,
+    0x98, 0x00, 0x00, 0x44, 0x99, 0x37, 0xa5, 0x09, 0x00, 0x85, 0x45, 0x23, 0x0e, 0xb5, 0x0a, 0x08,
+    0x08, 0xef, 0xc0, 0x3a, 0x95, 0xef, 0xe0, 0x29, 0xb5, 0xef, 0xe0, 0xe9, 0xe6, 0xef, 0xe0, 0xe9,
+    0xaf, 0x37, 0x54, 0x03, 0x20, 0x03, 0x26, 0x44, 0xdb, 0xb7, 0x54, 0x03, 0x20, 0x03, 0xa5, 0xc4,
+    0xdb, 0x83, 0x25, 0x44, 0xdb, 0x63, 0x64, 0xc5, 0x00, 0x0d, 0x8d, 0x19, 0xa0, 0x33, 0x85, 0xa5,
+    0x40, 0x93, 0x05, 0x00, 0x10, 0x63, 0x6a, 0xb5, 0x02, 0x37, 0x55, 0x03, 0x20, 0x03, 0x25, 0x85,
+    0xdb, 0x03, 0x26, 0x44, 0xdb, 0x83, 0x25, 0x44, 0xdb, 0x63, 0x67, 0xa6, 0x00, 0x33, 0x85, 0xa5,
+    0x40, 0x0b, 0x53, 0x05, 0x3c, 0x11, 0xa8, 0x0d, 0x8d, 0x0b, 0x44, 0x05, 0x3c, 0xef, 0x20, 0xa9,
+    0xe3, 0x03, 0x25, 0x44, 0xdb, 0x23, 0xae, 0xa4, 0xda, 0xef, 0xe0, 0xe9, 0xcf, 0x68, 0x00, 0xef,
+    0xc0, 0x5a, 0x8e, 0x42, 0x45, 0xb2, 0x45, 0xef, 0xc0, 0x9a, 0x92, 0xb7, 0x55, 0x03, 0x20, 0x93,
+    0x85, 0x85, 0xe0, 0x90, 0x4d, 0x63, 0x73, 0xa6, 0x00, 0x88, 0xcd, 0xb7, 0x55, 0x03, 0x20, 0x03,
+    0xa6, 0x85, 0xdf, 0x32, 0x95, 0x23, 0xac, 0xa5, 0xde, 0x24, 0x99, 0x00, 0x00, 0x00, 0x00, 0x40,
+    0x99, 0x2e, 0x84, 0xaa, 0x84, 0xef, 0x40, 0x2c, 0xa7, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0x60,
+    0x0e, 0x13, 0x06, 0x30, 0x11, 0x2b, 0xe6, 0xa5, 0x20, 0x23, 0x90, 0xc4, 0x00, 0x09, 0x45, 0x23,
+    0x10, 0xa4, 0x00, 0x20, 0x99, 0x00, 0x00, 0x40, 0x99, 0x2e, 0x84, 0xaa, 0x84, 0xef, 0x40, 0xac,
+    0xa4, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0x60, 0x0e, 0x13, 0x06, 0x00, 0x14, 0x2b, 0xe6, 0xa5,
+    0x20, 0x23, 0x90, 0xc4, 0x00, 0x0d, 0x45, 0x23, 0x10, 0xa4, 0x00, 0x20, 0x99, 0x00, 0x00, 0xc0,
+    0x99, 0x5d, 0xc9, 0x2a, 0x84, 0x03, 0x05, 0x05, 0x07, 0x03, 0x29, 0xc4, 0x2a, 0x7d, 0x15, 0x88,
+    0x91, 0x13, 0x05, 0xf0, 0x0f, 0x8b, 0xca, 0x05, 0x02, 0x83, 0x44, 0xa4, 0x03, 0xef, 0x40, 0xac,
+    0xa0, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x35, 0x15, 0x00, 0x13, 0x06, 0x60, 0x0e, 0x8b, 0x92, 0x04,
+    0x01, 0x13, 0x05, 0x30, 0x11, 0x19, 0xa0, 0x13, 0x05, 0x00, 0x14, 0x2b, 0x65, 0xb6, 0x22, 0x83,
+    0x55, 0x44, 0x27, 0x63, 0x6c, 0xb5, 0x02, 0x03, 0x45, 0x14, 0x03, 0x0b, 0x1c, 0x05, 0x01, 0x03,
+    0x45, 0x04, 0x2a, 0x0b, 0x1a, 0x05, 0x01, 0x03, 0x45, 0x14, 0x2a, 0x05, 0xe1, 0x03, 0x25, 0x44,
+    0x08, 0xab, 0x05, 0xa5, 0xbe, 0x2b, 0xb5, 0xa5, 0xbe, 0x95, 0x65, 0x93, 0x85, 0x65, 0x55, 0x23,
+    0x20, 0x04, 0x0a, 0x63, 0x64, 0xb5, 0x00, 0x23, 0x22, 0x04, 0x08, 0x03, 0x45, 0xc4, 0x07, 0x0b,
+    0x19, 0x05, 0x01, 0x09, 0x45, 0x23, 0x0e, 0xa4, 0x06, 0x23, 0x20, 0x04, 0x08, 0x23, 0x22, 0x04,
+    0x08, 0x13, 0x05, 0x44, 0x23, 0x93, 0x05, 0x40, 0x03, 0x93, 0x06, 0x40, 0x03, 0x01, 0x46, 0xef,
+    0x50, 0x47, 0xd1, 0x63, 0x0a, 0x09, 0x00, 0x03, 0x45, 0x39, 0x00, 0x0b, 0x13, 0x05, 0x05, 0x23,
+    0x20, 0x04, 0x08, 0x23, 0x22, 0x04, 0x08, 0xa0, 0x99, 0x00, 0x00, 0xc0, 0x99, 0x32, 0x84, 0xae,
+    0x84, 0x93, 0x05, 0x40, 0x15, 0x13, 0x09, 0xa0, 0x0f, 0x0b, 0x05, 0x05, 0x03, 0xef, 0x40, 0xac,
+    0x95, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0xe0, 0x15, 0xab, 0x65, 0xa9, 0x20, 0x23, 0x10, 0xb4,
+    0x00, 0x0b, 0x96, 0x89, 0x8c
+};
+
+/*
+01 04 fb 04 01 ef 40 2c 94 03 45 c5 0e 93 05 b0 12 ab 65 a9 20 23 10 b4 00 a0 99 00 00 00 00 c0
+99 3d cd ae 84 2a 84 03 29 45 02 a3 0c b5 02 ef 40 8c 91 03 45 c5 0e 93 05 60 0e 13 06 00 14 2b
+e6 a5 20 63 77 c9 02 09 45 a3 08 a4 02 8b 59 09 fb 93 05 04 03 11 45 a3 08 a4 02 8b 81 14 02 0b
+93 04 01 2e 85 ca 85 ef 20 4a df ef 60 c9 a9 25 a0 22 1c ef 60 49 a9 64 9d 93 85 e4 ff b3 35 b0
+00 4d 8d 11 e9 03 45 14 03 0b 02 05 04 8b 12 05 02 05 05 a3 08 a4 02 ef 20 09 e2 11 c1 22 1c a0
+99 22 85 4a 86 ef 20 6a dc e9 b7 00 00 00 00 aa 86 03 05 05 07 7d 15 08 93 2e 85 8b 52 07 02 b2
+85 6f 10 fa c5 83 c5 a6 03 8b 92 05 01 b2 85 6f 10 5a c6 b2 85 6f 10 3a c7 00 00 c0 98 2a 84 03
+45 65 00 8b 1e 05 02 03 47 44 00 a3 01 e4 00 10 5c 54 5c 7b 25 00 81 10 d8 54 d8 72 1c 7a 1c 0b
+47 05 04 fb 27 09 f6 37 05 23 00 13 05 e5 17 b7 b5 01 25 93 85 25 4c ef 60 87 da 0e 10 a0 98 00
+00 00 00 03 47 45 00 a3 01 e5 00 10 5d 54 5d fb 25 00 81 10 d9 54 d9 72 1d 7a 1d 0b c7 05 03 fb
+27 09 f6 37 05 23 00 13 05 e5 17 b7 b5 01 34 93 85 25 4c 6f 60 c7 d6 82 80 00 00 c0 99 37 05 00
+04 b7 45 10 40 ec 55 37 16 03 20 13 04 06 b1 50 54 13 09 f5 ff 2b e5 05 74 48 d0 b3 24 c5 00 22
+85 a9 3f 03 45 64 00 0b 16 05 01 03 45 54 00 13 35 15 00 65 8d 93 15 15 00 a9 8c 23 03 b4 00 48
+50 2a 10 48 d4 37 86 12 40 03 25 06 0b 83 25 46 0b 03 26 c6 0b 69 82 b3 e6 a5 00 b3 f6 26 01 23
+02 c4 00 99 c6 b3 f5 25 01 33 75 25 01 08 dc 4c dc 81 c4 22 85 80 99 b1 b7 a0 99 00 00 00 00 40
+98 22 a0 53 15 05 c2 53 00 05 d2 53 74 05 0a ef 30 9e a4 31 c1 ef 30 3e a4 13 45 45 00 93 05 40
+06 13 06 80 0c 2b e6 a5 20 37 a5 09 00 07 30 85 fc 53 15 04 c2 d3 00 05 d2 d3 70 14 0a d3 f0 00
+12 53 95 00 c2 b3 65 c5 02 0d 8d 53 01 05 d2 d3 f0 20 0a 53 f4 00 1a ef 00 4e c9 37 a5 09 00 07
+30 05 fd 53 15 85 a2 43 70 05 42 2b 64 a0 3a 53 05 84 22 02 24 20 98 00 00 00 00 d0 99 37 a5 09
+00 93 05 85 fd 13 05 51 02 6d 46 13 04 51 02 ef 80 86 ea 37 a5 09 00 93 05 35 ff 13 05 a1 00 6d
+46 93 04 a1 00 ef 80 26 e9 ef 40 ec 9a ab 64 a4 20 37 b5 00 20 13 04 05 f2 93 05 40 02 93 06 40
+02 13 09 40 02 22 85 01 46 ef 50 a7 a2 26 85 ef 80 96 bc aa 86 93 05 40 02 22 85 26 86 ef 40 f7
+bf 19 cd 7b 25 00 81 41 cd 37 05 23 00 13 05 e5 17 b7 b5 01 28 93 85 25 34 ef 60 e7 a7 b0 99 26
+85 ef 80 76 b9 aa 84 8b 28 05 1f 7b 25 00 81 25 c9 37 05 23 00 13 05 e5 17 b7 b5 01 2d 93 85 25
+34 26 86 ef 60 87 aa b0 99 ef 80 b7 a7 aa 86 33 85 84 00 b3 05 99 40 37 a6 09 00 13 06 e6 00 ef
+20 87 b6 0b 22 05 00 aa 94 31 a8 7b 25 00 81 19 c9 37 05 23 00 13 05 e5 17 b7 b5 01 34 93 85 25
+34 ef 60 67 a1 13 06 40 02 22 85 a6 85 ef 80 ae 8a 93 85 34 00 13 06 40 02 22 85 ef 80 4e 92 b0
+99 00 00 c0 98 ef 30 2e f3 3d c1 2a 84 37 b5 00 20 03 15 85 6a 85 65 95 05 23 10 b4 00 93 05 85
+00 23 13 b4 00 13 05 84 00 ac 91 ef 00 0e b2 23 11 a4 00 ef 00 ce 94 fb 25 00 81 23 12 a4 00 0b
+c8 05 03 03 56 64 00 83 56 24 00 37 05 23 00 13 05 e5 17 b7 b5 00 25 93 85 25 4c ef 60 87 a4 03
+55 64 00 93 05 85 00 22 85 80 98 6f 00 0e 9a a0 98 00 00 83 45 f5 02 13 f6 05 02 53 05 00 d2 59
+ca 54 45 18 45 37 a6 09 00 07 30 86 01 03 46 15 02 d3 80 16 d2 53 01 17 d2 43 70 01 0a 0b 53 16
+06 85 46 79 0c
+*/
+const uint8_t g_cfg_cmd4[] = {
+    0x01, 0x04, 0xfb, 0x04, 0x01, 0xef, 0x40, 0x2c, 0x94, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0xb0,
+    0x12, 0xab, 0x65, 0xa9, 0x20, 0x23, 0x10, 0xb4, 0x00, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc0,
+    0x99, 0x3d, 0xcd, 0xae, 0x84, 0x2a, 0x84, 0x03, 0x29, 0x45, 0x02, 0xa3, 0x0c, 0xb5, 0x02, 0xef,
+    0x40, 0x8c, 0x91, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0x60, 0x0e, 0x13, 0x06, 0x00, 0x14, 0x2b,
+    0xe6, 0xa5, 0x20, 0x63, 0x77, 0xc9, 0x02, 0x09, 0x45, 0xa3, 0x08, 0xa4, 0x02, 0x8b, 0x59, 0x09,
+    0xfb, 0x93, 0x05, 0x04, 0x03, 0x11, 0x45, 0xa3, 0x08, 0xa4, 0x02, 0x8b, 0x81, 0x14, 0x02, 0x0b,
+    0x93, 0x04, 0x01, 0x2e, 0x85, 0xca, 0x85, 0xef, 0x20, 0x4a, 0xdf, 0xef, 0x60, 0xc9, 0xa9, 0x25,
+    0xa0, 0x22, 0x1c, 0xef, 0x60, 0x49, 0xa9, 0x64, 0x9d, 0x93, 0x85, 0xe4, 0xff, 0xb3, 0x35, 0xb0,
+    0x00, 0x4d, 0x8d, 0x11, 0xe9, 0x03, 0x45, 0x14, 0x03, 0x0b, 0x02, 0x05, 0x04, 0x8b, 0x12, 0x05,
+    0x02, 0x05, 0x05, 0xa3, 0x08, 0xa4, 0x02, 0xef, 0x20, 0x09, 0xe2, 0x11, 0xc1, 0x22, 0x1c, 0xa0,
+    0x99, 0x22, 0x85, 0x4a, 0x86, 0xef, 0x20, 0x6a, 0xdc, 0xe9, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xaa,
+    0x86, 0x03, 0x05, 0x05, 0x07, 0x7d, 0x15, 0x08, 0x93, 0x2e, 0x85, 0x8b, 0x52, 0x07, 0x02, 0xb2,
+    0x85, 0x6f, 0x10, 0xfa, 0xc5, 0x83, 0xc5, 0xa6, 0x03, 0x8b, 0x92, 0x05, 0x01, 0xb2, 0x85, 0x6f,
+    0x10, 0x5a, 0xc6, 0xb2, 0x85, 0x6f, 0x10, 0x3a, 0xc7, 0x00, 0x00, 0xc0, 0x98, 0x2a, 0x84, 0x03,
+    0x45, 0x65, 0x00, 0x8b, 0x1e, 0x05, 0x02, 0x03, 0x47, 0x44, 0x00, 0xa3, 0x01, 0xe4, 0x00, 0x10,
+    0x5c, 0x54, 0x5c, 0x7b, 0x25, 0x00, 0x81, 0x10, 0xd8, 0x54, 0xd8, 0x72, 0x1c, 0x7a, 0x1c, 0x0b,
+    0x47, 0x05, 0x04, 0xfb, 0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7,
+    0xb5, 0x01, 0x25, 0x93, 0x85, 0x25, 0x4c, 0xef, 0x60, 0x87, 0xda, 0x0e, 0x10, 0xa0, 0x98, 0x00,
+    0x00, 0x00, 0x00, 0x03, 0x47, 0x45, 0x00, 0xa3, 0x01, 0xe5, 0x00, 0x10, 0x5d, 0x54, 0x5d, 0xfb,
+    0x25, 0x00, 0x81, 0x10, 0xd9, 0x54, 0xd9, 0x72, 0x1d, 0x7a, 0x1d, 0x0b, 0xc7, 0x05, 0x03, 0xfb,
+    0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x34, 0x93,
+    0x85, 0x25, 0x4c, 0x6f, 0x60, 0xc7, 0xd6, 0x82, 0x80, 0x00, 0x00, 0xc0, 0x99, 0x37, 0x05, 0x00,
+    0x04, 0xb7, 0x45, 0x10, 0x40, 0xec, 0x55, 0x37, 0x16, 0x03, 0x20, 0x13, 0x04, 0x06, 0xb1, 0x50,
+    0x54, 0x13, 0x09, 0xf5, 0xff, 0x2b, 0xe5, 0x05, 0x74, 0x48, 0xd0, 0xb3, 0x24, 0xc5, 0x00, 0x22,
+    0x85, 0xa9, 0x3f, 0x03, 0x45, 0x64, 0x00, 0x0b, 0x16, 0x05, 0x01, 0x03, 0x45, 0x54, 0x00, 0x13,
+    0x35, 0x15, 0x00, 0x65, 0x8d, 0x93, 0x15, 0x15, 0x00, 0xa9, 0x8c, 0x23, 0x03, 0xb4, 0x00, 0x48,
+    0x50, 0x2a, 0x10, 0x48, 0xd4, 0x37, 0x86, 0x12, 0x40, 0x03, 0x25, 0x06, 0x0b, 0x83, 0x25, 0x46,
+    0x0b, 0x03, 0x26, 0xc6, 0x0b, 0x69, 0x82, 0xb3, 0xe6, 0xa5, 0x00, 0xb3, 0xf6, 0x26, 0x01, 0x23,
+    0x02, 0xc4, 0x00, 0x99, 0xc6, 0xb3, 0xf5, 0x25, 0x01, 0x33, 0x75, 0x25, 0x01, 0x08, 0xdc, 0x4c,
+    0xdc, 0x81, 0xc4, 0x22, 0x85, 0x80, 0x99, 0xb1, 0xb7, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0x40,
+    0x98, 0x22, 0xa0, 0x53, 0x15, 0x05, 0xc2, 0x53, 0x00, 0x05, 0xd2, 0x53, 0x74, 0x05, 0x0a, 0xef,
+    0x30, 0x9e, 0xa4, 0x31, 0xc1, 0xef, 0x30, 0x3e, 0xa4, 0x13, 0x45, 0x45, 0x00, 0x93, 0x05, 0x40,
+    0x06, 0x13, 0x06, 0x80, 0x0c, 0x2b, 0xe6, 0xa5, 0x20, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x85,
+    0xfc, 0x53, 0x15, 0x04, 0xc2, 0xd3, 0x00, 0x05, 0xd2, 0xd3, 0x70, 0x14, 0x0a, 0xd3, 0xf0, 0x00,
+    0x12, 0x53, 0x95, 0x00, 0xc2, 0xb3, 0x65, 0xc5, 0x02, 0x0d, 0x8d, 0x53, 0x01, 0x05, 0xd2, 0xd3,
+    0xf0, 0x20, 0x0a, 0x53, 0xf4, 0x00, 0x1a, 0xef, 0x00, 0x4e, 0xc9, 0x37, 0xa5, 0x09, 0x00, 0x07,
+    0x30, 0x05, 0xfd, 0x53, 0x15, 0x85, 0xa2, 0x43, 0x70, 0x05, 0x42, 0x2b, 0x64, 0xa0, 0x3a, 0x53,
+    0x05, 0x84, 0x22, 0x02, 0x24, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x99, 0x37, 0xa5, 0x09,
+    0x00, 0x93, 0x05, 0x85, 0xfd, 0x13, 0x05, 0x51, 0x02, 0x6d, 0x46, 0x13, 0x04, 0x51, 0x02, 0xef,
+    0x80, 0x86, 0xea, 0x37, 0xa5, 0x09, 0x00, 0x93, 0x05, 0x35, 0xff, 0x13, 0x05, 0xa1, 0x00, 0x6d,
+    0x46, 0x93, 0x04, 0xa1, 0x00, 0xef, 0x80, 0x26, 0xe9, 0xef, 0x40, 0xec, 0x9a, 0xab, 0x64, 0xa4,
+    0x20, 0x37, 0xb5, 0x00, 0x20, 0x13, 0x04, 0x05, 0xf2, 0x93, 0x05, 0x40, 0x02, 0x93, 0x06, 0x40,
+    0x02, 0x13, 0x09, 0x40, 0x02, 0x22, 0x85, 0x01, 0x46, 0xef, 0x50, 0xa7, 0xa2, 0x26, 0x85, 0xef,
+    0x80, 0x96, 0xbc, 0xaa, 0x86, 0x93, 0x05, 0x40, 0x02, 0x22, 0x85, 0x26, 0x86, 0xef, 0x40, 0xf7,
+    0xbf, 0x19, 0xcd, 0x7b, 0x25, 0x00, 0x81, 0x41, 0xcd, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5,
+    0x17, 0xb7, 0xb5, 0x01, 0x28, 0x93, 0x85, 0x25, 0x34, 0xef, 0x60, 0xe7, 0xa7, 0xb0, 0x99, 0x26,
+    0x85, 0xef, 0x80, 0x76, 0xb9, 0xaa, 0x84, 0x8b, 0x28, 0x05, 0x1f, 0x7b, 0x25, 0x00, 0x81, 0x25,
+    0xc9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x2d, 0x93, 0x85, 0x25,
+    0x34, 0x26, 0x86, 0xef, 0x60, 0x87, 0xaa, 0xb0, 0x99, 0xef, 0x80, 0xb7, 0xa7, 0xaa, 0x86, 0x33,
+    0x85, 0x84, 0x00, 0xb3, 0x05, 0x99, 0x40, 0x37, 0xa6, 0x09, 0x00, 0x13, 0x06, 0xe6, 0x00, 0xef,
+    0x20, 0x87, 0xb6, 0x0b, 0x22, 0x05, 0x00, 0xaa, 0x94, 0x31, 0xa8, 0x7b, 0x25, 0x00, 0x81, 0x19,
+    0xc9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x34, 0x93, 0x85, 0x25,
+    0x34, 0xef, 0x60, 0x67, 0xa1, 0x13, 0x06, 0x40, 0x02, 0x22, 0x85, 0xa6, 0x85, 0xef, 0x80, 0xae,
+    0x8a, 0x93, 0x85, 0x34, 0x00, 0x13, 0x06, 0x40, 0x02, 0x22, 0x85, 0xef, 0x80, 0x4e, 0x92, 0xb0,
+    0x99, 0x00, 0x00, 0xc0, 0x98, 0xef, 0x30, 0x2e, 0xf3, 0x3d, 0xc1, 0x2a, 0x84, 0x37, 0xb5, 0x00,
+    0x20, 0x03, 0x15, 0x85, 0x6a, 0x85, 0x65, 0x95, 0x05, 0x23, 0x10, 0xb4, 0x00, 0x93, 0x05, 0x85,
+    0x00, 0x23, 0x13, 0xb4, 0x00, 0x13, 0x05, 0x84, 0x00, 0xac, 0x91, 0xef, 0x00, 0x0e, 0xb2, 0x23,
+    0x11, 0xa4, 0x00, 0xef, 0x00, 0xce, 0x94, 0xfb, 0x25, 0x00, 0x81, 0x23, 0x12, 0xa4, 0x00, 0x0b,
+    0xc8, 0x05, 0x03, 0x03, 0x56, 0x64, 0x00, 0x83, 0x56, 0x24, 0x00, 0x37, 0x05, 0x23, 0x00, 0x13,
+    0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x00, 0x25, 0x93, 0x85, 0x25, 0x4c, 0xef, 0x60, 0x87, 0xa4, 0x03,
+    0x55, 0x64, 0x00, 0x93, 0x05, 0x85, 0x00, 0x22, 0x85, 0x80, 0x98, 0x6f, 0x00, 0x0e, 0x9a, 0xa0,
+    0x98, 0x00, 0x00, 0x83, 0x45, 0xf5, 0x02, 0x13, 0xf6, 0x05, 0x02, 0x53, 0x05, 0x00, 0xd2, 0x59,
+    0xca, 0x54, 0x45, 0x18, 0x45, 0x37, 0xa6, 0x09, 0x00, 0x07, 0x30, 0x86, 0x01, 0x03, 0x46, 0x15,
+    0x02, 0xd3, 0x80, 0x16, 0xd2, 0x53, 0x01, 0x17, 0xd2, 0x43, 0x70, 0x01, 0x0a, 0x0b, 0x53, 0x16,
+    0x06, 0x85, 0x46, 0x79, 0x0c
+};
+
+/*
+01 05 fa b3 96 c6 00 93 f6 96 02 9d ce ab e6 35 44 11 ca 03 05 05 02 0b 17 06 03 37 07 04 20 13
+07 07 de 21 a8 03 05 05 02 37 57 04 20 13 07 07 cf 29 a0 37 57 04 20 13 07 07 cc 3a 95 89 ca 03
+45 05 00 11 c5 63 82 a6 02 53 05 00 22 82 80 01 45 13 36 16 00 8d 89 93 c6 35 00 ab 65 d0 20 2b
+e5 c5 22 09 c9 0b 19 f5 01 37 a5 09 00 87 30 05 02 53 75 10 02 82 80 00 00 00 00 c4 99 2a 84 03
+06 05 02 03 45 15 02 ae 84 23 90 c5 02 a3 86 a5 02 b2 85 ef a0 ce a3 83 d5 04 02 03 c6 d4 02 23
+91 a4 02 2e 89 8b 15 06 01 37 15 00 20 13 05 85 01 2b 05 b5 04 08 41 13 09 75 00 03 05 04 03 23
+88 a4 02 ec 91 32 85 ef 00 1f 9c a3 89 a4 02 03 c5 d4 02 02 c4 02 c2 02 c0 93 15 09 01 c1 81 0a
+86 ef 90 2e e1 02 45 83 05 44 02 03 06 b4 02 23 83 a4 02 23 86 b4 02 a3 82 c4 02 03 05 e4 01 83
+05 34 02 03 06 74 02 83 06 24 02 23 82 a4 02 a3 83 b4 02 a3 88 c4 02 13 85 d6 ff 88 91 93 b5 a5
+00 13 06 10 21 33 55 a6 00 6d 8d 4c 44 10 44 b7 a6 09 00 07 b0 86 01 23 8a a4 02 d3 80 05 d2 53
+01 16 d2 43 70 01 0a 27 b8 04 00 22 85 59 35 03 05 f4 02 88 a8 23 87 a4 02 a4 99 40 99 ef 30 bc
+be 2a 84 ef 30 5c ed 93 05 10 24 93 04 10 20 13 06 10 20 2b e6 a5 20 23 2a c4 10 ef 30 dc eb 83
+25 44 11 13 35 15 00 05 05 13 f6 05 04 a3 0a a4 04 09 c6 05 46 30 c8 23 0a a4 04 13 f5 05 20 23
+0b 04 04 11 c5 ef 30 3c e9 19 e1 23 1c 94 04 23 01 04 14 20 99 00 00 85 65 33 06 b5 00 03 26 86
+b0 93 85 05 b0 aa 95 0b 18 06 01 37 d6 4c 3f 13 06 d6 cc 23 26 c5 0e 37 06 40 40 23 28 c5 0e 37
+06 00 40 23 24 c5 0e 03 c6 85 01 11 c2 82 80 07 30 85 05 37 a6 09 00 87 30 86 02 53 16 10 a2 01
+ca b7 05 00 40 23 26 b5 0e b7 05 80 3f 31 a0 8c 41 0b 97 f5 01 b7 05 80 40 23 28 b5 0e 82 80 00
+00 00 00 82 80 00 00 c0 99 2e 86 2a 84 05 65 07 30 84 05 b7 a5 09 00 87 b0 05 03 b3 05 a4 00 83
+c5 85 b1 13 05 85 b0 d3 96 00 a2 b3 04 a4 00 81 c6 99 c1 81 45 82 14 32 85 ef 50 bd 86 cc 44 05
+49 8b 81 05 01 2a 89 07 30 84 05 37 a5 09 00 87 30 85 04 53 15 10 a2 01 cd ef 30 ad ab 8b 14 05
+01 ef 50 7d ef 8b 02 05 02 05 49 23 88 24 01 22 85 ef 50 bd 87 aa 85 01 45 8b 81 05 01 4a 85 8c
+40 0b 96 05 01 83 c5 24 04 0b 84 05 02 ef 50 3d 9e 8b 12 05 01 01 45 82 14 a0 99 01 45 a0 99 00
+00 00 00 c8 99 22 ac 26 a8 4a a4 32 84 08 22 2e 89 aa 84 ef 90 66 b5 07 30 04 00 53 04 a5 22 53
+05 00 22 ef 90 86 9a 07 30 84 00 d3 04 a5 22 53 05 00 22 ef 90 66 b3 07 30 84 00 53 09 a5 22 53
+05 00 22 ef 90 86 98 07 b0 84 00 87 b0 04 00 53 11 84 22 87 b1 04 01 53 70 20 12 d3 70 19 12 c7
+70 05 0a 53 f1 34 12 c3 70 25 0a 27 30 19 00 87 b0 04 00 d3 70 15 12 43 70 09 0a 43 70 29 02 27
+34 09 00 07 b0 84 00 88 4c 53 f0 04 12 43 70 34 02 27 38 09 00 23 2c a9 00 22 29 c2 24 62 24 a8
+99 00 00 dc 99 59 71 a2 ad a6 a9 2a 84 07 30 05 00 87 30 85 00 07 31 05 01 53 84 b5 22 d3 04 a5
+22 ae 84 02 b9 06 bd 8a a1 05 49 ca c5 08 19 8c 18 ef 50 fb ec 07 30 84 02 87 30 04 03 07 31 84
+03 02 a9 06 ad 0a b1 4a d5 28 10 0c 09 13 06 00 02 ef 80 66 96 28 00 8c 18 13 06 00 02 ef 80 a6
+95 28 10 2c 00 90 08 b4 00 ef 60 6b 86 46 20 e6 20 53 70 90 12 82 a8 53 f0 90 12 82 ac 88 08 0c
+09 90 18 c5 35 4a 20 ea 20 0a 31 27 34 04 02 27 38 14 02 27 3c 24 02 07 30 04 00 87 b0 04 00 53
+70 10 0a 5a 55
+*/
+const uint8_t g_cfg_cmd5[] = {
+    0x01, 0x05, 0xfa, 0xb3, 0x96, 0xc6, 0x00, 0x93, 0xf6, 0x96, 0x02, 0x9d, 0xce, 0xab, 0xe6, 0x35,
+    0x44, 0x11, 0xca, 0x03, 0x05, 0x05, 0x02, 0x0b, 0x17, 0x06, 0x03, 0x37, 0x07, 0x04, 0x20, 0x13,
+    0x07, 0x07, 0xde, 0x21, 0xa8, 0x03, 0x05, 0x05, 0x02, 0x37, 0x57, 0x04, 0x20, 0x13, 0x07, 0x07,
+    0xcf, 0x29, 0xa0, 0x37, 0x57, 0x04, 0x20, 0x13, 0x07, 0x07, 0xcc, 0x3a, 0x95, 0x89, 0xca, 0x03,
+    0x45, 0x05, 0x00, 0x11, 0xc5, 0x63, 0x82, 0xa6, 0x02, 0x53, 0x05, 0x00, 0x22, 0x82, 0x80, 0x01,
+    0x45, 0x13, 0x36, 0x16, 0x00, 0x8d, 0x89, 0x93, 0xc6, 0x35, 0x00, 0xab, 0x65, 0xd0, 0x20, 0x2b,
+    0xe5, 0xc5, 0x22, 0x09, 0xc9, 0x0b, 0x19, 0xf5, 0x01, 0x37, 0xa5, 0x09, 0x00, 0x87, 0x30, 0x05,
+    0x02, 0x53, 0x75, 0x10, 0x02, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x99, 0x2a, 0x84, 0x03,
+    0x06, 0x05, 0x02, 0x03, 0x45, 0x15, 0x02, 0xae, 0x84, 0x23, 0x90, 0xc5, 0x02, 0xa3, 0x86, 0xa5,
+    0x02, 0xb2, 0x85, 0xef, 0xa0, 0xce, 0xa3, 0x83, 0xd5, 0x04, 0x02, 0x03, 0xc6, 0xd4, 0x02, 0x23,
+    0x91, 0xa4, 0x02, 0x2e, 0x89, 0x8b, 0x15, 0x06, 0x01, 0x37, 0x15, 0x00, 0x20, 0x13, 0x05, 0x85,
+    0x01, 0x2b, 0x05, 0xb5, 0x04, 0x08, 0x41, 0x13, 0x09, 0x75, 0x00, 0x03, 0x05, 0x04, 0x03, 0x23,
+    0x88, 0xa4, 0x02, 0xec, 0x91, 0x32, 0x85, 0xef, 0x00, 0x1f, 0x9c, 0xa3, 0x89, 0xa4, 0x02, 0x03,
+    0xc5, 0xd4, 0x02, 0x02, 0xc4, 0x02, 0xc2, 0x02, 0xc0, 0x93, 0x15, 0x09, 0x01, 0xc1, 0x81, 0x0a,
+    0x86, 0xef, 0x90, 0x2e, 0xe1, 0x02, 0x45, 0x83, 0x05, 0x44, 0x02, 0x03, 0x06, 0xb4, 0x02, 0x23,
+    0x83, 0xa4, 0x02, 0x23, 0x86, 0xb4, 0x02, 0xa3, 0x82, 0xc4, 0x02, 0x03, 0x05, 0xe4, 0x01, 0x83,
+    0x05, 0x34, 0x02, 0x03, 0x06, 0x74, 0x02, 0x83, 0x06, 0x24, 0x02, 0x23, 0x82, 0xa4, 0x02, 0xa3,
+    0x83, 0xb4, 0x02, 0xa3, 0x88, 0xc4, 0x02, 0x13, 0x85, 0xd6, 0xff, 0x88, 0x91, 0x93, 0xb5, 0xa5,
+    0x00, 0x13, 0x06, 0x10, 0x21, 0x33, 0x55, 0xa6, 0x00, 0x6d, 0x8d, 0x4c, 0x44, 0x10, 0x44, 0xb7,
+    0xa6, 0x09, 0x00, 0x07, 0xb0, 0x86, 0x01, 0x23, 0x8a, 0xa4, 0x02, 0xd3, 0x80, 0x05, 0xd2, 0x53,
+    0x01, 0x16, 0xd2, 0x43, 0x70, 0x01, 0x0a, 0x27, 0xb8, 0x04, 0x00, 0x22, 0x85, 0x59, 0x35, 0x03,
+    0x05, 0xf4, 0x02, 0x88, 0xa8, 0x23, 0x87, 0xa4, 0x02, 0xa4, 0x99, 0x40, 0x99, 0xef, 0x30, 0xbc,
+    0xbe, 0x2a, 0x84, 0xef, 0x30, 0x5c, 0xed, 0x93, 0x05, 0x10, 0x24, 0x93, 0x04, 0x10, 0x20, 0x13,
+    0x06, 0x10, 0x20, 0x2b, 0xe6, 0xa5, 0x20, 0x23, 0x2a, 0xc4, 0x10, 0xef, 0x30, 0xdc, 0xeb, 0x83,
+    0x25, 0x44, 0x11, 0x13, 0x35, 0x15, 0x00, 0x05, 0x05, 0x13, 0xf6, 0x05, 0x04, 0xa3, 0x0a, 0xa4,
+    0x04, 0x09, 0xc6, 0x05, 0x46, 0x30, 0xc8, 0x23, 0x0a, 0xa4, 0x04, 0x13, 0xf5, 0x05, 0x20, 0x23,
+    0x0b, 0x04, 0x04, 0x11, 0xc5, 0xef, 0x30, 0x3c, 0xe9, 0x19, 0xe1, 0x23, 0x1c, 0x94, 0x04, 0x23,
+    0x01, 0x04, 0x14, 0x20, 0x99, 0x00, 0x00, 0x85, 0x65, 0x33, 0x06, 0xb5, 0x00, 0x03, 0x26, 0x86,
+    0xb0, 0x93, 0x85, 0x05, 0xb0, 0xaa, 0x95, 0x0b, 0x18, 0x06, 0x01, 0x37, 0xd6, 0x4c, 0x3f, 0x13,
+    0x06, 0xd6, 0xcc, 0x23, 0x26, 0xc5, 0x0e, 0x37, 0x06, 0x40, 0x40, 0x23, 0x28, 0xc5, 0x0e, 0x37,
+    0x06, 0x00, 0x40, 0x23, 0x24, 0xc5, 0x0e, 0x03, 0xc6, 0x85, 0x01, 0x11, 0xc2, 0x82, 0x80, 0x07,
+    0x30, 0x85, 0x05, 0x37, 0xa6, 0x09, 0x00, 0x87, 0x30, 0x86, 0x02, 0x53, 0x16, 0x10, 0xa2, 0x01,
+    0xca, 0xb7, 0x05, 0x00, 0x40, 0x23, 0x26, 0xb5, 0x0e, 0xb7, 0x05, 0x80, 0x3f, 0x31, 0xa0, 0x8c,
+    0x41, 0x0b, 0x97, 0xf5, 0x01, 0xb7, 0x05, 0x80, 0x40, 0x23, 0x28, 0xb5, 0x0e, 0x82, 0x80, 0x00,
+    0x00, 0x00, 0x00, 0x82, 0x80, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x86, 0x2a, 0x84, 0x05, 0x65, 0x07,
+    0x30, 0x84, 0x05, 0xb7, 0xa5, 0x09, 0x00, 0x87, 0xb0, 0x05, 0x03, 0xb3, 0x05, 0xa4, 0x00, 0x83,
+    0xc5, 0x85, 0xb1, 0x13, 0x05, 0x85, 0xb0, 0xd3, 0x96, 0x00, 0xa2, 0xb3, 0x04, 0xa4, 0x00, 0x81,
+    0xc6, 0x99, 0xc1, 0x81, 0x45, 0x82, 0x14, 0x32, 0x85, 0xef, 0x50, 0xbd, 0x86, 0xcc, 0x44, 0x05,
+    0x49, 0x8b, 0x81, 0x05, 0x01, 0x2a, 0x89, 0x07, 0x30, 0x84, 0x05, 0x37, 0xa5, 0x09, 0x00, 0x87,
+    0x30, 0x85, 0x04, 0x53, 0x15, 0x10, 0xa2, 0x01, 0xcd, 0xef, 0x30, 0xad, 0xab, 0x8b, 0x14, 0x05,
+    0x01, 0xef, 0x50, 0x7d, 0xef, 0x8b, 0x02, 0x05, 0x02, 0x05, 0x49, 0x23, 0x88, 0x24, 0x01, 0x22,
+    0x85, 0xef, 0x50, 0xbd, 0x87, 0xaa, 0x85, 0x01, 0x45, 0x8b, 0x81, 0x05, 0x01, 0x4a, 0x85, 0x8c,
+    0x40, 0x0b, 0x96, 0x05, 0x01, 0x83, 0xc5, 0x24, 0x04, 0x0b, 0x84, 0x05, 0x02, 0xef, 0x50, 0x3d,
+    0x9e, 0x8b, 0x12, 0x05, 0x01, 0x01, 0x45, 0x82, 0x14, 0xa0, 0x99, 0x01, 0x45, 0xa0, 0x99, 0x00,
+    0x00, 0x00, 0x00, 0xc8, 0x99, 0x22, 0xac, 0x26, 0xa8, 0x4a, 0xa4, 0x32, 0x84, 0x08, 0x22, 0x2e,
+    0x89, 0xaa, 0x84, 0xef, 0x90, 0x66, 0xb5, 0x07, 0x30, 0x04, 0x00, 0x53, 0x04, 0xa5, 0x22, 0x53,
+    0x05, 0x00, 0x22, 0xef, 0x90, 0x86, 0x9a, 0x07, 0x30, 0x84, 0x00, 0xd3, 0x04, 0xa5, 0x22, 0x53,
+    0x05, 0x00, 0x22, 0xef, 0x90, 0x66, 0xb3, 0x07, 0x30, 0x84, 0x00, 0x53, 0x09, 0xa5, 0x22, 0x53,
+    0x05, 0x00, 0x22, 0xef, 0x90, 0x86, 0x98, 0x07, 0xb0, 0x84, 0x00, 0x87, 0xb0, 0x04, 0x00, 0x53,
+    0x11, 0x84, 0x22, 0x87, 0xb1, 0x04, 0x01, 0x53, 0x70, 0x20, 0x12, 0xd3, 0x70, 0x19, 0x12, 0xc7,
+    0x70, 0x05, 0x0a, 0x53, 0xf1, 0x34, 0x12, 0xc3, 0x70, 0x25, 0x0a, 0x27, 0x30, 0x19, 0x00, 0x87,
+    0xb0, 0x04, 0x00, 0xd3, 0x70, 0x15, 0x12, 0x43, 0x70, 0x09, 0x0a, 0x43, 0x70, 0x29, 0x02, 0x27,
+    0x34, 0x09, 0x00, 0x07, 0xb0, 0x84, 0x00, 0x88, 0x4c, 0x53, 0xf0, 0x04, 0x12, 0x43, 0x70, 0x34,
+    0x02, 0x27, 0x38, 0x09, 0x00, 0x23, 0x2c, 0xa9, 0x00, 0x22, 0x29, 0xc2, 0x24, 0x62, 0x24, 0xa8,
+    0x99, 0x00, 0x00, 0xdc, 0x99, 0x59, 0x71, 0xa2, 0xad, 0xa6, 0xa9, 0x2a, 0x84, 0x07, 0x30, 0x05,
+    0x00, 0x87, 0x30, 0x85, 0x00, 0x07, 0x31, 0x05, 0x01, 0x53, 0x84, 0xb5, 0x22, 0xd3, 0x04, 0xa5,
+    0x22, 0xae, 0x84, 0x02, 0xb9, 0x06, 0xbd, 0x8a, 0xa1, 0x05, 0x49, 0xca, 0xc5, 0x08, 0x19, 0x8c,
+    0x18, 0xef, 0x50, 0xfb, 0xec, 0x07, 0x30, 0x84, 0x02, 0x87, 0x30, 0x04, 0x03, 0x07, 0x31, 0x84,
+    0x03, 0x02, 0xa9, 0x06, 0xad, 0x0a, 0xb1, 0x4a, 0xd5, 0x28, 0x10, 0x0c, 0x09, 0x13, 0x06, 0x00,
+    0x02, 0xef, 0x80, 0x66, 0x96, 0x28, 0x00, 0x8c, 0x18, 0x13, 0x06, 0x00, 0x02, 0xef, 0x80, 0xa6,
+    0x95, 0x28, 0x10, 0x2c, 0x00, 0x90, 0x08, 0xb4, 0x00, 0xef, 0x60, 0x6b, 0x86, 0x46, 0x20, 0xe6,
+    0x20, 0x53, 0x70, 0x90, 0x12, 0x82, 0xa8, 0x53, 0xf0, 0x90, 0x12, 0x82, 0xac, 0x88, 0x08, 0x0c,
+    0x09, 0x90, 0x18, 0xc5, 0x35, 0x4a, 0x20, 0xea, 0x20, 0x0a, 0x31, 0x27, 0x34, 0x04, 0x02, 0x27,
+    0x38, 0x14, 0x02, 0x27, 0x3c, 0x24, 0x02, 0x07, 0x30, 0x04, 0x00, 0x87, 0xb0, 0x04, 0x00, 0x53,
+    0x70, 0x10, 0x0a, 0x5a, 0x55
+};
+
+/*
+01 06 f9 87 30 84 00 07 b1 84 00 87 31 04 01 07 b2 04 01 02 a9 53 f0 20 0a 02 ad 53 f0 41 0a 02
+b1 4a d5 28 10 0c 09 13 06 00 02 ef 80 c6 8e 28 00 8c 18 13 06 00 02 ef 80 06 8e 28 10 2c 00 90
+08 b4 00 ef 50 db fe 46 20 e6 20 53 70 80 12 82 a8 53 f0 80 12 82 ac 88 08 0c 09 90 18 9d 35 07
+b0 04 00 ca 20 53 70 10 02 27 30 04 00 07 b0 84 00 ea 20 53 70 10 02 27 34 04 00 07 b0 04 01 8a
+30 53 70 10 02 27 38 04 00 ce 24 6e 24 65 61 bc 99 00 00 40 9b 2e 8a aa 84 05 64 13 05 04 b1 b3
+89 a4 00 ef 30 5c 8a 83 2a 85 0e ef 40 8d f1 aa 85 26 85 95 3b b3 85 84 00 83 a5 85 b3 25 46 b3
+35 b6 00 33 35 a0 00 6d 8d 15 e1 13 05 84 b7 26 95 b7 a5 09 00 07 b5 05 04 d2 85 ef 50 5d 95 23
+a0 09 00 37 55 04 20 23 2e 05 72 20 9b 13 05 84 b7 33 89 a4 00 63 8a 0a 00 53 05 00 d2 52 85 ca
+85 ef 50 fd 92 05 45 2d a0 37 a5 09 00 07 35 05 02 37 a5 09 00 87 35 85 03 52 85 ca 85 99 35 37
+a5 09 00 07 35 05 04 4a 85 d2 85 ef 50 5d 90 01 45 23 a0 a9 00 b7 55 04 20 23 ae a5 72 52 85 a6
+85 00 9b 6f 00 1d aa 00 00 00 00 37 a5 09 00 07 30 05 04 53 95 05 a2 11 c5 37 a5 09 00 07 30 85
+04 b9 a8 53 15 05 a2 01 c9 37 a5 09 00 07 30 05 02 53 70 05 02 a9 a0 37 a5 09 00 07 30 05 05 53
+15 05 a2 01 cd 37 a5 09 00 07 30 05 02 37 a5 09 00 87 30 85 02 43 70 15 02 1d a0 37 a5 09 00 07
+30 85 05 53 15 05 a2 01 c9 37 a5 09 00 07 30 05 02 53 70 05 12 29 a0 37 a5 09 00 07 30 05 06 53
+75 c0 12 82 80 00 00 c0 9b 37 ab 09 00 93 04 4b 0b dc 40 ba 89 36 89 32 8a 2e 84 aa 8a 05 65 93
+05 05 a0 3e 85 01 46 ae 86 ef 40 b7 ae 03 25 4b 0b 93 05 80 2d 93 06 80 2d 01 46 ef 40 97 ad 22
+85 ef c0 bd f9 83 26 4b 0b d8 40 05 45 d6 85 22 86 ef a0 2d ed 05 c5 03 25 4b 0b 93 95 29 00 13
+06 05 1e 93 06 40 0c 52 85 ef 40 27 c9 d0 40 22 85 d2 85 ca 86 ef 90 bd f5 33 35 a0 00 a0 9b 00
+00 00 00 8b 2f 05 01 81 48 33 28 b0 00 13 13 25 00 93 92 25 00 63 01 08 02 b2 83 36 8e ba 8e ae
+87 5b a5 43 a0 db 25 4e a0 53 75 b5 10 27 a0 ae 00 fd 17 9a 9e f5 f7 85 08 11 07 16 96 e3 9c a8
+fc 82 80 00 00 00 00 48 9e 22 b0 26 ac 80 10 83 2a 44 00 83 2d 04 00 2a 89 37 a5 09 00 63 d5 ba
+01 07 24 85 06 a1 aa c6 89 be 84 36 8c 2e 8b 23 24 e4 fa 23 26 04 fb 23 28 c4 fa 23 2a 24 fa 3d
+45 ab 05 55 05 c1 99 33 0a b1 40 52 81 b3 85 ba 03 ab 05 b5 04 c1 99 33 0d b1 40 6a 81 b3 0c b1
+40 66 81 ab 05 b5 05 c1 99 b3 05 b1 40 23 22 b4 fa 2e 81 b3 85 bd 03 2b 05 b5 04 41 99 b3 0b a1
+40 5e 81 93 95 2a 00 52 85 01 46 ae 86 ef 40 77 9c 6a 85 e2 85 56 86 ee 86 5a 87 ef f0 cd ad 0b
+a9 0a 01 13 05 f9 ff 13 35 15 00 d6 85 52 86 5b a5 44 a0 d3 75 a5 10 ab 65 a5 38 fd 15 5b 22 b6
+e0 fd f5 6e 85 d6 85 6a 86 d2 86 66 87 dd 3d 37 a5 09 00 87 24 c5 06 d3 05 00 f0 53 04 00 f0 01
+45 ee 85 6e 86 d6 86 53 85 94 20 66 87 ea 87 5e 88 ef f0 ed a2 5e 85 ee 85 ef f0 ad e2 11 c5 37
+a5 09 00 07 24 85 06 b1 a8 8b a7 0d 01 11 45 2b 05 b5 05 53 04 00 f0 de 85 6e 86 88 61 53 74 a4
+00 7d 16 aa 95 7d fa 05 46 d3 05 00 f0 01 45 ee 85 d6 86 53 85 94 20 66 87 83 27 84 fa 83 24 44
+fa 26 88 ef f0 cd 9d 05 46 d3 05 00 f0 01 45 ee 85 ee 86 53 85 94 20 5e 87 a6 87 03 28 c4 fa ef
+f0 0d 9c 83 24 44 fb 63 8a 09 00 5e 85 ce 85 6e 86 ee 86 03 27 04 fb ef f0 8d a3 26 81 53 05 84
+20 13 01 f6 d7
+*/
+const uint8_t g_cfg_cmd6[] = {
+    0x01, 0x06, 0xf9, 0x87, 0x30, 0x84, 0x00, 0x07, 0xb1, 0x84, 0x00, 0x87, 0x31, 0x04, 0x01, 0x07,
+    0xb2, 0x04, 0x01, 0x02, 0xa9, 0x53, 0xf0, 0x20, 0x0a, 0x02, 0xad, 0x53, 0xf0, 0x41, 0x0a, 0x02,
+    0xb1, 0x4a, 0xd5, 0x28, 0x10, 0x0c, 0x09, 0x13, 0x06, 0x00, 0x02, 0xef, 0x80, 0xc6, 0x8e, 0x28,
+    0x00, 0x8c, 0x18, 0x13, 0x06, 0x00, 0x02, 0xef, 0x80, 0x06, 0x8e, 0x28, 0x10, 0x2c, 0x00, 0x90,
+    0x08, 0xb4, 0x00, 0xef, 0x50, 0xdb, 0xfe, 0x46, 0x20, 0xe6, 0x20, 0x53, 0x70, 0x80, 0x12, 0x82,
+    0xa8, 0x53, 0xf0, 0x80, 0x12, 0x82, 0xac, 0x88, 0x08, 0x0c, 0x09, 0x90, 0x18, 0x9d, 0x35, 0x07,
+    0xb0, 0x04, 0x00, 0xca, 0x20, 0x53, 0x70, 0x10, 0x02, 0x27, 0x30, 0x04, 0x00, 0x07, 0xb0, 0x84,
+    0x00, 0xea, 0x20, 0x53, 0x70, 0x10, 0x02, 0x27, 0x34, 0x04, 0x00, 0x07, 0xb0, 0x04, 0x01, 0x8a,
+    0x30, 0x53, 0x70, 0x10, 0x02, 0x27, 0x38, 0x04, 0x00, 0xce, 0x24, 0x6e, 0x24, 0x65, 0x61, 0xbc,
+    0x99, 0x00, 0x00, 0x40, 0x9b, 0x2e, 0x8a, 0xaa, 0x84, 0x05, 0x64, 0x13, 0x05, 0x04, 0xb1, 0xb3,
+    0x89, 0xa4, 0x00, 0xef, 0x30, 0x5c, 0x8a, 0x83, 0x2a, 0x85, 0x0e, 0xef, 0x40, 0x8d, 0xf1, 0xaa,
+    0x85, 0x26, 0x85, 0x95, 0x3b, 0xb3, 0x85, 0x84, 0x00, 0x83, 0xa5, 0x85, 0xb3, 0x25, 0x46, 0xb3,
+    0x35, 0xb6, 0x00, 0x33, 0x35, 0xa0, 0x00, 0x6d, 0x8d, 0x15, 0xe1, 0x13, 0x05, 0x84, 0xb7, 0x26,
+    0x95, 0xb7, 0xa5, 0x09, 0x00, 0x07, 0xb5, 0x05, 0x04, 0xd2, 0x85, 0xef, 0x50, 0x5d, 0x95, 0x23,
+    0xa0, 0x09, 0x00, 0x37, 0x55, 0x04, 0x20, 0x23, 0x2e, 0x05, 0x72, 0x20, 0x9b, 0x13, 0x05, 0x84,
+    0xb7, 0x33, 0x89, 0xa4, 0x00, 0x63, 0x8a, 0x0a, 0x00, 0x53, 0x05, 0x00, 0xd2, 0x52, 0x85, 0xca,
+    0x85, 0xef, 0x50, 0xfd, 0x92, 0x05, 0x45, 0x2d, 0xa0, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x35, 0x05,
+    0x02, 0x37, 0xa5, 0x09, 0x00, 0x87, 0x35, 0x85, 0x03, 0x52, 0x85, 0xca, 0x85, 0x99, 0x35, 0x37,
+    0xa5, 0x09, 0x00, 0x07, 0x35, 0x05, 0x04, 0x4a, 0x85, 0xd2, 0x85, 0xef, 0x50, 0x5d, 0x90, 0x01,
+    0x45, 0x23, 0xa0, 0xa9, 0x00, 0xb7, 0x55, 0x04, 0x20, 0x23, 0xae, 0xa5, 0x72, 0x52, 0x85, 0xa6,
+    0x85, 0x00, 0x9b, 0x6f, 0x00, 0x1d, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x37, 0xa5, 0x09, 0x00, 0x07,
+    0x30, 0x05, 0x04, 0x53, 0x95, 0x05, 0xa2, 0x11, 0xc5, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x85,
+    0x04, 0xb9, 0xa8, 0x53, 0x15, 0x05, 0xa2, 0x01, 0xc9, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x05,
+    0x02, 0x53, 0x70, 0x05, 0x02, 0xa9, 0xa0, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x05, 0x53,
+    0x15, 0x05, 0xa2, 0x01, 0xcd, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x02, 0x37, 0xa5, 0x09,
+    0x00, 0x87, 0x30, 0x85, 0x02, 0x43, 0x70, 0x15, 0x02, 0x1d, 0xa0, 0x37, 0xa5, 0x09, 0x00, 0x07,
+    0x30, 0x85, 0x05, 0x53, 0x15, 0x05, 0xa2, 0x01, 0xc9, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x05,
+    0x02, 0x53, 0x70, 0x05, 0x12, 0x29, 0xa0, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x06, 0x53,
+    0x75, 0xc0, 0x12, 0x82, 0x80, 0x00, 0x00, 0xc0, 0x9b, 0x37, 0xab, 0x09, 0x00, 0x93, 0x04, 0x4b,
+    0x0b, 0xdc, 0x40, 0xba, 0x89, 0x36, 0x89, 0x32, 0x8a, 0x2e, 0x84, 0xaa, 0x8a, 0x05, 0x65, 0x93,
+    0x05, 0x05, 0xa0, 0x3e, 0x85, 0x01, 0x46, 0xae, 0x86, 0xef, 0x40, 0xb7, 0xae, 0x03, 0x25, 0x4b,
+    0x0b, 0x93, 0x05, 0x80, 0x2d, 0x93, 0x06, 0x80, 0x2d, 0x01, 0x46, 0xef, 0x40, 0x97, 0xad, 0x22,
+    0x85, 0xef, 0xc0, 0xbd, 0xf9, 0x83, 0x26, 0x4b, 0x0b, 0xd8, 0x40, 0x05, 0x45, 0xd6, 0x85, 0x22,
+    0x86, 0xef, 0xa0, 0x2d, 0xed, 0x05, 0xc5, 0x03, 0x25, 0x4b, 0x0b, 0x93, 0x95, 0x29, 0x00, 0x13,
+    0x06, 0x05, 0x1e, 0x93, 0x06, 0x40, 0x0c, 0x52, 0x85, 0xef, 0x40, 0x27, 0xc9, 0xd0, 0x40, 0x22,
+    0x85, 0xd2, 0x85, 0xca, 0x86, 0xef, 0x90, 0xbd, 0xf5, 0x33, 0x35, 0xa0, 0x00, 0xa0, 0x9b, 0x00,
+    0x00, 0x00, 0x00, 0x8b, 0x2f, 0x05, 0x01, 0x81, 0x48, 0x33, 0x28, 0xb0, 0x00, 0x13, 0x13, 0x25,
+    0x00, 0x93, 0x92, 0x25, 0x00, 0x63, 0x01, 0x08, 0x02, 0xb2, 0x83, 0x36, 0x8e, 0xba, 0x8e, 0xae,
+    0x87, 0x5b, 0xa5, 0x43, 0xa0, 0xdb, 0x25, 0x4e, 0xa0, 0x53, 0x75, 0xb5, 0x10, 0x27, 0xa0, 0xae,
+    0x00, 0xfd, 0x17, 0x9a, 0x9e, 0xf5, 0xf7, 0x85, 0x08, 0x11, 0x07, 0x16, 0x96, 0xe3, 0x9c, 0xa8,
+    0xfc, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x48, 0x9e, 0x22, 0xb0, 0x26, 0xac, 0x80, 0x10, 0x83,
+    0x2a, 0x44, 0x00, 0x83, 0x2d, 0x04, 0x00, 0x2a, 0x89, 0x37, 0xa5, 0x09, 0x00, 0x63, 0xd5, 0xba,
+    0x01, 0x07, 0x24, 0x85, 0x06, 0xa1, 0xaa, 0xc6, 0x89, 0xbe, 0x84, 0x36, 0x8c, 0x2e, 0x8b, 0x23,
+    0x24, 0xe4, 0xfa, 0x23, 0x26, 0x04, 0xfb, 0x23, 0x28, 0xc4, 0xfa, 0x23, 0x2a, 0x24, 0xfa, 0x3d,
+    0x45, 0xab, 0x05, 0x55, 0x05, 0xc1, 0x99, 0x33, 0x0a, 0xb1, 0x40, 0x52, 0x81, 0xb3, 0x85, 0xba,
+    0x03, 0xab, 0x05, 0xb5, 0x04, 0xc1, 0x99, 0x33, 0x0d, 0xb1, 0x40, 0x6a, 0x81, 0xb3, 0x0c, 0xb1,
+    0x40, 0x66, 0x81, 0xab, 0x05, 0xb5, 0x05, 0xc1, 0x99, 0xb3, 0x05, 0xb1, 0x40, 0x23, 0x22, 0xb4,
+    0xfa, 0x2e, 0x81, 0xb3, 0x85, 0xbd, 0x03, 0x2b, 0x05, 0xb5, 0x04, 0x41, 0x99, 0xb3, 0x0b, 0xa1,
+    0x40, 0x5e, 0x81, 0x93, 0x95, 0x2a, 0x00, 0x52, 0x85, 0x01, 0x46, 0xae, 0x86, 0xef, 0x40, 0x77,
+    0x9c, 0x6a, 0x85, 0xe2, 0x85, 0x56, 0x86, 0xee, 0x86, 0x5a, 0x87, 0xef, 0xf0, 0xcd, 0xad, 0x0b,
+    0xa9, 0x0a, 0x01, 0x13, 0x05, 0xf9, 0xff, 0x13, 0x35, 0x15, 0x00, 0xd6, 0x85, 0x52, 0x86, 0x5b,
+    0xa5, 0x44, 0xa0, 0xd3, 0x75, 0xa5, 0x10, 0xab, 0x65, 0xa5, 0x38, 0xfd, 0x15, 0x5b, 0x22, 0xb6,
+    0xe0, 0xfd, 0xf5, 0x6e, 0x85, 0xd6, 0x85, 0x6a, 0x86, 0xd2, 0x86, 0x66, 0x87, 0xdd, 0x3d, 0x37,
+    0xa5, 0x09, 0x00, 0x87, 0x24, 0xc5, 0x06, 0xd3, 0x05, 0x00, 0xf0, 0x53, 0x04, 0x00, 0xf0, 0x01,
+    0x45, 0xee, 0x85, 0x6e, 0x86, 0xd6, 0x86, 0x53, 0x85, 0x94, 0x20, 0x66, 0x87, 0xea, 0x87, 0x5e,
+    0x88, 0xef, 0xf0, 0xed, 0xa2, 0x5e, 0x85, 0xee, 0x85, 0xef, 0xf0, 0xad, 0xe2, 0x11, 0xc5, 0x37,
+    0xa5, 0x09, 0x00, 0x07, 0x24, 0x85, 0x06, 0xb1, 0xa8, 0x8b, 0xa7, 0x0d, 0x01, 0x11, 0x45, 0x2b,
+    0x05, 0xb5, 0x05, 0x53, 0x04, 0x00, 0xf0, 0xde, 0x85, 0x6e, 0x86, 0x88, 0x61, 0x53, 0x74, 0xa4,
+    0x00, 0x7d, 0x16, 0xaa, 0x95, 0x7d, 0xfa, 0x05, 0x46, 0xd3, 0x05, 0x00, 0xf0, 0x01, 0x45, 0xee,
+    0x85, 0xd6, 0x86, 0x53, 0x85, 0x94, 0x20, 0x66, 0x87, 0x83, 0x27, 0x84, 0xfa, 0x83, 0x24, 0x44,
+    0xfa, 0x26, 0x88, 0xef, 0xf0, 0xcd, 0x9d, 0x05, 0x46, 0xd3, 0x05, 0x00, 0xf0, 0x01, 0x45, 0xee,
+    0x85, 0xee, 0x86, 0x53, 0x85, 0x94, 0x20, 0x5e, 0x87, 0xa6, 0x87, 0x03, 0x28, 0xc4, 0xfa, 0xef,
+    0xf0, 0x0d, 0x9c, 0x83, 0x24, 0x44, 0xfb, 0x63, 0x8a, 0x09, 0x00, 0x5e, 0x85, 0xce, 0x85, 0x6e,
+    0x86, 0xee, 0x86, 0x03, 0x27, 0x04, 0xfb, 0xef, 0xf0, 0x8d, 0xa3, 0x26, 0x81, 0x53, 0x05, 0x84,
+    0x20, 0x13, 0x01, 0xf6, 0xd7
+};
+
+/*
+01 07 f8 04 fa e2 24 02 34 28 9e c0 99 2e 84 aa 84 ef d0 eb a2 15 c5 ef 50 ce c9 37 a5 09 00 87
+25 05 07 53 85 a5 a0 05 49 09 ed e0 91 26 85 ef 80 5e ba 37 a5 09 00 07 30 85 07 53 15 05 a2 11
+c1 01 49 4a 85 a0 99 00 00 00 00 c0 9b 0b d2 05 e4 01 4a a9 a8 ae 89 2a 89 31 4a 05 44 13 0b 40
+0e a0 90 26 85 ef a0 bc ce aa 8a 01 45 a6 85 71 3f 0b 16 05 01 33 05 49 01 b3 85 49 41 93 06 80
+0d 56 86 ef 40 87 a3 5a 8a 13 35 04 02 05 04 13 0b 8a 0d b3 b5 69 01 e4 9d 6d 8d 79 f1 93 05 4a
+ff 0d 45 05 46 ca 86 4e 87 ef 10 7e b1 52 85 a0 9b 00 00 40 9b 0b d2 05 e4 01 4a a1 a8 ae 89 2a
+89 31 4a 85 44 13 04 40 0e 64 91 ef d0 da ff aa 8a a4 91 0d 45 1d 3f 0b 16 05 01 33 05 49 01 b3
+85 49 41 93 06 80 0d 56 86 ef 40 27 9d 22 8a 13 b5 24 03 85 04 13 04 8a 0d b3 b5 89 00 e4 9d 6d
+8d 61 f5 93 05 4a ff 1d 45 05 46 ca 86 4e 87 ef 10 1e ab 52 85 20 9b c0 9b 0b d2 05 d4 01 4a a9
+a8 ae 89 2a 89 31 4a 05 44 13 0b 40 0d a0 90 26 85 ef e0 7b c2 aa 8a 19 45 a6 85 c1 3d 0b 16 05
+01 33 05 49 01 b3 85 49 41 93 06 80 0c 56 86 ef 40 c7 96 5a 8a 13 35 44 02 05 04 13 0b 8a 0c b3
+b5 69 01 e4 9d 6d 8d 79 f1 93 05 4a ff 39 45 05 46 ca 86 4e 87 ef 10 be a4 52 85 a0 9b 00 00 c0
+9b 0b d2 05 bc 01 4a b9 a8 ae 89 2a 89 31 4a 05 44 13 0b c0 0b a0 90 26 85 ef 00 6c f8 aa 8a 05
+45 a6 85 a5 35 0b 17 05 01 23 96 8a 0a 33 05 49 01 b3 85 49 41 93 06 00 0b 56 86 ef 40 07 90 5a
+8a 13 35 84 01 05 04 13 0b 0a 0b b3 b5 69 01 e4 9d 6d 8d 69 f1 93 05 4a ff 55 45 05 46 ca 86 4e
+87 ef 10 fe 9d 52 85 a0 9b 00 00 dc 9d 13 01 01 dd 27 3c 81 28 36 84 b2 89 2e 89 28 00 93 05 00
+29 7d 56 93 06 00 29 13 0a 81 00 ef 40 87 ec 28 00 93 05 40 0a ef 60 3e fc 37 15 09 00 13 05 05
+98 ab 05 84 04 33 86 a5 00 83 0a 06 00 13 a6 1a 00 93 b6 19 00 01 4b 55 8e 51 ea 2e 95 93 0b 15
+00 37 a5 09 00 07 34 05 08 05 4c 37 15 09 00 93 0c 45 9a 81 44 33 85 9b 00 03 44 05 00 13 1d 0c
+01 13 5d 0d 41 0b 5f 04 1b 22 85 ea 85 ef 90 3e 86 0d c5 ab 85 8c 04 03 94 25 00 63 40 04 02 ab
+05 aa 04 8c 41 8b 85 05 ff ef 80 fe 8d 19 c5 28 69 53 00 05 42 53 05 80 a2 19 cd 85 04 0b 9e e4
+04 33 25 5d 01 93 15 0b 01 c1 81 b3 b5 35 01 6d 8d 05 0c 45 f1 21 a8 33 05 84 01 93 15 0b 01 c1
+81 05 0b ab 05 b9 02 23 90 a5 00 d9 bf 13 15 0b 01 41 81 07 34 81 29 13 01 01 23 bc 9d 00 00 5c
+9e 13 01 01 dd 27 30 81 2a 27 3c 91 28 63 0d 05 10 2e 84 2a 89 01 45 93 09 81 00 fd 55 13 06 00
+29 b3 86 a9 00 11 05 8c c2 e3 1c c5 fe 28 00 93 05 40 0a ef 60 5e ec 13 7a f4 0f 63 06 0a 0e 37
+a5 09 00 07 34 05 08 37 a5 09 00 87 34 85 08 01 45 81 4a b7 15 09 00 13 8b 45 9a ab 05 ab 04 83
+9b 05 00 8b ae 2b 01 2b 0c a9 10 93 8c 25 00 85 44 13 f5 fa 0f e4 91 ef 90 8e f7 2a 84 7d 15 28
+91 8b 54 25 a3 22 85 ef 80 1e 80 83 45 0c 00 0b d1 25 24 2a 8d 03 96 0c 00 13 25 06 00 93 36 1d
+00 55 8d 25 e9 07 25 0d 05 53 00 05 42 53 05 80 a2 2d e1 2b 85 89 04 08 41 26 96 2b 04 bc 02 23
+12 c4 00 0b 0a 05 ff b3 0d bc 00 23 8e 0d 0c ef 60 de ed 93 05 15 00 ab 65 a0 20 23 8e bd 0c 07
+25 0d 05 83 45 0c 00 53 00 05 42 53 70 90 12 53 15 00 c2 23 16 a4 04 07 25 4d 05 53 00 05 42 53
+70 90 12 53 15 00 c2 23 1a a4 08 13 85 15 00 23 00 ac 00 13 85 14 00 e8 90 e3 dc 9b f4 85 0a 13
+f5 fa 0f 0c c2
+*/
+const uint8_t g_cfg_cmd7[] = {
+    0x01, 0x07, 0xf8, 0x04, 0xfa, 0xe2, 0x24, 0x02, 0x34, 0x28, 0x9e, 0xc0, 0x99, 0x2e, 0x84, 0xaa,
+    0x84, 0xef, 0xd0, 0xeb, 0xa2, 0x15, 0xc5, 0xef, 0x50, 0xce, 0xc9, 0x37, 0xa5, 0x09, 0x00, 0x87,
+    0x25, 0x05, 0x07, 0x53, 0x85, 0xa5, 0xa0, 0x05, 0x49, 0x09, 0xed, 0xe0, 0x91, 0x26, 0x85, 0xef,
+    0x80, 0x5e, 0xba, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x07, 0x53, 0x15, 0x05, 0xa2, 0x11,
+    0xc1, 0x01, 0x49, 0x4a, 0x85, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9b, 0x0b, 0xd2, 0x05,
+    0xe4, 0x01, 0x4a, 0xa9, 0xa8, 0xae, 0x89, 0x2a, 0x89, 0x31, 0x4a, 0x05, 0x44, 0x13, 0x0b, 0x40,
+    0x0e, 0xa0, 0x90, 0x26, 0x85, 0xef, 0xa0, 0xbc, 0xce, 0xaa, 0x8a, 0x01, 0x45, 0xa6, 0x85, 0x71,
+    0x3f, 0x0b, 0x16, 0x05, 0x01, 0x33, 0x05, 0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x80,
+    0x0d, 0x56, 0x86, 0xef, 0x40, 0x87, 0xa3, 0x5a, 0x8a, 0x13, 0x35, 0x04, 0x02, 0x05, 0x04, 0x13,
+    0x0b, 0x8a, 0x0d, 0xb3, 0xb5, 0x69, 0x01, 0xe4, 0x9d, 0x6d, 0x8d, 0x79, 0xf1, 0x93, 0x05, 0x4a,
+    0xff, 0x0d, 0x45, 0x05, 0x46, 0xca, 0x86, 0x4e, 0x87, 0xef, 0x10, 0x7e, 0xb1, 0x52, 0x85, 0xa0,
+    0x9b, 0x00, 0x00, 0x40, 0x9b, 0x0b, 0xd2, 0x05, 0xe4, 0x01, 0x4a, 0xa1, 0xa8, 0xae, 0x89, 0x2a,
+    0x89, 0x31, 0x4a, 0x85, 0x44, 0x13, 0x04, 0x40, 0x0e, 0x64, 0x91, 0xef, 0xd0, 0xda, 0xff, 0xaa,
+    0x8a, 0xa4, 0x91, 0x0d, 0x45, 0x1d, 0x3f, 0x0b, 0x16, 0x05, 0x01, 0x33, 0x05, 0x49, 0x01, 0xb3,
+    0x85, 0x49, 0x41, 0x93, 0x06, 0x80, 0x0d, 0x56, 0x86, 0xef, 0x40, 0x27, 0x9d, 0x22, 0x8a, 0x13,
+    0xb5, 0x24, 0x03, 0x85, 0x04, 0x13, 0x04, 0x8a, 0x0d, 0xb3, 0xb5, 0x89, 0x00, 0xe4, 0x9d, 0x6d,
+    0x8d, 0x61, 0xf5, 0x93, 0x05, 0x4a, 0xff, 0x1d, 0x45, 0x05, 0x46, 0xca, 0x86, 0x4e, 0x87, 0xef,
+    0x10, 0x1e, 0xab, 0x52, 0x85, 0x20, 0x9b, 0xc0, 0x9b, 0x0b, 0xd2, 0x05, 0xd4, 0x01, 0x4a, 0xa9,
+    0xa8, 0xae, 0x89, 0x2a, 0x89, 0x31, 0x4a, 0x05, 0x44, 0x13, 0x0b, 0x40, 0x0d, 0xa0, 0x90, 0x26,
+    0x85, 0xef, 0xe0, 0x7b, 0xc2, 0xaa, 0x8a, 0x19, 0x45, 0xa6, 0x85, 0xc1, 0x3d, 0x0b, 0x16, 0x05,
+    0x01, 0x33, 0x05, 0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x80, 0x0c, 0x56, 0x86, 0xef,
+    0x40, 0xc7, 0x96, 0x5a, 0x8a, 0x13, 0x35, 0x44, 0x02, 0x05, 0x04, 0x13, 0x0b, 0x8a, 0x0c, 0xb3,
+    0xb5, 0x69, 0x01, 0xe4, 0x9d, 0x6d, 0x8d, 0x79, 0xf1, 0x93, 0x05, 0x4a, 0xff, 0x39, 0x45, 0x05,
+    0x46, 0xca, 0x86, 0x4e, 0x87, 0xef, 0x10, 0xbe, 0xa4, 0x52, 0x85, 0xa0, 0x9b, 0x00, 0x00, 0xc0,
+    0x9b, 0x0b, 0xd2, 0x05, 0xbc, 0x01, 0x4a, 0xb9, 0xa8, 0xae, 0x89, 0x2a, 0x89, 0x31, 0x4a, 0x05,
+    0x44, 0x13, 0x0b, 0xc0, 0x0b, 0xa0, 0x90, 0x26, 0x85, 0xef, 0x00, 0x6c, 0xf8, 0xaa, 0x8a, 0x05,
+    0x45, 0xa6, 0x85, 0xa5, 0x35, 0x0b, 0x17, 0x05, 0x01, 0x23, 0x96, 0x8a, 0x0a, 0x33, 0x05, 0x49,
+    0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x00, 0x0b, 0x56, 0x86, 0xef, 0x40, 0x07, 0x90, 0x5a,
+    0x8a, 0x13, 0x35, 0x84, 0x01, 0x05, 0x04, 0x13, 0x0b, 0x0a, 0x0b, 0xb3, 0xb5, 0x69, 0x01, 0xe4,
+    0x9d, 0x6d, 0x8d, 0x69, 0xf1, 0x93, 0x05, 0x4a, 0xff, 0x55, 0x45, 0x05, 0x46, 0xca, 0x86, 0x4e,
+    0x87, 0xef, 0x10, 0xfe, 0x9d, 0x52, 0x85, 0xa0, 0x9b, 0x00, 0x00, 0xdc, 0x9d, 0x13, 0x01, 0x01,
+    0xdd, 0x27, 0x3c, 0x81, 0x28, 0x36, 0x84, 0xb2, 0x89, 0x2e, 0x89, 0x28, 0x00, 0x93, 0x05, 0x00,
+    0x29, 0x7d, 0x56, 0x93, 0x06, 0x00, 0x29, 0x13, 0x0a, 0x81, 0x00, 0xef, 0x40, 0x87, 0xec, 0x28,
+    0x00, 0x93, 0x05, 0x40, 0x0a, 0xef, 0x60, 0x3e, 0xfc, 0x37, 0x15, 0x09, 0x00, 0x13, 0x05, 0x05,
+    0x98, 0xab, 0x05, 0x84, 0x04, 0x33, 0x86, 0xa5, 0x00, 0x83, 0x0a, 0x06, 0x00, 0x13, 0xa6, 0x1a,
+    0x00, 0x93, 0xb6, 0x19, 0x00, 0x01, 0x4b, 0x55, 0x8e, 0x51, 0xea, 0x2e, 0x95, 0x93, 0x0b, 0x15,
+    0x00, 0x37, 0xa5, 0x09, 0x00, 0x07, 0x34, 0x05, 0x08, 0x05, 0x4c, 0x37, 0x15, 0x09, 0x00, 0x93,
+    0x0c, 0x45, 0x9a, 0x81, 0x44, 0x33, 0x85, 0x9b, 0x00, 0x03, 0x44, 0x05, 0x00, 0x13, 0x1d, 0x0c,
+    0x01, 0x13, 0x5d, 0x0d, 0x41, 0x0b, 0x5f, 0x04, 0x1b, 0x22, 0x85, 0xea, 0x85, 0xef, 0x90, 0x3e,
+    0x86, 0x0d, 0xc5, 0xab, 0x85, 0x8c, 0x04, 0x03, 0x94, 0x25, 0x00, 0x63, 0x40, 0x04, 0x02, 0xab,
+    0x05, 0xaa, 0x04, 0x8c, 0x41, 0x8b, 0x85, 0x05, 0xff, 0xef, 0x80, 0xfe, 0x8d, 0x19, 0xc5, 0x28,
+    0x69, 0x53, 0x00, 0x05, 0x42, 0x53, 0x05, 0x80, 0xa2, 0x19, 0xcd, 0x85, 0x04, 0x0b, 0x9e, 0xe4,
+    0x04, 0x33, 0x25, 0x5d, 0x01, 0x93, 0x15, 0x0b, 0x01, 0xc1, 0x81, 0xb3, 0xb5, 0x35, 0x01, 0x6d,
+    0x8d, 0x05, 0x0c, 0x45, 0xf1, 0x21, 0xa8, 0x33, 0x05, 0x84, 0x01, 0x93, 0x15, 0x0b, 0x01, 0xc1,
+    0x81, 0x05, 0x0b, 0xab, 0x05, 0xb9, 0x02, 0x23, 0x90, 0xa5, 0x00, 0xd9, 0xbf, 0x13, 0x15, 0x0b,
+    0x01, 0x41, 0x81, 0x07, 0x34, 0x81, 0x29, 0x13, 0x01, 0x01, 0x23, 0xbc, 0x9d, 0x00, 0x00, 0x5c,
+    0x9e, 0x13, 0x01, 0x01, 0xdd, 0x27, 0x30, 0x81, 0x2a, 0x27, 0x3c, 0x91, 0x28, 0x63, 0x0d, 0x05,
+    0x10, 0x2e, 0x84, 0x2a, 0x89, 0x01, 0x45, 0x93, 0x09, 0x81, 0x00, 0xfd, 0x55, 0x13, 0x06, 0x00,
+    0x29, 0xb3, 0x86, 0xa9, 0x00, 0x11, 0x05, 0x8c, 0xc2, 0xe3, 0x1c, 0xc5, 0xfe, 0x28, 0x00, 0x93,
+    0x05, 0x40, 0x0a, 0xef, 0x60, 0x5e, 0xec, 0x13, 0x7a, 0xf4, 0x0f, 0x63, 0x06, 0x0a, 0x0e, 0x37,
+    0xa5, 0x09, 0x00, 0x07, 0x34, 0x05, 0x08, 0x37, 0xa5, 0x09, 0x00, 0x87, 0x34, 0x85, 0x08, 0x01,
+    0x45, 0x81, 0x4a, 0xb7, 0x15, 0x09, 0x00, 0x13, 0x8b, 0x45, 0x9a, 0xab, 0x05, 0xab, 0x04, 0x83,
+    0x9b, 0x05, 0x00, 0x8b, 0xae, 0x2b, 0x01, 0x2b, 0x0c, 0xa9, 0x10, 0x93, 0x8c, 0x25, 0x00, 0x85,
+    0x44, 0x13, 0xf5, 0xfa, 0x0f, 0xe4, 0x91, 0xef, 0x90, 0x8e, 0xf7, 0x2a, 0x84, 0x7d, 0x15, 0x28,
+    0x91, 0x8b, 0x54, 0x25, 0xa3, 0x22, 0x85, 0xef, 0x80, 0x1e, 0x80, 0x83, 0x45, 0x0c, 0x00, 0x0b,
+    0xd1, 0x25, 0x24, 0x2a, 0x8d, 0x03, 0x96, 0x0c, 0x00, 0x13, 0x25, 0x06, 0x00, 0x93, 0x36, 0x1d,
+    0x00, 0x55, 0x8d, 0x25, 0xe9, 0x07, 0x25, 0x0d, 0x05, 0x53, 0x00, 0x05, 0x42, 0x53, 0x05, 0x80,
+    0xa2, 0x2d, 0xe1, 0x2b, 0x85, 0x89, 0x04, 0x08, 0x41, 0x26, 0x96, 0x2b, 0x04, 0xbc, 0x02, 0x23,
+    0x12, 0xc4, 0x00, 0x0b, 0x0a, 0x05, 0xff, 0xb3, 0x0d, 0xbc, 0x00, 0x23, 0x8e, 0x0d, 0x0c, 0xef,
+    0x60, 0xde, 0xed, 0x93, 0x05, 0x15, 0x00, 0xab, 0x65, 0xa0, 0x20, 0x23, 0x8e, 0xbd, 0x0c, 0x07,
+    0x25, 0x0d, 0x05, 0x83, 0x45, 0x0c, 0x00, 0x53, 0x00, 0x05, 0x42, 0x53, 0x70, 0x90, 0x12, 0x53,
+    0x15, 0x00, 0xc2, 0x23, 0x16, 0xa4, 0x04, 0x07, 0x25, 0x4d, 0x05, 0x53, 0x00, 0x05, 0x42, 0x53,
+    0x70, 0x90, 0x12, 0x53, 0x15, 0x00, 0xc2, 0x23, 0x1a, 0xa4, 0x08, 0x13, 0x85, 0x15, 0x00, 0x23,
+    0x00, 0xac, 0x00, 0x13, 0x85, 0x14, 0x00, 0xe8, 0x90, 0xe3, 0xdc, 0x9b, 0xf4, 0x85, 0x0a, 0x13,
+    0xf5, 0xfa, 0x0f, 0x0c, 0xc2
+};
+
+/*
+01 08 f7 e3 6c 45 f3 87 34 81 29 07 34 01 2a 13 01 01 23 3c 9e 00 00 c0 99 2e 89 aa 84 93 06 c5
+10 37 a5 09 00 13 06 05 09 93 05 00 08 4a 85 ef 10 87 e5 63 45 05 06 13 84 04 0d 22 85 ef 70 b6
+e3 aa 86 93 05 00 08 4a 85 22 86 ef 80 17 ca 39 e5 93 84 04 0f 26 85 ef 70 16 e2 aa 86 93 05 00
+08 4a 85 26 86 ef 80 77 c8 15 e9 26 85 ef 70 b6 e0 8b 13 05 01 37 a5 09 00 13 04 75 09 29 a0 37
+a5 09 00 13 04 95 09 22 85 ef 70 f6 de aa 86 93 05 00 08 4a 85 22 86 ef 80 57 c5 11 c1 a0 99 4a
+85 ef 70 76 dd aa 85 13 06 00 08 4a 85 ef 70 ae b4 4a 85 ef 70 56 dc 13 06 00 08 aa 85 4a 85 80
+99 6f 70 ee bb 00 00 40 9a 32 89 ae 89 01 45 01 44 93 85 a5 1b 33 86 a5 00 03 16 06 00 63 43 c0
+00 01 46 30 92 09 05 32 94 0b 1b f5 0c 93 86 c9 10 37 a5 09 00 13 06 05 0a 93 05 00 08 4a 85 ef
+10 87 d8 63 47 05 0a 93 84 09 0d 26 85 ef 70 b6 d6 aa 86 93 05 00 08 4a 85 26 86 ef 80 17 bd 49
+e9 93 84 09 03 26 85 ef 70 16 d5 aa 86 93 05 00 08 4a 85 26 86 ef 80 77 bb 25 ed 93 84 09 10 26
+85 ef 70 76 d3 aa 86 93 05 00 08 4a 85 26 86 ef 80 d7 b9 39 ed 93 06 00 08 22 85 81 45 4a 86 ef
+70 4e 9d 4e 85 ef 70 36 d1 aa 86 93 05 00 08 4a 85 4e 86 ef 80 97 b7 0d ed 13 84 09 05 22 85 ef
+70 96 cf aa 86 93 05 00 08 4a 85 22 86 ef 80 f7 b5 05 e1 37 a5 09 00 13 04 75 0a 22 85 ef 70 b6
+cd aa 86 93 05 00 08 4a 85 22 86 ef 80 17 b4 11 c1 20 9a 4a 85 ef 70 36 cc aa 85 13 06 00 08 4a
+85 ef 70 6e a3 4a 85 ef 70 16 cb 13 06 00 08 aa 85 4a 85 00 9a 6f 70 ae aa 00 00 40 98 ef 20 3e
+98 b7 c5 04 20 03 a6 85 0c 81 45 01 e6 85 45 0b 52 05 05 2e 85 20 98 ef c0 db db 13 25 55 00 8d
+45 33 85 a5 40 20 98 00 00 00 00 c0 99 2a 84 f1 37 aa 84 ef c0 1b da 2a 89 84 92 37 a5 09 00 93
+04 e5 00 91 45 22 85 26 86 ef 10 e7 c5 63 4a 05 00 13 05 44 00 c1 45 26 86 ca 86 80 99 6f 10 a7
+c4 a0 99 dc 99 7d 71 2e 89 aa 84 08 10 93 05 00 06 93 06 00 06 01 46 ef 40 c7 a7 28 00 d1 45 d1
+46 01 46 ef 40 07 a7 37 05 05 20 13 04 85 c3 22 85 ef 70 ae da 08 10 a2 85 ef 70 ae d6 28 00 71
+37 37 a5 09 00 13 06 a5 0a 26 85 ca 85 ef 80 27 e8 3d e9 10 10 26 85 ca 85 ef 80 67 e7 2d e5 10
+18 26 85 ca 85 ef 80 a7 e6 39 ed 90 00 26 85 ca 85 ef 80 e7 e5 29 e9 90 08 26 85 ca 85 ef 80 27
+e5 39 e1 30 00 26 85 ca 85 ef 80 67 e4 0d ed 90 10 26 85 ca 85 ef 80 a7 e3 1d e5 70 00 26 85 ca
+85 ef 80 e7 e2 0d e1 26 85 ef 70 f6 b8 aa 85 26 85 4a 86 ef 70 4e 90 26 85 ef 70 f6 b7 aa 85 26
+85 4a 86 ef 70 ce 97 41 61 bc 99 49 1f 00 00 00 00 00 00 49 1f 00 00 00 00 00 00 00 00 00 00 49
+1f 00 00 c7 31 00 00 63 65 ce 00 05 00 e9 51 1c 0d 06 00 87 40 04 01 04 00 73 4c 6b 0b 06 00 87
+40 08 02 03 00 88 41 64 08 06 00 88 41 32 04 07 00 00 00 00 00 00 00 00 00 00 00 00 00 63 65 ce
+00 05 00 e9 51 1c 0d 06 00 fd 78 c9 01 05 00 73 4c 6b 0b 06 00 47 6e cd 03 05 00 88 41 64 08 06
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 65 ce 00 05 00 e9 51 1c 0d 06 00 63
+65 ce 00 05 00 e9 51 1c 0d 06 00 aa 79 28 01 05 00 de 7a bf 0e 07 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 8f 40 00 00 00 00 00 00 00 c0 24 41 63 68 69
+6c 6c 65 73 2c 48 37 53 31 2c 51 33 35 2c 46 31 50 31 30 2e 30 00 24 41 63 68 69 6c 6c 65 73 2c
+48 37 53 a5 d7
+*/
+const uint8_t g_cfg_cmd8[] = {
+    0x01, 0x08, 0xf7, 0xe3, 0x6c, 0x45, 0xf3, 0x87, 0x34, 0x81, 0x29, 0x07, 0x34, 0x01, 0x2a, 0x13,
+    0x01, 0x01, 0x23, 0x3c, 0x9e, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x89, 0xaa, 0x84, 0x93, 0x06, 0xc5,
+    0x10, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x06, 0x05, 0x09, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0xef,
+    0x10, 0x87, 0xe5, 0x63, 0x45, 0x05, 0x06, 0x13, 0x84, 0x04, 0x0d, 0x22, 0x85, 0xef, 0x70, 0xb6,
+    0xe3, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x80, 0x17, 0xca, 0x39,
+    0xe5, 0x93, 0x84, 0x04, 0x0f, 0x26, 0x85, 0xef, 0x70, 0x16, 0xe2, 0xaa, 0x86, 0x93, 0x05, 0x00,
+    0x08, 0x4a, 0x85, 0x26, 0x86, 0xef, 0x80, 0x77, 0xc8, 0x15, 0xe9, 0x26, 0x85, 0xef, 0x70, 0xb6,
+    0xe0, 0x8b, 0x13, 0x05, 0x01, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x04, 0x75, 0x09, 0x29, 0xa0, 0x37,
+    0xa5, 0x09, 0x00, 0x13, 0x04, 0x95, 0x09, 0x22, 0x85, 0xef, 0x70, 0xf6, 0xde, 0xaa, 0x86, 0x93,
+    0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x80, 0x57, 0xc5, 0x11, 0xc1, 0xa0, 0x99, 0x4a,
+    0x85, 0xef, 0x70, 0x76, 0xdd, 0xaa, 0x85, 0x13, 0x06, 0x00, 0x08, 0x4a, 0x85, 0xef, 0x70, 0xae,
+    0xb4, 0x4a, 0x85, 0xef, 0x70, 0x56, 0xdc, 0x13, 0x06, 0x00, 0x08, 0xaa, 0x85, 0x4a, 0x85, 0x80,
+    0x99, 0x6f, 0x70, 0xee, 0xbb, 0x00, 0x00, 0x40, 0x9a, 0x32, 0x89, 0xae, 0x89, 0x01, 0x45, 0x01,
+    0x44, 0x93, 0x85, 0xa5, 0x1b, 0x33, 0x86, 0xa5, 0x00, 0x03, 0x16, 0x06, 0x00, 0x63, 0x43, 0xc0,
+    0x00, 0x01, 0x46, 0x30, 0x92, 0x09, 0x05, 0x32, 0x94, 0x0b, 0x1b, 0xf5, 0x0c, 0x93, 0x86, 0xc9,
+    0x10, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x06, 0x05, 0x0a, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0xef,
+    0x10, 0x87, 0xd8, 0x63, 0x47, 0x05, 0x0a, 0x93, 0x84, 0x09, 0x0d, 0x26, 0x85, 0xef, 0x70, 0xb6,
+    0xd6, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x26, 0x86, 0xef, 0x80, 0x17, 0xbd, 0x49,
+    0xe9, 0x93, 0x84, 0x09, 0x03, 0x26, 0x85, 0xef, 0x70, 0x16, 0xd5, 0xaa, 0x86, 0x93, 0x05, 0x00,
+    0x08, 0x4a, 0x85, 0x26, 0x86, 0xef, 0x80, 0x77, 0xbb, 0x25, 0xed, 0x93, 0x84, 0x09, 0x10, 0x26,
+    0x85, 0xef, 0x70, 0x76, 0xd3, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x26, 0x86, 0xef,
+    0x80, 0xd7, 0xb9, 0x39, 0xed, 0x93, 0x06, 0x00, 0x08, 0x22, 0x85, 0x81, 0x45, 0x4a, 0x86, 0xef,
+    0x70, 0x4e, 0x9d, 0x4e, 0x85, 0xef, 0x70, 0x36, 0xd1, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a,
+    0x85, 0x4e, 0x86, 0xef, 0x80, 0x97, 0xb7, 0x0d, 0xed, 0x13, 0x84, 0x09, 0x05, 0x22, 0x85, 0xef,
+    0x70, 0x96, 0xcf, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x80, 0xf7,
+    0xb5, 0x05, 0xe1, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x04, 0x75, 0x0a, 0x22, 0x85, 0xef, 0x70, 0xb6,
+    0xcd, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x80, 0x17, 0xb4, 0x11,
+    0xc1, 0x20, 0x9a, 0x4a, 0x85, 0xef, 0x70, 0x36, 0xcc, 0xaa, 0x85, 0x13, 0x06, 0x00, 0x08, 0x4a,
+    0x85, 0xef, 0x70, 0x6e, 0xa3, 0x4a, 0x85, 0xef, 0x70, 0x16, 0xcb, 0x13, 0x06, 0x00, 0x08, 0xaa,
+    0x85, 0x4a, 0x85, 0x00, 0x9a, 0x6f, 0x70, 0xae, 0xaa, 0x00, 0x00, 0x40, 0x98, 0xef, 0x20, 0x3e,
+    0x98, 0xb7, 0xc5, 0x04, 0x20, 0x03, 0xa6, 0x85, 0x0c, 0x81, 0x45, 0x01, 0xe6, 0x85, 0x45, 0x0b,
+    0x52, 0x05, 0x05, 0x2e, 0x85, 0x20, 0x98, 0xef, 0xc0, 0xdb, 0xdb, 0x13, 0x25, 0x55, 0x00, 0x8d,
+    0x45, 0x33, 0x85, 0xa5, 0x40, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x99, 0x2a, 0x84, 0xf1,
+    0x37, 0xaa, 0x84, 0xef, 0xc0, 0x1b, 0xda, 0x2a, 0x89, 0x84, 0x92, 0x37, 0xa5, 0x09, 0x00, 0x93,
+    0x04, 0xe5, 0x00, 0x91, 0x45, 0x22, 0x85, 0x26, 0x86, 0xef, 0x10, 0xe7, 0xc5, 0x63, 0x4a, 0x05,
+    0x00, 0x13, 0x05, 0x44, 0x00, 0xc1, 0x45, 0x26, 0x86, 0xca, 0x86, 0x80, 0x99, 0x6f, 0x10, 0xa7,
+    0xc4, 0xa0, 0x99, 0xdc, 0x99, 0x7d, 0x71, 0x2e, 0x89, 0xaa, 0x84, 0x08, 0x10, 0x93, 0x05, 0x00,
+    0x06, 0x93, 0x06, 0x00, 0x06, 0x01, 0x46, 0xef, 0x40, 0xc7, 0xa7, 0x28, 0x00, 0xd1, 0x45, 0xd1,
+    0x46, 0x01, 0x46, 0xef, 0x40, 0x07, 0xa7, 0x37, 0x05, 0x05, 0x20, 0x13, 0x04, 0x85, 0xc3, 0x22,
+    0x85, 0xef, 0x70, 0xae, 0xda, 0x08, 0x10, 0xa2, 0x85, 0xef, 0x70, 0xae, 0xd6, 0x28, 0x00, 0x71,
+    0x37, 0x37, 0xa5, 0x09, 0x00, 0x13, 0x06, 0xa5, 0x0a, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0x27,
+    0xe8, 0x3d, 0xe9, 0x10, 0x10, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0x67, 0xe7, 0x2d, 0xe5, 0x10,
+    0x18, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0xa7, 0xe6, 0x39, 0xed, 0x90, 0x00, 0x26, 0x85, 0xca,
+    0x85, 0xef, 0x80, 0xe7, 0xe5, 0x29, 0xe9, 0x90, 0x08, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0x27,
+    0xe5, 0x39, 0xe1, 0x30, 0x00, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0x67, 0xe4, 0x0d, 0xed, 0x90,
+    0x10, 0x26, 0x85, 0xca, 0x85, 0xef, 0x80, 0xa7, 0xe3, 0x1d, 0xe5, 0x70, 0x00, 0x26, 0x85, 0xca,
+    0x85, 0xef, 0x80, 0xe7, 0xe2, 0x0d, 0xe1, 0x26, 0x85, 0xef, 0x70, 0xf6, 0xb8, 0xaa, 0x85, 0x26,
+    0x85, 0x4a, 0x86, 0xef, 0x70, 0x4e, 0x90, 0x26, 0x85, 0xef, 0x70, 0xf6, 0xb7, 0xaa, 0x85, 0x26,
+    0x85, 0x4a, 0x86, 0xef, 0x70, 0xce, 0x97, 0x41, 0x61, 0xbc, 0x99, 0x49, 0x1f, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x49, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+    0x1f, 0x00, 0x00, 0xc7, 0x31, 0x00, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c,
+    0x0d, 0x06, 0x00, 0x87, 0x40, 0x04, 0x01, 0x04, 0x00, 0x73, 0x4c, 0x6b, 0x0b, 0x06, 0x00, 0x87,
+    0x40, 0x08, 0x02, 0x03, 0x00, 0x88, 0x41, 0x64, 0x08, 0x06, 0x00, 0x88, 0x41, 0x32, 0x04, 0x07,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x65, 0xce,
+    0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0xfd, 0x78, 0xc9, 0x01, 0x05, 0x00, 0x73,
+    0x4c, 0x6b, 0x0b, 0x06, 0x00, 0x47, 0x6e, 0xcd, 0x03, 0x05, 0x00, 0x88, 0x41, 0x64, 0x08, 0x06,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0x63,
+    0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0xaa, 0x79, 0x28, 0x01, 0x05,
+    0x00, 0xde, 0x7a, 0xbf, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x40, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x24, 0x41, 0x63, 0x68, 0x69,
+    0x6c, 0x6c, 0x65, 0x73, 0x2c, 0x48, 0x37, 0x53, 0x31, 0x2c, 0x51, 0x33, 0x35, 0x2c, 0x46, 0x31,
+    0x50, 0x31, 0x30, 0x2e, 0x30, 0x00, 0x24, 0x41, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x2c,
+    0x48, 0x37, 0x53, 0xa5, 0xd7
+};
+
+/*
+01 09 f6 31 2c 51 35 30 2c 46 31 50 31 30 2e 30 00 2c 25 64 00 00 00 00 00 00 00 00 00 00 00 00
+00 10 3e 00 00 00 00 00 00 e0 3f 00 00 00 00 00 00 00 40 00 00 00 00 00 00 1c 40 9a 99 99 99 99
+99 b9 3f 00 00 00 00 00 00 f0 3f 33 33 33 33 33 33 d3 3f 00 00 00 00 00 00 14 40 00 00 00 00 00
+00 54 40 00 00 00 00 00 00 44 40 00 00 80 bf 00 00 80 3f 00 50 c3 47 00 00 00 00 87 44 e7 4a 18
+57 c6 3f 55 94 e7 4a 18 57 b6 3f f8 c1 63 1a dc a5 4c 40 24 25 73 5a 44 41 00 2c 2c 2c 30 30 2c
+30 30 00 24 25 73 47 47 41 00 2c 2c 00 24 50 4e 54 48 30 30 31 00 00 00 70 05 20 d8 72 05 20 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 4a a7
+*/
+const uint8_t g_cfg_cmd9[] = {
+    0x01, 0x09, 0xf6, 0x31, 0x2c, 0x51, 0x35, 0x30, 0x2c, 0x46, 0x31, 0x50, 0x31, 0x30, 0x2e, 0x30,
+    0x00, 0x2c, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x10, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x9a, 0x99, 0x99, 0x99, 0x99,
+    0x99, 0xb9, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33,
+    0x33, 0xd3, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x80, 0xbf, 0x00,
+    0x00, 0x80, 0x3f, 0x00, 0x50, 0xc3, 0x47, 0x00, 0x00, 0x00, 0x00, 0x87, 0x44, 0xe7, 0x4a, 0x18,
+    0x57, 0xc6, 0x3f, 0x55, 0x94, 0xe7, 0x4a, 0x18, 0x57, 0xb6, 0x3f, 0xf8, 0xc1, 0x63, 0x1a, 0xdc,
+    0xa5, 0x4c, 0x40, 0x24, 0x25, 0x73, 0x5a, 0x44, 0x41, 0x00, 0x2c, 0x2c, 0x2c, 0x30, 0x30, 0x2c,
+    0x30, 0x30, 0x00, 0x24, 0x25, 0x73, 0x47, 0x47, 0x41, 0x00, 0x2c, 0x2c, 0x00, 0x24, 0x50, 0x4e,
+    0x54, 0x48, 0x30, 0x30, 0x31, 0x00, 0x00, 0x00, 0x70, 0x05, 0x20, 0xd8, 0x72, 0x05, 0x20, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x4a, 0xa7
+};
+
+/*
+04
+*/
+const uint8_t g_cfg_cmd10[] = {
+    0x04
+};
+
+/*
+51 55 49 54 20
+*/
+const uint8_t g_cfg_cmd11[] = {
+    0x51, 0x55, 0x49, 0x54, 0x20
+};
+
+
+
+// 配置GNSS输出全量NMEA命令:7e 04 13 00 03 00 04 01 00 00 06 00 03 00 02 00 ff 00 7e 
+const uint8_t g_cfg_all_nmea_cmd[]={0x7e,0x04,0x13,0x00,0x03,0x00,0x04,0x01,0x00,0x00,0x06,0x00,0x03,0x00,0x02,0x00,0xff,0x00,0x7e};
+// 调用主控UART接口发送配置GNSS命令,配置输出全量NMEA语句
+
+
+// 启动GNSS串口命令:7e 04 19 00 01 00 03 00 00 00 0c 00 01 00 00 00 01 00 01 00 00 00 00 00 7e 
+const uint8_t g_start_gnss_cmd[] = {0x7e,0x04,0x19,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x0c,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x7e}; 
+// 调用主控UART接口发送启动GNSS命令
+
+
+// 停止GNSS串口命令:7e 04 0d 00 02 00 00 00 00 00 00 00 7e 
+const uint8_t g_stop_gnss_cmd[] = {0x7e,0x04,0x0d,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e}; 
+// 调用主控UART接口发送停止GNSS命令
+
+
+const struct cfg_cmd g_cfg_cmds[] = {
+    { g_cfg_cmd0, sizeof(g_cfg_cmd0) },
+    { g_cfg_cmd1, sizeof(g_cfg_cmd1) },
+    { g_cfg_cmd2, sizeof(g_cfg_cmd2) },
+    { g_cfg_cmd3, sizeof(g_cfg_cmd3) },
+    { g_cfg_cmd4, sizeof(g_cfg_cmd4) },
+    { g_cfg_cmd5, sizeof(g_cfg_cmd5) },
+    { g_cfg_cmd6, sizeof(g_cfg_cmd6) },
+    { g_cfg_cmd7, sizeof(g_cfg_cmd7) },
+    { g_cfg_cmd8, sizeof(g_cfg_cmd8) },
+    { g_cfg_cmd9, sizeof(g_cfg_cmd9) },
+    { g_cfg_cmd10, sizeof(g_cfg_cmd10) },
+    { g_cfg_cmd11, sizeof(g_cfg_cmd11) },
+};
+
+#define GNSS_CFG_SIZE (sizeof(g_cfg_cmds)/sizeof(g_cfg_cmds[0]))
+
+
+errcode_t gnss_get_current_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen)
+{
+    if (cmd_index<GNSS_CFG_SIZE)
+    {
+        *cmdbuf=g_cfg_cmds[cmd_index].content;
+        *cmdlen=g_cfg_cmds[cmd_index].len;
+        return 0;
+    }
+    else
+    {
+        return -1;
+
+    }
+}
+errcode_t gnss_get_nmea_cfg_cmd(uint8_t** cmdbuf,int *cmdlen)
+{
+    *cmdbuf = g_cfg_all_nmea_cmd;
+    *cmdlen = sizeof(g_cfg_all_nmea_cmd);
+    return 0;
+}
+
+errcode_t gnss_get_stop_cmd(uint8_t** cmdbuf,int *cmdlen)
+{
+    *cmdbuf = g_stop_gnss_cmd;
+    *cmdlen = sizeof(g_stop_gnss_cmd);
+    return 0;
+}
+errcode_t gnss_get_start_cmd(uint8_t** cmdbuf,int *cmdlen)
+{
+    *cmdbuf = g_start_gnss_cmd;
+    *cmdlen = sizeof(g_start_gnss_cmd);
+    return 0;
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c b/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c
new file mode 100644 (file)
index 0000000..ce8914b
--- /dev/null
@@ -0,0 +1,205 @@
+// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "driver/uart.h"
+
+#include "pinctrl.h"
+#include "debug_print.h"
+#include "soc_osal.h"
+#include "tcxo.h"
+#include "irmalloc.h"
+#include "errcode.h"
+#include "common_def.h"
+#include "wearable_log.h"
+#include "thread_init.h"
+#include "custom_utils.h"
+#include "gnss_ctl.h"
+#include "gpio.h"
+#include "uart_gnss.h"
+#include "gnss_sample.h"
+
+errcode_t gnss_power_on(void)
+{
+
+     errcode_t ret=0;
+#if defined(BOARD_U8)
+/*
+S_AGPIO_L23  GPS_BAT_ON
+S_AGPIO_L30  GPS_PWRON
+S_AGPIO_L28    GPS_1V8
+*/
+    ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L30,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L30,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L28,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   // gps V3.3 sw en
+    PRINT("GPS_1V8 set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);   // crystal sw
+    PRINT("GPS_BAT_ON  set_value S_AGPIO_L23 GPIO_LEVEL_HIGH  ret %d\n",ret);
+  
+    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_LOW);   //gps reset
+    PRINT("GPS_PWREN set_value S_AGPIO_L30 GPIO_LEVEL_LOW ret %d\n",ret);
+    osDelay(1000);
+    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_HIGH);   //gps reset
+    PRINT("GPS_PWREN set_value S_AGPIO_L30 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+
+#elif defined (BOARD_L22) || defined (BOARD_W9)
+
+    ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+
+    ret=uapi_gpio_set_dir(S_AGPIO_L32,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L20,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_R9,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_HGPIO0,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_HGPIO0, GPIO_LEVEL_HIGH);   // crystal sw
+    PRINT("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
+    
+    ret=uapi_gpio_set_val(S_AGPIO_L20, GPIO_LEVEL_HIGH);   // gps V1.8 sw en
+    PRINT("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_R9, GPIO_LEVEL_HIGH);   // gps V3.3 sw en
+    PRINT("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_LOW);   //gps reset
+    PRINT("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
+
+    osDelay(1000);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_HIGH);   //gps reset
+    PRINT("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    // ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_HIGH);   // crystal sw
+    // PRINT("SWITCH uart to GPS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);
+   
+
+#endif
+    return ERRCODE_SUCC;
+}
+errcode_t gnss_power_off(void)
+{
+    
+     errcode_t ret=0;
+#if defined(BOARD_U8)
+/*
+S_AGPIO_L23  GPS_BAT_ON
+S_AGPIO_L30  GPS_PWRON
+S_AGPIO_L28    GPS_1V8
+*/
+    ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L30,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L30,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);
+    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L28,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);   // crystal sw
+    PRINT("GPS_BAT_ON  set_value S_AGPIO_L23 GPIO_LEVEL_HIGH  ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   // gps V3.3 sw en
+    PRINT("GPS_1V8 set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_LOW);   //gps reset
+    PRINT("GPS_PWRON set_value S_AGPIO_L30 GPIO_LEVEL_LOW ret %d\n",ret);
+
+  
+#elif defined (BOARD_L22) || defined (BOARD_W9)
+
+    ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L32,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_L20,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_AGPIO_R9,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    ret=uapi_gpio_set_dir(S_HGPIO0,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_HGPIO0, GPIO_LEVEL_HIGH);   // crystal sw
+    PRINT("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
+    
+    ret=uapi_gpio_set_val(S_AGPIO_L20, GPIO_LEVEL_HIGH);   // gps V1.8 sw en
+    PRINT("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_R9, GPIO_LEVEL_HIGH);   // gps V3.3 sw en
+    PRINT("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
+
+    ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_LOW);   //gps reset
+    PRINT("GPS_PWRON set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
+
+    // ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_LOW);   // crystal sw
+    // PRINT("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
+  
+#endif
+    return ERRCODE_SUCC;
+}
+
+static uint8_t g_gnss_status=0;
+
+
+errcode_t gnss_start(void)
+{
+    // do_gnss_cmd(GNSS_CMD_WRITEDATA,g_cfg_all_nmea_cmd,sizeof(g_cfg_all_nmea_cmd)); 
+    uint8_t cmd = GNSS_CMD_START;
+    do_gnss_cmd(GNSS_CMD_WRITEDATA, &cmd,1);
+    g_gnss_status = 1;
+    return 0;
+}
+
+errcode_t gnss_stop(void)
+{
+    // uint8_t cmd = GNSS_CMD_STOP;
+    // do_gnss_cmd(GNSS_CMD_WRITEDATA, &cmd,1);
+    // g_gnss_status = 0;
+    GnssServerStop();
+    return 0;
+
+}
+
+uint8_t is_gnss_on(void)
+{
+    return g_gnss_status;
+}
+
+
+errcode_t download_gnss_switch(DOWNLOAD_GPS_SWITCH_T download_gps_switch)
+{
+    errcode_t ret=ERRCODE_SUCC;
+    ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
+    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    
+    if (download_gps_switch == SWITCH_TO_GNSS)
+    {
+        ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_HIGH);   // crystal sw
+        PRINT("SWITCH uart to GNSS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);  
+    }else{
+        ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_LOW);   // crystal sw
+        PRINT("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
+    }
+    return ret;
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/src/nmealist.txt b/code/sdk/drivers/peripheral/gnss/src/nmealist.txt
new file mode 100644 (file)
index 0000000..55412e6
--- /dev/null
@@ -0,0 +1,2276 @@
+$Achilles,H7S1,Q35,F1P26.0,0*72\r
+$Achilles,H7S1,Q35,F1P26.0,0*72\r
+$GNGGA,,,,,,0,,,,,,,,*78\r
+$GNGLL,,,,,,V,N*7A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,42,30,,,41,1*61\r
+$GNRMC,,V,,,,,,,,,E,N,V*72\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,,,,,00,00*56\r
+$PNTH000,2,,-58,3359,,,,,1,1*2C\r
+$PNTH001,0.000000,0.00,0.00,300000.00,1,2,0*1F\r
+$PNTH002,,N,0.000000,0,0,0.000000,0,0.000000*50\r
+$GNGGA,,,,,,0,,,,,,,,*78\r
+$GNGLL,,,,,,V,N*7A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,35,1*67\r
+$GLGSV,1,1,01,81,,,36,1*75\r
+$GBGSV,1,1,02,16,,,38,26,,,41,1*79\r
+$GNRMC,,V,,,,,,,,,E,N,V*72\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,,,,,00,00*56\r
+$PNTH000,2,,-58,3576,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,,N,0.000000,0,0,0.000000,0,0.000000*50\r
+$GNGGA,,,,,,0,,,,,,,,*78\r
+$GNGLL,,,,,,V,N*7A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,33,26,,,35,1*71\r
+$GNRMC,,V,,,,,,,,,E,N,V*72\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,,,,,00,00*56\r
+$PNTH000,2,,-58,3572,,,,,1,1*23\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,,N,0.000000,0,0,0.000000,0,0.000000*50\r
+$GNGGA,,,,,,0,,,,,,,,*78\r
+$GNGLL,,,,,,V,N*7A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,36,26,,,39,1*78\r
+$GNRMC,,V,,,,,,,,,E,N,V*72\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,,,,,00,00*56\r
+$PNTH000,2,,-57,3748,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,,N,0.000000,0,0,0.000000,0,0.000000*50\r
+$GNGGA,095421.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095421.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,36,26,,,39,1*78\r
+$GNRMC,095421.28,V,,,,,,,271221,,E,N,V*58\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095421.28,27,12,2021,00,00*7E\r
+$PNTH000,2,,-58,3362,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095421.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095422.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095422.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,39,1*79\r
+$GNRMC,095422.28,V,,,,,,,271221,,E,N,V*5B\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095422.28,27,12,2021,00,00*7D\r
+$PNTH000,2,,-58,3663,,,,,1,1*20\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095422.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095423.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095423.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,46,30,,,39,1*6A\r
+$GLGSV,1,1,01,81,,,37,1*74\r
+$GBGSV,1,1,02,16,,,36,26,,,40,1*76\r
+$GNRMC,095423.28,V,,,,,,,271221,,E,N,V*5A\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095423.28,27,12,2021,00,00*7C\r
+$PNTH000,2,,-57,3694,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095423.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095424.28,,,,,0,,,,,,,,*52\r
+$GNGLL,,,,,095424.28,V,N*50\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,37,1*74\r
+$GBGSV,1,1,02,16,,,36,26,,,40,1*76\r
+$GNRMC,095424.28,V,,,,,,,271221,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095424.28,27,12,2021,00,00*7B\r
+$PNTH000,2,,-58,3626,,,,,1,1*21\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095424.28,N,0.000000,0,0,0.000000,0,0.000000*7A\r
+$GNGGA,095425.28,,,,,0,,,,,,,,*53\r
+$GNGLL,,,,,095425.28,V,N*51\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,37,1*74\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095425.28,V,,,,,,,271221,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095425.28,27,12,2021,00,00*7A\r
+$PNTH000,2,,-58,3606,,,,,1,1*23\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095425.28,N,0.000000,0,0,0.000000,0,0.000000*7B\r
+$GNGGA,095426.28,,,,,0,,,,,,,,*50\r
+$GNGLL,,,,,095426.28,V,N*52\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,39,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095426.28,V,,,,,,,271221,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095426.28,27,12,2021,00,00*79\r
+$PNTH000,2,,-58,3676,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095426.28,N,0.000000,0,0,0.000000,0,0.000000*78\r
+$GNGGA,095427.28,,,,,0,,,,,,,,*51\r
+$GNGLL,,,,,095427.28,V,N*53\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,47,30,,,38,1*6A\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,36,26,,,39,1*78\r
+$GNRMC,095427.28,V,,,,,,,271221,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095427.28,27,12,2021,00,00*78\r
+$PNTH000,2,,-57,3858,,,,,1,1*29\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095427.28,N,0.000000,0,0,0.000000,0,0.000000*79\r
+$GNGGA,095428.28,,,,,0,,,,,,,,*5E\r
+$GNGLL,,,,,095428.28,V,N*5C\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,46,30,,,38,1*6B\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095428.28,V,,,,,,,271221,,E,N,V*51\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095428.28,27,12,2021,00,00*77\r
+$PNTH000,2,,-57,3761,,,,,1,1*2C\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095428.28,N,0.000000,0,0,0.000000,0,0.000000*76\r
+$GNGGA,095429.28,,,,,0,,,,,,,,*5F\r
+$GNGLL,,,,,095429.28,V,N*5D\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,46,30,,,39,1*6A\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095429.28,V,,,,,,,271221,,E,N,V*50\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095429.28,27,12,2021,00,00*76\r
+$PNTH000,2,,-57,3961,,,,,1,1*22\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095429.28,N,0.000000,0,0,0.000000,0,0.000000*77\r
+$GNGGA,095430.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095430.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,02,07,,,46,30,,,39,1*6A\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095430.28,V,,,,,,,271221,,E,N,V*58\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095430.28,27,12,2021,00,00*7E\r
+$PNTH000,2,,-57,3890,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,5,0*1B\r
+$PNTH002,095430.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095431.28,,,,,0,,,,,,,,*56\r
+$GNGLL,,,,,095431.28,V,N*54\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,26,07,,,46,30,,,38,1*6D\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,11,16,,,37,26,,,40,1*73\r
+$GNRMC,095431.28,V,,,,,,,271221,,E,N,V*59\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095431.28,27,12,2021,00,00*7F\r
+$PNTH000,2,,-56,4156,,,,,1,1*28\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095431.28,N,0.000000,0,0,0.000000,0,0.000000*7E\r
+$GNGGA,095432.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095432.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,26,07,,,46,30,,,38,1*6D\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,09,16,,,37,26,,,40,1*7A\r
+$GNRMC,095432.28,V,,,,,,,271221,,E,N,V*5A\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095432.28,27,12,2021,00,00*7C\r
+$PNTH000,2,,-57,3976,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095432.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095433.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095433.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,,,46,30,,,38,1*6C\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,09,16,,,37,26,,,40,1*7A\r
+$GNRMC,095433.28,V,,,,,,,271221,,E,N,V*5B\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095433.28,27,12,2021,00,00*7D\r
+$PNTH000,2,,-57,3991,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095433.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095434.28,,,,,0,,,,,,,,*53\r
+$GNGLL,,,,,095434.28,V,N*51\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,,,46,30,,,38,1*6C\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,09,16,,,37,26,,,40,1*7A\r
+$GNRMC,095434.28,V,,,,,,,271221,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095434.28,27,12,2021,00,00*7A\r
+$PNTH000,2,,-57,3845,,,,,1,1*25\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095434.28,N,0.000000,0,0,0.000000,0,0.000000*7B\r
+$GNGGA,095435.28,,,,,0,,,,,,,,*52\r
+$GNGLL,,,,,095435.28,V,N*50\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,,,46,30,,,38,1*6C\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,09,16,,,37,26,,,40,1*7A\r
+$GNRMC,095435.28,V,,,,,,,271221,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095435.28,27,12,2021,00,00*7B\r
+$PNTH000,2,,-57,3905,,,,,1,1*20\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095435.28,N,0.000000,0,0,0.000000,0,0.000000*7A\r
+$GNGGA,095436.28,,,,,0,,,,,,,,*51\r
+$GNGLL,,,,,095436.28,V,N*53\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,37,1*6C\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,03,14,,,09,16,,,37,26,,,40,1*7A\r
+$GNRMC,095436.28,V,,,,,,,271221,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095436.28,27,12,2021,00,00*78\r
+$PNTH000,2,,-57,3864,,,,,1,1*26\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095436.28,N,0.000000,0,0,0.000000,0,0.000000*79\r
+$GNGGA,095437.28,,,,,0,,,,,,,,*50\r
+$GNGLL,,,,,095437.28,V,N*52\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,38,1*63\r
+$GLGSV,1,1,01,81,,,38,1*7B\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095437.28,V,,,,,,,271221,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095437.28,27,12,2021,00,00*79\r
+$PNTH000,2,,-57,3791,,,,,1,1*23\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,6,0*18\r
+$PNTH002,095437.28,N,0.000000,0,0,0.000000,0,0.000000*78\r
+$GNGGA,095438.28,,,,,0,,,,,,,,*5F\r
+$GNGLL,,,,,095438.28,V,N*5D\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,37,1*6C\r
+$GLGSV,1,1,02,75,,,29,81,,,39,1*70\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095438.28,V,,,,,,,271221,,E,N,V*50\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095438.28,27,12,2021,00,00*76\r
+$PNTH000,2,,-57,3761,,,,,1,1*2C\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095438.28,N,0.000000,0,0,0.000000,0,0.000000*77\r
+$GNGGA,095439.28,,,,,0,,,,,,,,*5E\r
+$GNGLL,,,,,095439.28,V,N*5C\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,37,1*6C\r
+$GLGSV,1,1,02,75,,,26,81,,,39,1*7F\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095439.28,V,,,,,,,271221,,E,N,V*51\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095439.28,27,12,2021,00,00*77\r
+$PNTH000,2,,-57,3881,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095439.28,N,0.000000,0,0,0.000000,0,0.000000*76\r
+$GNGGA,095440.28,,,,,0,,,,,,,,*50\r
+$GNGLL,,,,,095440.28,V,N*52\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,37,1*6C\r
+$GLGSV,1,1,02,75,,,26,81,,,39,1*7F\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095440.28,V,,,,,,,271221,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095440.28,27,12,2021,00,00*79\r
+$PNTH000,2,,-56,4078,,,,,1,1*25\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095440.28,N,0.000000,0,0,0.000000,0,0.000000*78\r
+$GNGGA,095441.28,,,,,0,,,,,,,,*51\r
+$GNGLL,,,,,095441.28,V,N*53\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,,,46,30,,,37,1*63\r
+$GLGSV,1,1,02,75,,,26,81,,,39,1*7F\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095441.28,V,,,,,,,271221,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095441.28,27,12,2021,00,00*78\r
+$PNTH000,2,,-57,3865,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095441.28,N,0.000000,0,0,0.000000,0,0.000000*79\r
+$GNGGA,095442.28,,,,,0,,,,,,,,*52\r
+$GNGLL,,,,,095442.28,V,N*50\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,,,46,30,,,36,1*62\r
+$GLGSV,1,1,02,75,,,26,81,,,38,1*7E\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095442.28,V,,,,,,,271221,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095442.28,27,12,2021,00,00*7B\r
+$PNTH000,2,,-57,3945,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095442.28,N,0.000000,0,0,0.000000,0,0.000000*7A\r
+$GNGGA,095443.28,,,,,0,,,,,,,,*53\r
+$GNGLL,,,,,095443.28,V,N*51\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,,,45,30,,,36,1*6F\r
+$GLGSV,1,1,02,75,,,27,81,,,38,1*7F\r
+$GBGSV,1,1,02,16,,,37,26,,,40,1*77\r
+$GNRMC,095443.28,V,,,,,,,271221,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095443.28,27,12,2021,00,00*7A\r
+$PNTH000,2,,-57,3691,,,,,1,1*22\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,0*19\r
+$PNTH002,095443.28,N,0.000000,0,0,0.000000,0,0.000000*7B\r
+$GNGGA,095444.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095444.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,45,30,,,36,1*6E\r
+$GLGSV,1,1,02,75,,,27,81,,,39,1*7E\r
+$GBGSV,1,1,02,16,34,205,37,26,55,182,40,1*7C\r
+$GNRMC,095444.28,V,,,,,,,271221,,E,N,V*5B\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095444.28,27,12,2021,00,00*7D\r
+$PNTH000,2,,-57,3892,,,,,1,1*2F\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,2*1B\r
+$PNTH002,095444.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095445.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095445.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,,,46,30,,,36,1*6D\r
+$GLGSV,1,1,02,75,,,28,81,,,38,1*70\r
+$GBGSV,1,1,02,16,34,205,37,26,55,182,40,1*7C\r
+$GNRMC,095445.28,V,,,,,,,271221,,E,N,V*5A\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095445.28,27,12,2021,00,00*7C\r
+$PNTH000,2,,-57,3982,,,,,1,1*2F\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,2*1B\r
+$PNTH002,095445.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095446.28,,,,,0,,,,,,,,*56\r
+$GNGLL,,,,,095446.28,V,N*54\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,,,46,30,,,36,1*6C\r
+$GLGSV,1,1,02,75,,,27,81,,,38,1*7F\r
+$GBGSV,1,1,02,16,34,205,37,26,55,182,40,1*7C\r
+$GNRMC,095446.28,V,,,,,,,271221,,E,N,V*59\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095446.28,27,12,2021,00,00*7F\r
+$PNTH000,2,,-57,3909,,,,,1,1*2C\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,2*1B\r
+$PNTH002,095446.28,N,0.000000,0,0,0.000000,0,0.000000*7E\r
+$GNGGA,095447.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095447.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,,,46,30,,,36,1*6C\r
+$GLGSV,1,1,02,75,,,27,81,,,38,1*7F\r
+$GBGSV,1,1,02,16,34,205,37,26,55,182,40,1*7C\r
+$GNRMC,095447.28,V,,,,,,,271221,,E,N,V*58\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095447.28,27,12,2021,00,00*7E\r
+$PNTH000,2,,-56,4104,,,,,1,1*2F\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,7,2*1B\r
+$PNTH002,095447.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095448.28,,,,,0,,,,,,,,*58\r
+$GNGLL,,,,,095448.28,V,N*5A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,31,203,46,30,,,36,1*5E\r
+$GLGSV,1,1,03,75,,,26,76,,,25,81,,,38,1*79\r
+$GBGSV,1,1,02,16,34,205,38,26,55,182,40,1*73\r
+$GNRMC,095448.28,V,,,,,,,060125,,E,N,V*52\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095448.28,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3761,,,,,1,1*2C\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,8,3*15\r
+$PNTH002,095448.28,N,0.000000,0,0,0.000000,0,0.000000*70\r
+$GNGGA,095449.28,,,,,0,,,,,,,,*59\r
+$GNGLL,,,,,095449.28,V,N*5B\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,27,07,31,203,46,30,,,35,1*52\r
+$GLGSV,1,1,03,75,,,26,76,,,25,81,,,38,1*79\r
+$GBGSV,1,1,03,06,,,37,16,34,205,38,26,55,182,40,1*70\r
+$GNRMC,095449.28,V,,,,,,,060125,,E,N,V*53\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095449.28,06,01,2025,00,00*75\r
+$PNTH000,2,,-58,3631,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,9,3*14\r
+$PNTH002,095449.28,N,0.000000,0,0,0.000000,0,0.000000*71\r
+$GNGGA,095450.28,,,,,0,,,,,,,,*51\r
+$GNGLL,,,,,095450.28,V,N*53\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,31,203,45,30,,,35,1*5E\r
+$GLGSV,1,1,03,75,,,27,76,,,22,81,,,38,1*7F\r
+$GBGSV,2,1,05,03,,,33,05,,,29,06,,,31,16,34,205,38,1*45\r
+$GBGSV,2,2,05,26,55,182,40,1*48\r
+$GNRMC,095450.28,V,,,,,,,060125,,E,N,V*5B\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095450.28,06,01,2025,00,00*7D\r
+$PNTH000,2,,-57,3908,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,11,3*2D\r
+$PNTH002,095450.28,N,0.000000,0,0,0.000000,0,0.000000*79\r
+$GNGGA,095451.28,,,,,0,,,,,,,,*50\r
+$GNGLL,,,,,095451.28,V,N*52\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,31,203,45,30,,,35,1*5E\r
+$GLGSV,1,1,03,75,,,29,76,,,24,81,,,38,1*77\r
+$GBGSV,2,1,06,03,,,30,05,,,25,06,,,34,09,,,29,1*72\r
+$GBGSV,2,2,06,16,34,205,38,26,55,182,40,1*77\r
+$GNRMC,095451.28,V,,,,,,,060125,,E,N,V*5A\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095451.28,06,01,2025,00,00*7C\r
+$PNTH000,2,,-57,3812,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,3*2E\r
+$PNTH002,095451.28,N,0.000000,0,0,0.000000,0,0.000000*78\r
+$GNGGA,095452.28,,,,,0,,,,,,,,*53\r
+$GNGLL,,,,,095452.28,V,N*51\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,28,07,31,203,45,30,,,34,1*5F\r
+$GLGSV,1,1,03,75,,,30,76,,,23,81,,,38,1*78\r
+$GBGSV,2,1,06,03,,,30,05,,,25,06,,,35,09,,,29,1*73\r
+$GBGSV,2,2,06,16,34,205,38,26,55,182,40,1*77\r
+$GNRMC,095452.28,V,,,,,,,060125,,E,N,V*59\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095452.28,06,01,2025,00,00*7F\r
+$PNTH000,2,,-57,3928,,,,,1,1*2F\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,3*2E\r
+$PNTH002,095452.28,N,0.000000,0,0,0.000000,0,0.000000*7B\r
+$GNGGA,095453.28,,,,,0,,,,,,,,*52\r
+$GNGLL,,,,,095453.28,V,N*50\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,,,35,1*5F\r
+$GLGSV,1,1,03,75,,,31,76,,,22,81,,,38,1*78\r
+$GBGSV,2,1,06,03,,,30,05,,,25,06,,,35,09,,,32,1*79\r
+$GBGSV,2,2,06,16,34,205,37,26,55,182,40,1*78\r
+$GNRMC,095453.28,V,,,,,,,060125,,E,N,V*58\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095453.28,06,01,2025,00,00*7E\r
+$PNTH000,2,,-57,3938,,,,,1,1*2E\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,3*2E\r
+$PNTH002,095453.28,N,0.000000,0,0,0.000000,0,0.000000*7A\r
+$GNGGA,095454.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095454.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,42,247,35,1*68\r
+$GLGSV,1,1,03,75,,,31,76,,,21,81,,,38,1*7B\r
+$GBGSV,2,1,06,03,,,30,05,,,25,06,,,35,09,,,32,1*79\r
+$GBGSV,2,2,06,16,34,205,38,26,55,182,40,1*77\r
+$GNRMC,095454.28,V,,,,,,,060125,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095454.28,06,01,2025,00,00*79\r
+$PNTH000,2,,-58,3621,,,,,1,1*26\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095454.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095455.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095455.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,42,247,35,1*68\r
+$GLGSV,1,1,03,75,,,31,76,,,21,81,,,38,1*7B\r
+$GBGSV,2,1,06,03,,,29,05,,,25,06,,,35,09,,,32,1*71\r
+$GBGSV,2,2,06,16,34,205,38,26,55,182,40,1*77\r
+$GNRMC,095455.28,V,,,,,,,060125,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095455.28,06,01,2025,00,00*78\r
+$PNTH000,2,,-58,3742,,,,,1,1*22\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095455.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095456.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095456.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,42,247,34,1*69\r
+$GLGSV,1,1,03,75,,,31,76,,,19,81,,,38,1*70\r
+$GBGSV,2,1,06,03,,,29,05,,,25,06,,,35,09,,,31,1*72\r
+$GBGSV,2,2,06,16,34,205,37,26,55,182,40,1*78\r
+$GNRMC,095456.28,V,,,,,,,060125,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095456.28,06,01,2025,00,00*7B\r
+$PNTH000,2,,-57,3856,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095456.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095457.28,,,,,0,,,,,,,,*56\r
+$GNGLL,,,,,095457.28,V,N*54\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,42,247,34,1*69\r
+$GLGSV,1,1,03,75,,,31,76,,,19,81,,,38,1*70\r
+$GBGSV,2,1,06,03,,,30,05,,,26,06,,,35,09,,,31,1*79\r
+$GBGSV,2,2,06,16,34,205,37,26,55,182,40,1*78\r
+$GNRMC,095457.28,V,,,,,,,060125,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095457.28,06,01,2025,00,00*7A\r
+$PNTH000,2,,-58,3622,,,,,1,1*25\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095457.28,N,0.000000,0,0,0.000000,0,0.000000*7E\r
+$GNGGA,095458.28,,,,,0,,,,,,,,*59\r
+$GNGLL,,,,,095458.28,V,N*5B\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,29,07,31,203,45,30,42,247,34,1*69\r
+$GLGSV,1,1,03,75,,,32,76,,,18,81,,,38,1*72\r
+$GBGSV,2,1,06,03,,,29,05,,,24,06,,,35,09,,,31,1*73\r
+$GBGSV,2,2,06,16,34,205,37,26,55,182,40,1*78\r
+$GNRMC,095458.28,V,,,,,,,060125,,E,N,V*53\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095458.28,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4016,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095458.28,N,0.000000,0,0,0.000000,0,0.000000*71\r
+$GNGGA,095459.28,,,,,0,,,,,,,,*58\r
+$GNGLL,,,,,095459.28,V,N*5A\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,,,30,07,31,203,45,30,42,247,34,1*61\r
+$GLGSV,1,1,03,75,,,32,76,,,17,81,,,37,1*72\r
+$GBGSV,2,1,06,03,,,30,05,,,25,06,,,35,09,,,32,1*79\r
+$GBGSV,2,2,06,16,34,205,38,26,55,182,41,1*76\r
+$GNRMC,095459.28,V,,,,,,,060125,,E,N,V*52\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095459.28,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3856,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,2,12,4*29\r
+$PNTH002,095459.28,N,0.000000,0,0,0.000000,0,0.000000*70\r
+$GNGGA,095500.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095500.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,30,07,43,195,44,30,53,252,34,1*58\r
+$GLGSV,1,1,03,75,,,32,76,,,16,81,,,37,1*73\r
+$GBGSV,2,1,06,03,,,29,05,,,26,06,,,35,09,,,32,1*72\r
+$GBGSV,2,2,06,16,45,198,37,26,64,158,40,1*7C\r
+$GNRMC,095500.28,V,,,,,,,060125,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095500.28,06,01,2025,00,00*79\r
+$PNTH000,2,,-57,3906,,,,,1,1*23\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,12,5*29\r
+$PNTH002,095500.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095501.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095501.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,30,07,43,195,45,30,53,252,33,1*5E\r
+$GLGSV,1,1,03,75,,,32,76,,,14,81,,,37,1*71\r
+$GBGSV,2,1,07,02,,,35,03,,,30,05,,,25,06,,,35,1*74\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095501.28,V,,,,,,,060125,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095501.28,06,01,2025,00,00*78\r
+$PNTH000,2,,-57,3998,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095501.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095502.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095502.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,30,07,43,195,45,30,53,252,34,1*59\r
+$GLGSV,1,1,03,75,,,32,76,,,11,81,,,37,1*74\r
+$GBGSV,2,1,07,02,,,33,03,,,29,05,,,23,06,,,35,1*7C\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095502.28,V,,,,,,,060125,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095502.28,06,01,2025,00,00*7B\r
+$PNTH000,2,,-56,3988,,,,,1,1*24\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095502.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095503.28,,,,,0,,,,,,,,*56\r
+$GNGLL,,,,,095503.28,V,N*54\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,30,07,43,195,45,30,53,252,34,1*59\r
+$GLGSV,1,1,03,75,,,31,76,,,09,81,,,37,1*7E\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,,,35,1*79\r
+$GBGSV,2,2,07,09,,,31,16,45,198,37,26,64,158,40,1*76\r
+$GNRMC,095503.28,V,,,,,,,060125,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095503.28,06,01,2025,00,00*7A\r
+$PNTH000,2,,-57,3858,,,,,1,1*29\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095503.28,N,0.000000,0,0,0.000000,0,0.000000*7E\r
+$GNGGA,095504.28,,,,,0,,,,,,,,*51\r
+$GNGLL,,,,,095504.28,V,N*53\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,30,07,43,195,45,30,53,252,34,1*59\r
+$GLGSV,1,1,03,75,,,32,76,,,09,81,,,37,1*7D\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,,,35,1*7F\r
+$GBGSV,2,2,07,09,,,31,16,45,198,37,26,64,158,40,1*76\r
+$GNRMC,095504.28,V,,,,,,,060125,,E,N,V*5B\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095504.28,06,01,2025,00,00*7D\r
+$PNTH000,2,,-57,3821,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095504.28,N,0.000000,0,0,0.000000,0,0.000000*79\r
+$GNGGA,095505.28,,,,,0,,,,,,,,*50\r
+$GNGLL,,,,,095505.28,V,N*52\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,31,07,43,195,45,30,53,252,34,1*58\r
+$GLGSV,1,1,03,75,,,31,76,,,12,81,,,37,1*74\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,24,06,,,35,1*71\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095505.28,V,,,,,,,060125,,E,N,V*5A\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095505.28,06,01,2025,00,00*7C\r
+$PNTH000,2,,-56,4233,,,,,1,1*28\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095505.28,N,0.000000,0,0,0.000000,0,0.000000*78\r
+$GNGGA,095506.28,,,,,0,,,,,,,,*53\r
+$GNGLL,,,,,095506.28,V,N*51\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,31,07,43,195,45,30,53,252,34,1*58\r
+$GLGSV,1,1,03,75,,,31,76,,,13,81,,,36,1*74\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,24,06,,,35,1*71\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095506.28,V,,,,,,,060125,,E,N,V*59\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095506.28,06,01,2025,00,00*7F\r
+$PNTH000,2,,-56,4174,,,,,1,1*28\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095506.28,N,0.000000,0,0,0.000000,0,0.000000*7B\r
+$GNGGA,095507.28,,,,,0,,,,,,,,*52\r
+$GNGLL,,,,,095507.28,V,N*50\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,32,07,43,195,45,30,53,252,34,1*5B\r
+$GLGSV,1,1,03,75,,,31,76,,,15,81,,,36,1*72\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,,,34,1*78\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095507.28,V,,,,,,,060125,,E,N,V*58\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095507.28,06,01,2025,00,00*7E\r
+$PNTH000,2,,-56,4028,,,,,1,1*20\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,5*28\r
+$PNTH002,095507.28,N,0.000000,0,0,0.000000,0,0.000000*7A\r
+$GNGGA,095508.28,,,,,0,,,,,,,,*5D\r
+$GNGLL,,,,,095508.28,V,N*5F\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,31,07,43,195,45,30,53,252,33,1*5F\r
+$GLGSV,1,1,03,76,,,16,79,,,32,81,29,019,36,1*4D\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,,,35,1*79\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095508.28,V,,,,,,,060125,,E,N,V*57\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095508.28,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3926,,,,,1,1*21\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095508.28,N,0.000000,0,0,0.000000,0,0.000000*75\r
+$GNGGA,095509.28,,,,,0,,,,,,,,*5C\r
+$GNGLL,,,,,095509.28,V,N*5E\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,31,07,43,195,45,30,53,252,33,1*5F\r
+$GLGSV,1,1,03,76,,,17,79,,,32,81,29,019,36,1*4C\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,25,06,,,34,1*71\r
+$GBGSV,2,2,07,09,,,32,16,45,198,36,26,64,158,40,1*74\r
+$GNRMC,095509.28,V,,,,,,,060125,,E,N,V*56\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095509.28,06,01,2025,00,00*70\r
+$PNTH000,2,,-57,3783,,,,,1,1*20\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095509.28,N,0.000000,0,0,0.000000,0,0.000000*74\r
+$GNGGA,095510.28,,,,,0,,,,,,,,*54\r
+$GNGLL,,,,,095510.28,V,N*56\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,31,07,43,195,45,30,53,252,34,1*58\r
+$GLGSV,1,1,03,76,,,17,79,,,32,81,29,019,37,1*4D\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,,,35,1*78\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095510.28,V,,,,,,,060125,,E,N,V*5E\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095510.28,06,01,2025,00,00*78\r
+$PNTH000,2,,-57,3948,,,,,1,1*29\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095510.28,N,0.000000,0,0,0.000000,0,0.000000*7C\r
+$GNGGA,095511.28,,,,,0,,,,,,,,*55\r
+$GNGLL,,,,,095511.28,V,N*57\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,45,30,53,252,34,1*5A\r
+$GLGSV,1,1,03,76,,,17,79,,,33,81,29,019,37,1*4C\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,24,06,,,35,1*71\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095511.28,V,,,,,,,060125,,E,N,V*5F\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095511.28,06,01,2025,00,00*79\r
+$PNTH000,2,,-57,4060,,,,,1,1*2D\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095511.28,N,0.000000,0,0,0.000000,0,0.000000*7D\r
+$GNGGA,095512.28,,,,,0,,,,,,,,*56\r
+$GNGLL,,,,,095512.28,V,N*54\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,45,30,53,252,33,1*5D\r
+$GLGSV,1,1,03,76,,,17,79,,,32,81,29,019,37,1*4D\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,,,35,1*7F\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095512.28,V,,,,,,,060125,,E,N,V*5C\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095512.28,06,01,2025,00,00*7A\r
+$PNTH000,2,,-57,3864,,,,,1,1*26\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095512.28,N,0.000000,0,0,0.000000,0,0.000000*7E\r
+$GNGGA,095513.28,,,,,0,,,,,,,,*57\r
+$GNGLL,,,,,095513.28,V,N*55\r
+$GNGSA,A,1,,,,,,,,,,,,,,,*00\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,45,30,53,252,33,1*5D\r
+$GLGSV,1,1,03,76,,,18,79,,,32,81,29,019,37,1*42\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,,,35,1*78\r
+$GBGSV,2,2,07,09,,,32,16,45,198,37,26,64,158,40,1*75\r
+$GNRMC,095513.28,V,,,,,,,060125,,E,N,V*5D\r
+$GNVTG,,T,,M,,N,,K,N*32\r
+$GNZDA,095513.28,06,01,2025,00,00*7B\r
+$PNTH000,2,,-57,3931,,,,,1,1*27\r
+$PNTH001,0.000000,0.00,0.00,300000.00,3,13,6*2B\r
+$PNTH002,095513.28,N,0.000000,0,0,0.000000,0,0.000000*7F\r
+$GNGGA,095514.28,2235.191702,N,11357.913761,E,1,8,1.5,26.3,M,,M,,*61\r
+$GNGLL,2235.191702,N,11357.913761,E,095514.28,A,A*71\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,1.5,4.4,1*31\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.7,1.5,4.4,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,1.5,4.4,4*3F\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,33,1*5C\r
+$GLGSV,1,1,03,76,,,18,79,,,33,81,29,019,37,1*43\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,25,06,47,200,35,1*41\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095514.28,A,2235.191702,N,11357.913761,E,001.0,121.6,060125,,E,A,V*7C\r
+$GNVTG,121.6,T,121.6,M,001.0,N,001.8,K,A*35\r
+$GNZDA,095514.28,06,01,2025,00,00*7C\r
+$PNTH000,2,,-56,4077,,,,,1,1*2A\r
+$PNTH001,1.529626,4.44,2.85,9.79,0,13,8*14\r
+$PNTH002,095514.28,N,-1329.219164,3,0,0.000000,0,3.000000*65\r
+$GNGGA,095515.28,2235.192040,N,11357.913304,E,1,8,1.5,24.1,M,,M,,*65\r
+$GNGLL,2235.192040,N,11357.913304,E,095515.28,A,A*75\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,1.5,4.4,1*31\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.7,1.5,4.4,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,1.5,4.4,4*3F\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,45,30,53,252,33,1*5C\r
+$GLGSV,1,1,03,76,,,19,79,,,32,81,29,019,38,1*4C\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095515.28,A,2235.192040,N,11357.913304,E,000.2,140.7,060125,,E,A,V*7D\r
+$GNVTG,140.7,T,140.7,M,000.2,N,000.4,K,A*3B\r
+$GNZDA,095515.28,06,01,2025,00,00*7D\r
+$PNTH000,2,,-56,4034,,,,,1,1*2D\r
+$PNTH001,1.529469,4.44,2.85,7.67,0,13,8*1C\r
+$PNTH002,095515.28,N,-1333.239504,3,0,0.000000,0,3.000000*6F\r
+$GNGGA,095516.28,2235.192342,N,11357.913521,E,1,8,1.5,25.5,M,,M,,*63\r
+$GNGLL,2235.192342,N,11357.913521,E,095516.28,A,A*76\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,1.5,4.4,1*31\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.7,1.5,4.4,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,1.5,4.4,4*3F\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,33,1*5D\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,37,1*49\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,31,16,45,198,37,26,64,158,40,1*47\r
+$GNRMC,095516.28,A,2235.192342,N,11357.913521,E,000.2,072.9,060125,,E,A,V*70\r
+$GNVTG,072.9,T,072.9,M,000.2,N,000.4,K,A*3B\r
+$GNZDA,095516.28,06,01,2025,00,00*7E\r
+$PNTH000,2,,-57,3844,,,,,1,1*24\r
+$PNTH001,1.529310,4.44,2.85,8.30,0,13,8*18\r
+$PNTH002,095516.28,N,-1332.144651,3,0,0.000000,0,3.000000*67\r
+$GNGGA,095517.00,2235.191568,N,11357.913427,E,1,8,1.5,35.3,M,,M,,*65\r
+$GNGLL,2235.191568,N,11357.913427,E,095517.00,A,A*77\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,1.5,4.4,1*31\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.7,1.5,4.4,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,1.5,4.4,4*3F\r
+$GPGSV,1,1,04,03,30,125,33,05,,,11,07,43,194,44,30,53,252,33,1*5F\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,38,1*46\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095517.00,A,2235.191568,N,11357.913427,E,000.4,221.5,060125,,E,A,V*7F\r
+$GNVTG,221.5,T,221.5,M,000.4,N,000.7,K,A*3E\r
+$GNZDA,095517.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4119,,,,,1,1*23\r
+$PNTH001,1.529192,4.44,2.85,6.21,0,14,8*19\r
+$PNTH002,095517.00,N,-1331.849248,3,0,0.000000,0,3.000000*67\r
+$GNGGA,095518.00,2235.192007,N,11357.913119,E,1,8,1.5,36.4,M,,M,,*69\r
+$GNGLL,2235.192007,N,11357.913119,E,095518.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,1.5,4.4,1*31\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.7,1.5,4.4,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,1.5,4.4,4*3F\r
+$GPGSV,1,1,04,03,30,125,33,05,,,10,07,43,194,44,30,53,252,33,1*5E\r
+$GLGSV,1,1,03,76,,,20,79,,,31,81,29,019,38,1*45\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,31,16,45,198,37,26,64,158,40,1*47\r
+$GNRMC,095518.00,A,2235.192007,N,11357.913119,E,000.2,266.3,060125,,E,A,V*74\r
+$GNVTG,266.3,T,266.3,M,000.2,N,000.4,K,A*3B\r
+$GNZDA,095518.00,06,01,2025,00,00*7A\r
+$PNTH000,2,,-57,4016,,,,,1,1*2C\r
+$PNTH001,1.529037,4.44,2.85,6.99,0,14,8*14\r
+$PNTH002,095518.00,N,-1331.139606,3,0,0.000000,0,3.000000*68\r
+$GNGGA,095519.00,2235.190482,N,11357.912367,E,1,8,1.5,40.5,M,,M,,*69\r
+$GNGLL,2235.190482,N,11357.912367,E,095519.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.7,1*32\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.0,1.5,3.7,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.7,4*3C\r
+$GPGSV,1,1,04,03,30,125,32,05,,,10,07,43,194,44,30,53,252,33,1*5F\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,38,1*46\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,25,06,47,200,35,1*41\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095519.00,A,2235.190482,N,11357.912367,E,000.4,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.4,N,000.7,K,A*3E\r
+$GNZDA,095519.00,06,01,2025,00,00*7B\r
+$PNTH000,2,,-57,3957,,,,,1,1*27\r
+$PNTH001,1.501216,3.75,2.56,7.47,0,14,8*16\r
+$PNTH002,095519.00,N,-1325.827530,3,0,0.000000,0,0.548195*6B\r
+$GNGGA,095520.00,2235.192178,N,11357.913131,E,1,8,1.6,42.4,M,,M,,*61\r
+$GNGLL,2235.192178,N,11357.913131,E,095520.00,A,A*77\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.1,1.6,3.7,1*30\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.1,1.6,3.7,2*3D\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.1,1.6,3.7,4*3E\r
+$GPGSV,1,1,04,03,30,125,33,05,,,09,07,43,194,45,30,53,252,33,1*57\r
+$GLGSV,1,1,03,76,,,21,79,,,32,81,29,019,38,1*47\r
+$GBGSV,2,1,07,02,,,30,03,,,30,05,,,24,06,47,200,35,1*41\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095520.00,A,2235.192178,N,11357.913131,E,000.3,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.3,N,000.6,K,A*38\r
+$GNZDA,095520.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3835,,,,,1,1*22\r
+$PNTH001,1.647506,3.75,2.57,7.20,0,14,8*11\r
+$PNTH002,095520.00,N,-1326.654916,3,0,0.000000,0,0.555096*6E\r
+$GNGGA,095521.00,2235.191548,N,11357.914100,E,1,8,1.5,44.6,M,,M,,*66\r
+$GNGLL,2235.191548,N,11357.914100,E,095521.00,A,A*77\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.7,1*32\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.0,1.5,3.7,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.7,4*3C\r
+$GPGSV,1,1,04,03,30,125,33,05,,,09,07,43,194,44,30,53,252,33,1*56\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,38,1*46\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,23,06,47,200,35,1*47\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,41,1*45\r
+$GNRMC,095521.00,A,2235.191548,N,11357.914100,E,000.2,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.2,N,000.4,K,A*3B\r
+$GNZDA,095521.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-56,4017,,,,,1,1*2C\r
+$PNTH001,1.501017,3.75,2.56,6.93,0,14,8*1D\r
+$PNTH002,095521.00,N,-1324.706200,3,0,0.000000,0,0.587450*66\r
+$GNGGA,095522.00,2235.191591,N,11357.914707,E,1,8,2.8,45.8,M,,M,,*61\r
+$GNGLL,2235.191591,N,11357.914707,E,095522.00,A,A*71\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,04,03,30,125,33,05,,,09,07,43,194,44,30,53,252,33,1*56\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,39,1*47\r
+$GBGSV,2,1,08,02,,,31,03,,,30,05,,,24,06,47,200,35,1*4F\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,40,43,,,37,1*48\r
+$GNRMC,095522.00,A,2235.191591,N,11357.914707,E,000.4,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.4,N,000.7,K,A*3E\r
+$GNZDA,095522.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-56,4228,,,,,1,1*22\r
+$PNTH001,2.758240,4.45,3.91,7.17,0,15,8*12\r
+$PNTH002,095522.00,N,-1326.533042,3,0,0.000000,0,0.364265*6C\r
+$GNGGA,095523.00,2235.191505,N,11357.915057,E,1,8,2.8,46.5,M,,M,,*60\r
+$GNGLL,2235.191505,N,11357.915057,E,095523.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,33,1*5D\r
+$GLGSV,1,1,03,76,,,20,79,,,32,81,29,019,38,1*46\r
+$GBGSV,2,1,08,02,,,31,03,,,29,05,,,25,06,47,200,35,1*46\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,41,43,,,11,1*4D\r
+$GNRMC,095523.00,A,2235.191505,N,11357.915057,E,000.4,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.4,N,000.8,K,A*31\r
+$GNZDA,095523.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-56,4087,,,,,1,1*25\r
+$PNTH001,2.758421,4.46,3.91,6.95,0,14,8*1A\r
+$PNTH002,095523.00,N,-1322.114483,3,0,0.000000,0,0.839904*6E\r
+$GNGGA,095524.00,2235.191688,N,11357.915144,E,1,8,1.5,46.2,M,,M,,*6B\r
+$GNGLL,2235.191688,N,11357.915144,E,095524.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.7,1*32\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.0,1.5,3.7,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.7,4*3C\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,33,1*5D\r
+$GLGSV,1,1,03,76,,,20,79,,,31,81,29,019,38,1*45\r
+$GBGSV,2,1,08,02,,,30,03,,,29,05,,,23,06,47,200,35,1*41\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,40,43,,,09,1*45\r
+$GNRMC,095524.00,A,2235.191688,N,11357.915144,E,000.4,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.4,N,000.8,K,A*31\r
+$GNZDA,095524.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-57,3863,,,,,1,1*21\r
+$PNTH001,1.500719,3.75,2.56,6.91,0,14,8*17\r
+$PNTH002,095524.00,N,-1321.943265,3,0,0.000000,0,0.384274*6F\r
+$GNGGA,095525.00,2235.191863,N,11357.915201,E,1,8,1.5,47.1,M,,M,,*61\r
+$GNGLL,2235.191863,N,11357.915201,E,095525.00,A,A*74\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.7,1*32\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.0,1.5,3.7,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.7,4*3C\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,32,1*5C\r
+$GLGSV,1,1,03,76,,,20,79,,,31,81,29,019,38,1*45\r
+$GBGSV,2,1,08,02,,,31,03,,,30,05,,,22,06,47,200,35,1*49\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,40,43,,,09,1*45\r
+$GNRMC,095525.00,A,2235.191863,N,11357.915201,E,000.3,068.3,060125,,E,A,V*72\r
+$GNVTG,068.3,T,068.3,M,000.3,N,000.5,K,A*3B\r
+$GNZDA,095525.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3948,,,,,1,1*29\r
+$PNTH001,1.500622,3.75,2.56,6.93,0,14,8*1C\r
+$PNTH002,095525.00,N,-1320.941502,3,0,0.000000,0,0.228857*67\r
+$GNGGA,095526.00,2235.192041,N,11357.915289,E,1,8,2.8,48.0,M,,M,,*69\r
+$GNGLL,2235.192041,N,11357.915289,E,095526.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,32,1*5C\r
+$GLGSV,1,1,03,76,,,21,79,,,31,81,29,019,39,1*45\r
+$GBGSV,2,1,08,02,,,30,03,,,29,05,,,25,06,47,200,35,1*47\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,38,26,64,158,40,43,,,09,1*4A\r
+$GNRMC,095526.00,A,2235.192041,N,11357.915289,E,000.2,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.2,N,000.3,K,A*3C\r
+$GNZDA,095526.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-55,4359,,,,,1,1*26\r
+$PNTH001,2.758968,4.46,3.91,7.12,0,14,8*14\r
+$PNTH002,095526.00,N,-1319.084677,3,0,0.000000,0,0.358292*6A\r
+$GNGGA,095527.00,2235.192123,N,11357.915288,E,1,8,2.8,48.5,M,,M,,*69\r
+$GNGLL,2235.192123,N,11357.915288,E,095527.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,32,1*5D\r
+$GLGSV,1,1,03,76,,,20,79,,,31,81,29,019,39,1*44\r
+$GBGSV,2,1,08,02,,,30,03,,,29,05,,,24,06,47,200,35,1*46\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,40,43,,,09,1*45\r
+$GNRMC,095527.00,A,2235.192123,N,11357.915288,E,000.3,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.3,N,000.5,K,A*3B\r
+$GNZDA,095527.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4050,,,,,1,1*2F\r
+$PNTH001,2.759148,4.46,3.91,7.36,0,14,8*19\r
+$PNTH002,095527.00,N,-1318.200480,3,0,0.000000,0,0.354736*69\r
+$GNGGA,095528.00,2235.192188,N,11357.915118,E,1,8,2.8,48.9,M,,M,,*61\r
+$GNGLL,2235.192188,N,11357.915118,E,095528.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,32,1*5C\r
+$GLGSV,1,1,03,76,,,21,79,,,32,81,29,019,39,1*46\r
+$GBGSV,2,1,08,02,,,30,03,,,29,05,,,23,06,47,200,35,1*41\r
+$GBGSV,2,2,08,09,56,222,32,16,45,198,37,26,64,158,40,43,,,09,1*45\r
+$GNRMC,095528.00,A,2235.192188,N,11357.915118,E,000.9,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.9,N,001.7,K,A*32\r
+$GNZDA,095528.00,06,01,2025,00,00*79\r
+$PNTH000,2,,-58,3578,,,,,1,1*29\r
+$PNTH001,2.759322,4.46,3.91,7.47,0,14,8*11\r
+$PNTH002,095528.00,N,-1320.161460,3,0,0.000000,0,0.458204*68\r
+$GNGGA,095529.00,2235.192188,N,11357.915118,E,1,8,1.5,48.9,M,,M,,*6E\r
+$GNGLL,2235.192188,N,11357.915118,E,095529.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.7,1*32\r
+$GNGSA,A,3,81,,,,,,,,,,,,4.0,1.5,3.7,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.7,4*3C\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,32,1*5D\r
+$GLGSV,1,1,03,76,,,21,79,,,32,81,29,019,38,1*47\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,26,06,47,200,35,1*4A\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,41,1*45\r
+$GNRMC,095529.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095529.00,06,01,2025,00,00*78\r
+$PNTH000,2,,-58,3592,,,,,1,1*2D\r
+$PNTH001,1.500227,3.75,2.56,7.47,0,13,8*12\r
+$PNTH002,095529.00,N,-1317.973083,3,0,0.000000,0,0.458204*6F\r
+$GNGGA,095530.00,2235.192188,N,11357.915118,E,1,8,2.8,48.9,M,,M,,*68\r
+$GNGLL,2235.192188,N,11357.915118,E,095530.00,A,A*74\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,31,1*5E\r
+$GLGSV,1,1,03,76,,,21,79,,,31,81,29,019,38,1*44\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,37,26,64,158,40,1*45\r
+$GNRMC,095530.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095530.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-57,3969,,,,,1,1*2A\r
+$PNTH001,2.759702,4.46,3.92,7.47,0,13,8*13\r
+$PNTH002,095530.00,N,-1316.299386,3,0,0.000000,0,0.458204*6F\r
+$GNGGA,095531.00,2235.192188,N,11357.915118,E,1,8,2.8,48.9,M,,M,,*69\r
+$GNGLL,2235.192188,N,11357.915118,E,095531.00,A,A*75\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,32,1*5D\r
+$GLGSV,1,1,03,76,,,21,79,,,32,81,29,019,38,1*47\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,37,26,64,158,40,1*44\r
+$GNRMC,095531.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095531.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3770,,,,,1,1*2C\r
+$PNTH001,2.759887,4.46,3.92,7.47,0,13,8*11\r
+$PNTH002,095531.00,N,-1313.590477,3,0,0.000000,0,0.458204*6C\r
+$GNGGA,095532.00,2235.192188,N,11357.915118,E,1,8,2.8,48.9,M,,M,,*6A\r
+$GNGLL,2235.192188,N,11357.915118,E,095532.00,A,A*76\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.2,2.8,4.5,1*3A\r
+$GNGSA,A,3,81,,,,,,,,,,,,5.2,2.8,4.5,2*37\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.2,2.8,4.5,4*34\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,43,30,53,252,32,1*5B\r
+$GLGSV,1,1,03,76,,,21,79,,,32,81,29,019,38,1*47\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,32,16,45,198,38,26,64,158,40,1*4B\r
+$GNRMC,095532.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*73\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095532.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-57,3814,,,,,1,1*21\r
+$PNTH001,2.760064,4.46,3.92,7.47,0,13,8*1E\r
+$PNTH002,095532.00,N,-1311.374216,3,0,0.000000,0,0.458204*60\r
+$GNGGA,095533.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*64\r
+$GNGLL,2235.192188,N,11357.915118,E,095533.00,A,A*77\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,31,1*5F\r
+$GLGSV,1,1,03,76,,,21,79,72,112,32,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,25,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095533.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*72\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095533.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-57,3722,,,,,1,1*2B\r
+$PNTH001,1.499836,3.75,2.56,7.47,0,13,9*18\r
+$PNTH002,095533.00,N,-1310.789916,3,0,0.000000,0,0.458204*6D\r
+$GNGGA,095534.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*63\r
+$GNGLL,2235.192188,N,11357.915118,E,095534.00,A,A*70\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,31,1*5E\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,37,1*7C\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,24,06,47,200,35,1*40\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,37,26,64,158,41,1*44\r
+$GNRMC,095534.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*75\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095534.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3894,,,,,1,1*29\r
+$PNTH001,1.499735,3.75,2.56,7.47,0,13,9*14\r
+$PNTH002,095534.00,N,-1311.380670,3,0,0.000000,0,0.458204*69\r
+$GNGGA,095535.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*62\r
+$GNGLL,2235.192188,N,11357.915118,E,095535.00,A,A*71\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,31,1*5F\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095535.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*74\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095535.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4227,,,,,1,1*2D\r
+$PNTH001,1.499639,3.75,2.56,7.47,0,13,9*19\r
+$PNTH002,095535.00,N,-1309.078971,3,0,0.000000,0,0.458204*6B\r
+$GNGGA,095536.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*61\r
+$GNGLL,2235.192188,N,11357.915118,E,095536.00,A,A*72\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,31,1*5F\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,37,1*7C\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095536.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*77\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095536.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-57,3872,,,,,1,1*21\r
+$PNTH001,1.499541,3.75,2.56,7.47,0,13,9*15\r
+$PNTH002,095536.00,N,-1306.980320,3,0,0.000000,0,0.458204*67\r
+$GNGGA,095537.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*60\r
+$GNGLL,2235.192188,N,11357.915118,E,095537.00,A,A*73\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,31,1*5E\r
+$GLGSV,1,1,03,76,,,23,79,72,112,31,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095537.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*76\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095537.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-56,3936,,,,,1,1*21\r
+$PNTH001,1.499443,3.75,2.56,7.47,0,13,9*16\r
+$PNTH002,095537.00,N,-1305.397278,3,0,0.000000,0,0.458204*65\r
+$GNGGA,095538.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*6F\r
+$GNGLL,2235.192188,N,11357.915118,E,095538.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,31,1*5E\r
+$GLGSV,1,1,03,76,,,21,79,72,112,32,81,29,019,37,1*7F\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,26,06,47,200,35,1*4A\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095538.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095538.00,06,01,2025,00,00*78\r
+$PNTH000,2,,-56,4201,,,,,1,1*29\r
+$PNTH001,1.499340,3.75,2.56,7.47,0,13,9*12\r
+$PNTH002,095538.00,N,-1305.174224,3,0,0.000000,0,0.458204*6C\r
+$GNGGA,095539.00,2235.192188,N,11357.915118,E,1,9,1.5,48.9,M,,M,,*6E\r
+$GNGLL,2235.192188,N,11357.915118,E,095539.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,32,1*5D\r
+$GLGSV,1,1,03,76,,,22,79,72,112,31,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,30,03,,,30,05,,,24,06,47,200,35,1*41\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095539.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095539.00,06,01,2025,00,00*79\r
+$PNTH000,2,,-57,3987,,,,,1,1*2A\r
+$PNTH001,1.499247,3.75,2.56,7.47,0,13,9*14\r
+$PNTH002,095539.00,N,-1304.837718,3,0,0.000000,0,0.458204*68\r
+$GNGGA,095540.00,2235.192188,N,11357.915118,E,1,9,1.6,48.9,M,,M,,*63\r
+$GNGLL,2235.192188,N,11357.915118,E,095540.00,A,A*73\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.1,1.6,3.8,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.1,1.6,3.8,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.1,1.6,3.8,4*31\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,32,1*5D\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,37,1*7C\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095540.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*76\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095540.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-57,3806,,,,,1,1*22\r
+$PNTH001,1.644100,3.75,2.56,7.47,0,13,9*16\r
+$PNTH002,095540.00,N,-1304.108404,3,0,0.000000,0,0.458204*6D\r
+$GNGGA,095541.00,2235.192188,N,11357.915118,E,1,9,1.6,48.9,M,,M,,*62\r
+$GNGLL,2235.192188,N,11357.915118,E,095541.00,A,A*72\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.1,1.6,3.8,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.1,1.6,3.8,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.1,1.6,3.8,4*31\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,252,31,1*5E\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095541.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*77\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095541.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4101,,,,,1,1*2A\r
+$PNTH001,1.643931,3.75,2.56,7.47,0,13,9*1B\r
+$PNTH002,095541.00,N,-1303.960158,3,0,0.000000,0,0.458204*61\r
+$GNGGA,095542.00,2235.192188,N,11357.915118,E,1,9,2.0,48.9,M,,M,,*64\r
+$GNGLL,2235.192188,N,11357.915118,E,095542.00,A,A*71\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,252,32,1*5C\r
+$GLGSV,1,1,03,76,,,23,79,72,112,32,81,29,019,37,1*7D\r
+$GBGSV,2,1,07,02,,,30,03,,,30,05,,,24,06,47,200,35,1*41\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095542.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*74\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095542.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4117,,,,,1,1*2D\r
+$PNTH001,1.983476,4.08,2.84,7.47,0,13,9*14\r
+$PNTH002,095542.00,N,-1302.510001,3,0,0.000000,0,0.458204*65\r
+$GNGGA,095543.00,2235.192188,N,11357.915118,E,1,9,2.0,48.9,M,,M,,*65\r
+$GNGLL,2235.192188,N,11357.915118,E,095543.00,A,A*70\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,31,1*5D\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095543.00,A,2235.192188,N,11357.915118,E,000.0,068.3,060125,,E,A,V*75\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095543.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-56,4220,,,,,1,1*2A\r
+$PNTH001,1.983468,4.08,2.84,7.47,0,13,9*1B\r
+$PNTH002,095543.00,N,-1302.338584,3,0,0.000000,0,0.458204*60\r
+$GNGGA,095544.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*63\r
+$GNGLL,2235.192005,N,11357.915065,E,095544.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,31,1*5D\r
+$GLGSV,1,1,03,76,,,23,79,72,112,31,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,35,1*4E\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095544.00,A,2235.192005,N,11357.915065,E,000.7,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.7,N,001.3,K,A*38\r
+$GNZDA,095544.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-57,3973,,,,,1,1*21\r
+$PNTH001,1.983459,4.08,2.84,7.38,0,13,9*11\r
+$PNTH002,095544.00,N,-1300.949391,3,0,0.000000,0,0.340486*69\r
+$GNGGA,095545.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*62\r
+$GNGLL,2235.192005,N,11357.915065,E,095545.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,31,1*5E\r
+$GLGSV,1,1,03,76,,,23,79,72,112,31,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095545.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095545.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-56,4081,,,,,1,1*23\r
+$PNTH001,1.983451,4.08,2.84,7.38,0,13,9*19\r
+$PNTH002,095545.00,N,-1300.905092,3,0,0.000000,0,0.340486*60\r
+$GNGGA,095546.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*6A\r
+$GNGLL,2235.192005,N,11357.915065,E,095546.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.6,1.8,3.1,1*38\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.6,1.8,3.1,2*3B\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.6,1.8,3.1,4*36\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,30,1*5F\r
+$GLGSV,1,1,03,76,,,22,79,72,112,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095546.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095546.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3946,,,,,1,1*27\r
+$PNTH001,1.794984,3.08,2.28,7.38,0,13,9*15\r
+$PNTH002,095546.00,N,-1299.819625,3,0,0.000000,0,0.340486*64\r
+$GNGGA,095547.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*6B\r
+$GNGLL,2235.192005,N,11357.915065,E,095547.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.6,1.8,3.1,1*38\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.6,1.8,3.1,2*3B\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.6,1.8,3.1,4*36\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,30,1*5F\r
+$GLGSV,1,1,03,76,,,20,79,72,112,32,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,35,1*4E\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095547.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095547.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-56,4250,,,,,1,1*2D\r
+$PNTH001,1.794924,3.08,2.28,7.38,0,13,9*1F\r
+$PNTH002,095547.00,N,-1299.285585,3,0,0.000000,0,0.340486*63\r
+$GNGGA,095548.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*6F\r
+$GNGLL,2235.192005,N,11357.915065,E,095548.00,A,A*74\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,31,1*5E\r
+$GLGSV,1,1,03,76,,,23,79,72,112,33,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,35,1*4E\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095548.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095548.00,06,01,2025,00,00*7F\r
+$PNTH000,2,,-56,3967,,,,,1,1*25\r
+$PNTH001,1.273751,2.51,1.84,7.38,0,13,9*17\r
+$PNTH002,095548.00,N,-1298.664687,3,0,0.000000,0,0.340486*67\r
+$GNGGA,095549.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*6E\r
+$GNGLL,2235.192005,N,11357.915065,E,095549.00,A,A*75\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,30,1*5F\r
+$GLGSV,1,1,03,76,,,21,79,72,112,32,81,29,019,39,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095549.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095549.00,06,01,2025,00,00*7E\r
+$PNTH000,2,,-56,4065,,,,,1,1*29\r
+$PNTH001,1.273732,2.51,1.84,7.38,0,13,9*12\r
+$PNTH002,095549.00,N,-1297.827693,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095550.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*66\r
+$GNGLL,2235.192005,N,11357.915065,E,095550.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,31,07,43,194,44,30,53,251,30,1*5F\r
+$GLGSV,1,1,03,76,,,21,79,72,112,32,81,29,019,39,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095550.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095550.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4017,,,,,1,1*2C\r
+$PNTH001,1.273712,2.51,1.84,7.38,0,13,9*10\r
+$PNTH002,095550.00,N,-1296.560957,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095551.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095551.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,24,79,72,112,32,81,29,019,39,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,41,1*4B\r
+$GNRMC,095551.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095551.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-56,4001,,,,,1,1*2B\r
+$PNTH001,1.273693,2.51,1.84,7.38,0,13,9*18\r
+$PNTH002,095551.00,N,-1296.437861,3,0,0.000000,0,0.340486*63\r
+$GNGGA,095552.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*6F\r
+$GNGLL,2235.192005,N,11357.915065,E,095552.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.7,1.8,3.2,1*3A\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.7,1.8,3.2,2*39\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.7,1.8,3.2,4*34\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,22,79,72,113,32,81,29,019,39,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095552.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095552.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-56,3957,,,,,1,1*26\r
+$PNTH001,1.830441,3.18,2.38,7.38,0,13,9*10\r
+$PNTH002,095552.00,N,-1294.764743,3,0,0.000000,0,0.340486*68\r
+$GNGGA,095553.00,2235.192005,N,11357.915065,E,1,9,5.2,47.8,M,,M,,*60\r
+$GNGLL,2235.192005,N,11357.915065,E,095553.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,14.3,5.2,13.3,1*36\r
+$GNGSA,A,3,79,81,,,,,,,,,,,14.3,5.2,13.3,2*35\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,14.3,5.2,13.3,4*38\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,23,79,72,113,32,81,29,019,39,1*72\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095553.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095553.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4029,,,,,1,1*21\r
+$PNTH001,5.217188,13.32,12.97,7.38,0,13,9*16\r
+$PNTH002,095553.00,N,-1294.409944,3,0,0.000000,0,0.340486*68\r
+$GNGGA,095554.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*62\r
+$GNGLL,2235.192005,N,11357.915065,E,095554.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,25,79,72,113,32,81,29,019,39,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,158,40,1*4A\r
+$GNRMC,095554.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095554.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-55,4278,,,,,1,1*24\r
+$PNTH001,1.273635,2.51,1.84,7.38,0,13,9*14\r
+$PNTH002,095554.00,N,-1294.005193,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095555.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*63\r
+$GNGLL,2235.192005,N,11357.915065,E,095555.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,30,125,32,07,43,194,44,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,23,79,72,113,32,81,29,019,40,1*7C\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,21,06,47,200,35,1*4C\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095555.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095555.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-57,3950,,,,,1,1*20\r
+$PNTH001,1.273616,2.51,1.84,7.38,0,13,9*15\r
+$PNTH002,095555.00,N,-1293.266581,3,0,0.000000,0,0.340486*63\r
+$GNGGA,095556.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*60\r
+$GNGLL,2235.192005,N,11357.915065,E,095556.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,251,31,1*5C\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095556.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095556.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-57,3833,,,,,1,1*24\r
+$PNTH001,1.983356,4.08,2.84,7.38,0,13,9*19\r
+$PNTH002,095556.00,N,-1292.507725,3,0,0.000000,0,0.340486*6D\r
+$GNGGA,095557.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*61\r
+$GNGLL,2235.192005,N,11357.915065,E,095557.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,44,30,53,251,31,1*5C\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095557.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095557.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3812,,,,,1,1*27\r
+$PNTH001,1.983347,4.08,2.83,7.38,0,13,9*1E\r
+$PNTH002,095557.00,N,-1292.174511,3,0,0.000000,0,0.340486*69\r
+$GNGGA,095558.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*65\r
+$GNGLL,2235.192005,N,11357.915065,E,095558.00,A,A*75\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.6,1.8,3.1,1*38\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.6,1.8,3.1,2*3B\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.6,1.8,3.1,4*36\r
+$GPGSV,1,1,03,03,30,125,33,07,43,194,43,30,53,251,31,1*5B\r
+$GLGSV,1,1,03,76,,,24,79,72,113,32,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,29,03,,,29,05,,,23,06,47,200,36,1*45\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095558.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095558.00,06,01,2025,00,00*7E\r
+$PNTH000,2,,-56,4099,,,,,1,1*2A\r
+$PNTH001,1.794253,3.07,2.28,7.38,0,13,9*1B\r
+$PNTH002,095558.00,N,-1289.654480,3,0,0.000000,0,0.340486*60\r
+$GNGGA,095559.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*64\r
+$GNGLL,2235.192005,N,11357.915065,E,095559.00,A,A*74\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.6,1.8,3.1,1*38\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.6,1.8,3.1,2*3B\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.6,1.8,3.1,4*36\r
+$GPGSV,1,1,03,03,30,125,34,07,43,194,44,30,53,251,30,1*5A\r
+$GLGSV,1,1,03,76,,,24,79,72,113,32,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,23,06,47,200,35,1*4F\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095559.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095559.00,06,01,2025,00,00*7F\r
+$PNTH000,2,,-56,4206,,,,,1,1*2E\r
+$PNTH001,1.794191,3.07,2.28,7.38,0,13,9*16\r
+$PNTH002,095559.00,N,-1290.859737,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095600.00,2235.192005,N,11357.915065,E,1,9,1.9,47.8,M,,M,,*6A\r
+$GNGLL,2235.192005,N,11357.915065,E,095600.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.9,3.5,1*3C\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.9,3.5,2*3F\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.9,3.5,4*32\r
+$GPGSV,1,1,03,03,30,125,34,07,43,194,43,30,53,251,30,1*5D\r
+$GLGSV,1,1,03,76,,,25,79,72,113,32,81,29,019,39,1*74\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,24,06,47,200,35,1*49\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095600.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095600.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-56,4055,,,,,1,1*2A\r
+$PNTH001,1.946650,3.52,2.63,7.38,0,13,9*12\r
+$PNTH002,095600.00,N,-1290.274610,3,0,0.000000,0,0.340486*6B\r
+$GNGGA,095601.00,2235.192005,N,11357.915065,E,1,9,5.2,47.8,M,,M,,*64\r
+$GNGLL,2235.192005,N,11357.915065,E,095601.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,14.3,5.2,13.3,1*36\r
+$GNGSA,A,3,79,81,,,,,,,,,,,14.3,5.2,13.3,2*35\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,14.3,5.2,13.3,4*38\r
+$GPGSV,1,1,03,03,30,125,34,07,43,194,44,30,53,251,30,1*5A\r
+$GLGSV,1,1,03,76,,,24,79,72,113,32,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095601.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095601.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-55,4383,,,,,1,1*21\r
+$PNTH001,5.231278,13.33,12.97,7.38,0,13,9*1F\r
+$PNTH002,095601.00,N,-1288.513155,3,0,0.000000,0,0.340486*63\r
+$GNGGA,095602.00,2235.192005,N,11357.915065,E,1,9,5.2,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095602.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,14.3,5.2,13.3,1*36\r
+$GNGSA,A,3,79,81,,,,,,,,,,,14.3,5.2,13.3,2*35\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,14.3,5.2,13.3,4*38\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,44,30,53,251,30,1*5B\r
+$GLGSV,1,1,03,76,,,24,79,72,113,32,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,35,1*48\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095602.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095602.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-58,3648,,,,,1,1*29\r
+$PNTH001,5.233540,13.33,12.98,7.38,0,13,9*1E\r
+$PNTH002,095602.00,N,-1287.901866,3,0,0.000000,0,0.340486*69\r
+$GNGGA,095603.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*63\r
+$GNGLL,2235.192005,N,11357.915065,E,095603.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,44,30,53,251,30,1*5B\r
+$GLGSV,1,1,03,76,,,25,79,72,113,32,81,29,019,39,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,36,1*4D\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,38,26,64,159,40,1*4C\r
+$GNRMC,095603.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095603.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-56,3986,,,,,1,1*2A\r
+$PNTH001,1.273467,2.51,1.84,7.38,0,13,9*11\r
+$PNTH002,095603.00,N,-1286.481526,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095604.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*64\r
+$GNGLL,2235.192005,N,11357.915065,E,095604.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,24,79,72,113,32,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095604.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095604.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-55,4303,,,,,1,1*29\r
+$PNTH001,1.273449,2.51,1.84,7.38,0,13,9*1D\r
+$PNTH002,095604.00,N,-1285.584029,3,0,0.000000,0,0.340486*6F\r
+$GNGGA,095605.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*65\r
+$GNGLL,2235.192005,N,11357.915065,E,095605.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095605.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095605.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-55,4379,,,,,1,1*24\r
+$PNTH001,1.273430,2.51,1.84,7.38,0,13,9*13\r
+$PNTH002,095605.00,N,-1285.260630,3,0,0.000000,0,0.340486*6D\r
+$GNGGA,095606.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*6D\r
+$GNGLL,2235.192005,N,11357.915065,E,095606.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.6,1.8,3.1,1*38\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.6,1.8,3.1,2*3B\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.6,1.8,3.1,4*36\r
+$GPGSV,1,1,03,03,31,125,35,07,43,194,43,30,53,251,30,1*5D\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,39,1*75\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095606.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095606.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4261,,,,,1,1*2F\r
+$PNTH001,1.793762,3.07,2.27,7.38,0,13,9*14\r
+$PNTH002,095606.00,N,-1284.645639,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095607.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095607.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,31,125,35,07,43,194,43,30,53,251,30,1*5D\r
+$GLGSV,1,1,03,76,,,26,79,72,113,33,81,29,019,38,1*77\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,35,1*4E\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095607.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095607.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-57,3971,,,,,1,1*23\r
+$PNTH001,1.983266,4.07,2.83,7.38,0,13,9*13\r
+$PNTH002,095607.00,N,-1284.019262,3,0,0.000000,0,0.340486*61\r
+$GNGGA,095608.00,2235.192005,N,11357.915065,E,1,9,2.0,47.8,M,,M,,*68\r
+$GNGLL,2235.192005,N,11357.915065,E,095608.00,A,A*73\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,26,79,72,113,32,81,29,019,38,1*76\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,38,26,64,159,40,1*4C\r
+$GNRMC,095608.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*76\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095608.00,06,01,2025,00,00*78\r
+$PNTH000,2,,-56,4107,,,,,1,1*2C\r
+$PNTH001,1.983258,4.07,2.83,7.38,0,13,9*1E\r
+$PNTH002,095608.00,N,-1283.069121,3,0,0.000000,0,0.340486*6A\r
+$GNGGA,095609.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*69\r
+$GNGLL,2235.192005,N,11357.915065,E,095609.00,A,A*72\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,26,79,72,113,33,81,29,019,38,1*77\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095609.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*77\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095609.00,06,01,2025,00,00*79\r
+$PNTH000,2,,-56,4088,,,,,1,1*2A\r
+$PNTH001,1.273359,2.51,1.84,7.38,0,13,9*1B\r
+$PNTH002,095609.00,N,-1282.692296,3,0,0.000000,0,0.340486*67\r
+$GNGGA,095610.00,2235.192005,N,11357.915065,E,1,9,1.5,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095610.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.0,1.5,3.8,1*3D\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.0,1.5,3.8,2*3E\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.0,1.5,3.8,4*33\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,29,1*54\r
+$GLGSV,1,1,03,76,,,26,79,72,113,33,81,29,019,38,1*77\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095610.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095610.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-56,4157,,,,,1,1*29\r
+$PNTH001,1.496223,3.76,2.56,7.38,0,13,9*12\r
+$PNTH002,095610.00,N,-1281.179479,3,0,0.000000,0,0.340486*69\r
+$GNGGA,095611.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*60\r
+$GNGLL,2235.192005,N,11357.915065,E,095611.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,26,79,72,113,34,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,24,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,38,26,64,159,40,1*4C\r
+$GNRMC,095611.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095611.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-55,4257,,,,,1,1*29\r
+$PNTH001,1.273324,2.51,1.84,7.38,0,13,9*11\r
+$PNTH002,095611.00,N,-1281.208958,3,0,0.000000,0,0.340486*63\r
+$GNGGA,095612.00,2235.192005,N,11357.915065,E,1,9,2.8,47.8,M,,M,,*6B\r
+$GNGLL,2235.192005,N,11357.915065,E,095612.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.3,2.8,4.5,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,5.3,2.8,4.5,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.3,2.8,4.5,4*35\r
+$GPGSV,1,1,03,03,31,125,34,07,43,194,43,30,53,251,30,1*5C\r
+$GLGSV,1,1,03,76,,,25,79,72,113,34,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,38,26,64,159,40,1*4B\r
+$GNRMC,095612.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095612.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-56,4182,,,,,1,1*21\r
+$PNTH001,2.767364,4.50,3.95,7.38,0,13,9*13\r
+$PNTH002,095612.00,N,-1280.980527,3,0,0.000000,0,0.340486*6E\r
+$GNGGA,095613.00,2235.192005,N,11357.915065,E,1,9,2.8,47.8,M,,M,,*6A\r
+$GNGLL,2235.192005,N,11357.915065,E,095613.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.3,2.8,4.5,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,5.3,2.8,4.5,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.3,2.8,4.5,4*35\r
+$GPGSV,1,1,04,03,31,124,34,07,43,194,43,14,,,28,30,53,251,30,1*55\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,38,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,22,06,47,200,36,1*4C\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,39,26,64,159,40,1*4A\r
+$GNRMC,095613.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095613.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-58,3496,,,,,1,1*28\r
+$PNTH001,2.767545,4.50,3.95,7.38,0,14,9*11\r
+$PNTH002,095613.00,N,-1280.114875,3,0,0.000000,0,0.340486*60\r
+$GNGGA,095614.00,2235.192005,N,11357.915065,E,1,9,2.8,47.8,M,,M,,*6D\r
+$GNGLL,2235.192005,N,11357.915065,E,095614.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,5.3,2.8,4.5,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,5.3,2.8,4.5,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,5.3,2.8,4.5,4*35\r
+$GPGSV,1,1,04,03,31,124,33,07,43,194,43,14,,,25,30,53,251,31,1*5E\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,38,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,23,06,47,200,36,1*4D\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095614.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095614.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4101,,,,,1,1*2A\r
+$PNTH001,2.767727,4.50,3.95,7.38,0,14,9*17\r
+$PNTH002,095614.00,N,-1279.328191,3,0,0.000000,0,0.340486*6F\r
+$GNGGA,095615.00,2235.192005,N,11357.915065,E,1,9,2.6,47.8,M,,M,,*62\r
+$GNGLL,2235.192005,N,11357.915065,E,095615.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,1,1,04,03,31,124,33,07,43,194,43,14,,,25,30,53,251,31,1*5E\r
+$GLGSV,1,1,03,76,,,24,79,72,113,33,81,29,019,38,1*75\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095615.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095615.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3822,,,,,1,1*24\r
+$PNTH001,2.579318,3.89,3.78,7.38,0,14,9*12\r
+$PNTH002,095615.00,N,-1278.829876,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095616.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095616.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,04,03,31,124,33,07,43,194,43,14,,,25,30,53,251,31,1*5E\r
+$GLGSV,1,1,03,76,,,24,79,72,113,33,81,29,019,38,1*75\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,36,1*4A\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,39,26,64,159,40,1*4A\r
+$GNRMC,095616.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095616.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-57,3858,,,,,1,1*29\r
+$PNTH001,1.273239,2.51,1.84,7.38,0,14,9*1B\r
+$PNTH002,095616.00,N,-1277.731002,3,0,0.000000,0,0.340486*64\r
+$GNGGA,095617.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*66\r
+$GNGLL,2235.192005,N,11357.915065,E,095617.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,1,1,04,03,31,124,33,07,43,194,43,14,,,24,30,53,251,31,1*5F\r
+$GLGSV,1,1,03,76,,,23,79,72,113,33,81,29,019,38,1*72\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,38,26,64,159,40,1*4C\r
+$GNRMC,095617.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095617.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4085,,,,,1,1*27\r
+$PNTH001,1.273222,2.51,1.84,7.38,0,14,9*11\r
+$PNTH002,095617.00,N,-1277.512717,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095618.00,2235.192005,N,11357.915065,E,1,9,2.6,47.8,M,,M,,*6F\r
+$GNGLL,2235.192005,N,11357.915065,E,095618.00,A,A*72\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,24,17,,,25,1*6D\r
+$GPGSV,2,2,05,30,53,251,31,1*50\r
+$GLGSV,1,1,03,76,,,25,79,72,113,33,81,29,019,38,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,30,05,,,24,06,47,200,36,1*42\r
+$GBGSV,2,2,07,09,56,222,33,16,45,198,39,26,64,159,40,1*4A\r
+$GNRMC,095618.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*77\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095618.00,06,01,2025,00,00*79\r
+$PNTH000,2,,-56,4076,,,,,1,1*2B\r
+$PNTH001,2.580602,3.89,3.78,7.38,0,15,9*1B\r
+$PNTH002,095618.00,N,-1275.778564,3,0,0.000000,0,0.340486*60\r
+$GNGGA,095619.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*68\r
+$GNGLL,2235.192005,N,11357.915065,E,095619.00,A,A*73\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,21,17,,,22,1*6F\r
+$GPGSV,2,2,05,30,53,251,32,1*53\r
+$GLGSV,1,1,03,76,,,22,79,72,113,33,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,26,06,47,200,37,1*48\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095619.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*76\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095619.00,06,01,2025,00,00*78\r
+$PNTH000,2,,-58,3562,,,,,1,1*22\r
+$PNTH001,1.273188,2.51,1.84,7.38,0,15,9*13\r
+$PNTH002,095619.00,N,-1275.345140,3,0,0.000000,0,0.340486*69\r
+$GNGGA,095620.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*62\r
+$GNGLL,2235.192005,N,11357.915065,E,095620.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,22,17,,,22,1*6C\r
+$GPGSV,2,2,05,30,53,251,32,1*53\r
+$GLGSV,1,1,03,76,,,22,79,72,113,33,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095620.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095620.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-57,3825,,,,,1,1*23\r
+$PNTH001,1.273172,2.51,1.84,7.38,0,15,9*16\r
+$PNTH002,095620.00,N,-1274.878788,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095621.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*63\r
+$GNGLL,2235.192005,N,11357.915065,E,095621.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,22,17,,,22,1*6C\r
+$GPGSV,2,2,05,30,53,251,32,1*53\r
+$GLGSV,1,1,03,76,,,23,79,72,113,33,81,29,019,38,1*72\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,25,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095621.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095621.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-56,4032,,,,,1,1*2B\r
+$PNTH001,1.273156,2.51,1.84,7.38,0,15,9*10\r
+$PNTH002,095621.00,N,-1273.403067,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095622.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*60\r
+$GNGLL,2235.192005,N,11357.915065,E,095622.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,22,17,,,22,1*6C\r
+$GPGSV,2,2,05,30,53,251,32,1*53\r
+$GLGSV,1,1,03,76,,,21,79,72,113,33,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,21,06,47,200,36,1*4F\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095622.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095622.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-56,4088,,,,,1,1*2A\r
+$PNTH001,1.273139,2.51,1.84,7.38,0,15,9*19\r
+$PNTH002,095622.00,N,-1273.077217,3,0,0.000000,0,0.340486*64\r
+$GNGGA,095623.00,2235.192005,N,11357.915065,E,1,9,1.8,47.8,M,,M,,*6A\r
+$GNGLL,2235.192005,N,11357.915065,E,095623.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.5,1.8,3.1,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.5,1.8,3.1,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.5,1.8,3.1,4*35\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,42,14,,,21,17,,,21,1*6D\r
+$GPGSV,2,2,05,30,53,251,31,1*50\r
+$GLGSV,1,1,03,76,,,16,79,72,113,33,81,29,019,38,1*74\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,36,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095623.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095623.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-57,3951,,,,,1,1*21\r
+$PNTH001,1.792728,3.06,2.26,7.38,0,15,9*1D\r
+$PNTH002,095623.00,N,-1272.571516,3,0,0.000000,0,0.340486*61\r
+$GNGGA,095624.00,2235.192005,N,11357.915065,E,1,9,3.0,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095624.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,3.0,3.6,1*33\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,3.0,3.6,2*30\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,3.0,3.6,4*3D\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,43,14,,,22,17,,,21,1*6F\r
+$GPGSV,2,2,05,30,53,251,31,1*50\r
+$GLGSV,1,1,03,76,,,16,79,71,113,33,81,29,019,38,1*77\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095624.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095624.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-57,3854,,,,,1,1*25\r
+$PNTH001,2.954695,3.64,2.55,7.38,0,15,9*1D\r
+$PNTH002,095624.00,N,-1270.598434,3,0,0.000000,0,0.340486*62\r
+$GNGGA,095625.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*67\r
+$GNGLL,2235.192005,N,11357.915065,E,095625.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,06,03,31,124,33,07,43,194,43,14,,,21,17,,,18,1*65\r
+$GPGSV,2,2,06,19,,,25,30,53,251,31,1*5C\r
+$GLGSV,1,1,03,76,,,15,79,71,114,32,81,29,019,38,1*72\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095625.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095625.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-58,3623,,,,,1,1*24\r
+$PNTH001,1.273091,2.51,1.83,7.38,0,16,9*1E\r
+$PNTH002,095625.00,N,-1270.227104,3,0,0.000000,0,0.340486*66\r
+$GNGGA,095626.00,2235.192005,N,11357.915065,E,1,9,1.3,47.8,M,,M,,*64\r
+$GNGLL,2235.192005,N,11357.915065,E,095626.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,06,03,31,124,34,07,43,194,42,14,,,19,17,,,19,1*69\r
+$GPGSV,2,2,06,19,,,16,30,53,251,30,1*5D\r
+$GLGSV,1,1,03,76,,,15,79,71,114,32,81,29,019,38,1*72\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095626.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095626.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3766,,,,,1,1*2B\r
+$PNTH001,1.273076,2.51,1.83,7.38,0,16,9*17\r
+$PNTH002,095626.00,N,-1270.675064,3,0,0.000000,0,0.340486*61\r
+$GNGGA,095627.00,2235.192005,N,11357.915065,E,1,9,1.6,47.8,M,,M,,*60\r
+$GNGLL,2235.192005,N,11357.915065,E,095627.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.1,1.6,3.8,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.1,1.6,3.8,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.1,1.6,3.8,4*31\r
+$GPGSV,2,1,06,03,31,124,34,07,43,194,42,14,,,16,17,,,19,1*66\r
+$GPGSV,2,2,06,19,,,13,30,53,251,31,1*59\r
+$GLGSV,1,1,03,76,,,15,79,71,114,33,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095627.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095627.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,4010,,,,,1,1*2B\r
+$PNTH001,1.636444,3.77,2.56,7.38,0,16,9*19\r
+$PNTH002,095627.00,N,-1270.141043,3,0,0.000000,0,0.340486*65\r
+$GNGGA,095628.00,2235.192005,N,11357.915065,E,1,9,1.4,47.8,M,,M,,*6D\r
+$GNGLL,2235.192005,N,11357.915065,E,095628.00,A,A*71\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,06,03,31,124,34,07,43,194,42,14,,,17,17,,,19,1*67\r
+$GPGSV,2,2,06,19,,,12,30,53,251,30,1*59\r
+$GLGSV,1,1,03,76,,,14,79,71,114,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095628.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*74\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095628.00,06,01,2025,00,00*7A\r
+$PNTH000,2,,-57,3940,,,,,1,1*21\r
+$PNTH001,1.443012,2.51,1.84,7.38,0,16,9*17\r
+$PNTH002,095628.00,N,-1269.679434,3,0,0.000000,0,0.340486*6A\r
+$GNGGA,095629.00,2235.192005,N,11357.915065,E,1,9,3.0,47.8,M,,M,,*6A\r
+$GNGLL,2235.192005,N,11357.915065,E,095629.00,A,A*70\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,3.0,3.6,1*33\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,3.0,3.6,2*30\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,3.0,3.6,4*3D\r
+$GPGSV,2,1,06,03,31,124,34,07,43,194,42,14,,,17,17,,,19,1*67\r
+$GPGSV,2,2,06,19,,,11,30,53,251,30,1*5A\r
+$GLGSV,1,1,03,76,,,14,79,71,114,32,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095629.00,A,2235.192005,N,11357.915065,E,000.0,068.3,060125,,E,A,V*75\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095629.00,06,01,2025,00,00*7B\r
+$PNTH000,2,,-56,4077,,,,,1,1*2A\r
+$PNTH001,2.951885,3.63,2.54,7.38,0,16,9*12\r
+$PNTH002,095629.00,N,-1269.166612,3,0,0.000000,0,0.340486*64\r
+$GNGGA,095630.00,2235.192064,N,11357.914919,E,1,9,3.0,47.8,M,,M,,*66\r
+$GNGLL,2235.192064,N,11357.914919,E,095630.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,3.0,3.6,1*33\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,3.0,3.6,2*30\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,3.0,3.6,4*3D\r
+$GPGSV,2,1,06,03,31,124,34,07,43,194,42,14,,,17,17,,,18,1*66\r
+$GPGSV,2,2,06,19,,,10,30,53,251,29,1*53\r
+$GLGSV,1,1,03,76,,,16,79,71,114,31,81,29,019,38,1*72\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,40,26,64,159,40,1*43\r
+$GNRMC,095630.00,A,2235.192064,N,11357.914919,E,001.1,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,001.1,N,002.1,K,A*3E\r
+$GNZDA,095630.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-57,3783,,,,,1,1*20\r
+$PNTH001,2.951326,3.63,2.54,7.25,0,16,9*1C\r
+$PNTH002,095630.00,N,-1267.674466,3,0,0.000000,0,0.712842*60\r
+$GNGGA,095631.00,2235.192064,N,11357.914919,E,1,9,1.3,47.8,M,,M,,*66\r
+$GNGLL,2235.192064,N,11357.914919,E,095631.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,17,17,,,18,1*65\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,17,79,71,114,32,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,24,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095631.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095631.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-56,4066,,,,,1,1*2A\r
+$PNTH001,1.272998,2.51,1.83,7.25,0,15,9*10\r
+$PNTH002,095631.00,N,-1266.086030,3,0,0.000000,0,0.712842*6C\r
+$GNGGA,095632.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*62\r
+$GNGLL,2235.192064,N,11357.914919,E,095632.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,17,17,,,18,1*65\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,18,79,71,114,32,81,29,019,38,1*7F\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,39,1*42\r
+$GNRMC,095632.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095632.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-56,3989,,,,,1,1*25\r
+$PNTH001,1.442844,2.51,1.84,7.25,0,15,9*12\r
+$PNTH002,095632.00,N,-1265.584204,3,0,0.000000,0,0.712842*6E\r
+$GNGGA,095633.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*63\r
+$GNGLL,2235.192064,N,11357.914919,E,095633.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,16,17,,,18,1*64\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,37,1*71\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095633.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095633.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-57,3908,,,,,1,1*2D\r
+$PNTH001,1.442803,2.51,1.84,7.25,0,15,9*11\r
+$PNTH002,095633.00,N,-1263.657247,3,0,0.000000,0,0.712842*63\r
+$GNGGA,095634.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*64\r
+$GNGLL,2235.192064,N,11357.914919,E,095634.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,17,17,,,18,1*65\r
+$GPGSV,2,2,05,30,53,251,28,1*58\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,38,1*7E\r
+$GBGSV,2,1,07,02,,,32,03,,,30,05,,,25,06,47,200,37,1*40\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095634.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095634.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-56,4199,,,,,1,1*2B\r
+$PNTH001,1.442762,2.51,1.84,7.25,0,15,9*19\r
+$PNTH002,095634.00,N,-1264.507656,3,0,0.000000,0,0.712842*61\r
+$GNGGA,095635.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*65\r
+$GNGLL,2235.192064,N,11357.914919,E,095635.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,17,17,,,19,1*64\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,37,1*71\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,39,1*42\r
+$GNRMC,095635.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095635.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-57,3888,,,,,1,1*24\r
+$PNTH001,1.442721,2.51,1.84,7.25,0,15,9*1E\r
+$PNTH002,095635.00,N,-1263.535912,3,0,0.000000,0,0.712842*69\r
+$GNGGA,095636.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*66\r
+$GNGLL,2235.192064,N,11357.914919,E,095636.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,18,17,,,19,1*6B\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,37,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,40,1*4C\r
+$GNRMC,095636.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095636.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-57,3766,,,,,1,1*2B\r
+$PNTH001,1.442680,2.51,1.84,7.25,0,15,9*14\r
+$PNTH002,095636.00,N,-1263.184450,3,0,0.000000,0,0.712842*6F\r
+$GNGGA,095637.00,2235.192064,N,11357.914919,E,1,9,1.4,47.8,M,,M,,*67\r
+$GNGLL,2235.192064,N,11357.914919,E,095637.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.9,1.4,2.5,1*3F\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.9,1.4,2.5,2*3C\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.9,1.4,2.5,4*31\r
+$GPGSV,2,1,05,03,31,124,34,07,43,194,42,14,,,18,17,,,20,1*61\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,37,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,40,1*4C\r
+$GNRMC,095637.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095637.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-56,4079,,,,,1,1*24\r
+$PNTH001,1.442639,2.51,1.84,7.25,0,15,9*16\r
+$PNTH002,095637.00,N,-1261.962004,3,0,0.000000,0,0.712842*69\r
+$GNGGA,095638.00,2235.192064,N,11357.914919,E,1,9,1.3,47.8,M,,M,,*6F\r
+$GNGLL,2235.192064,N,11357.914919,E,095638.00,A,A*74\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,41,14,,,19,17,,,20,1*64\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,37,1*71\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,40,1*4C\r
+$GNRMC,095638.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*71\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095638.00,06,01,2025,00,00*7B\r
+$PNTH000,2,,-57,3879,,,,,1,1*2A\r
+$PNTH001,1.272894,2.51,1.83,7.25,0,15,9*1D\r
+$PNTH002,095638.00,N,-1261.666334,3,0,0.000000,0,0.712842*6D\r
+$GNGGA,095639.00,2235.192064,N,11357.914919,E,1,9,2.6,47.8,M,,M,,*68\r
+$GNGLL,2235.192064,N,11357.914919,E,095639.00,A,A*75\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,42,14,,,19,17,,,20,1*67\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,19,79,71,114,32,81,29,019,38,1*7E\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,25,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,40,1*4C\r
+$GNRMC,095639.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*70\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095639.00,06,01,2025,00,00*7A\r
+$PNTH000,2,,-56,4116,,,,,1,1*2C\r
+$PNTH001,2.589513,3.90,3.79,7.25,0,15,9*14\r
+$PNTH002,095639.00,N,-1261.862811,3,0,0.000000,0,0.712842*6A\r
+$GNGGA,095640.00,2235.192064,N,11357.914919,E,1,9,2.6,47.8,M,,M,,*66\r
+$GNGLL,2235.192064,N,11357.914919,E,095640.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,05,03,31,124,33,07,43,194,41,14,,,19,17,,,21,1*65\r
+$GPGSV,2,2,05,30,53,251,28,1*58\r
+$GLGSV,1,1,03,76,,,20,79,71,114,32,81,29,019,37,1*7B\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,64,159,40,1*4C\r
+$GNRMC,095640.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095640.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-56,3974,,,,,1,1*27\r
+$PNTH001,2.589939,3.90,3.79,7.25,0,15,9*10\r
+$PNTH002,095640.00,N,-1261.008606,3,0,0.000000,0,0.712842*68\r
+$GNGGA,095641.00,2235.192064,N,11357.914919,E,1,9,2.6,47.8,M,,M,,*67\r
+$GNGLL,2235.192064,N,11357.914919,E,095641.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,05,03,31,124,32,07,43,194,41,14,,,20,17,,,20,1*6F\r
+$GPGSV,2,2,05,30,53,251,29,1*59\r
+$GLGSV,1,1,03,76,,,23,79,71,114,32,81,29,019,37,1*78\r
+$GBGSV,2,1,07,02,,,31,03,,,30,05,,,25,06,47,200,37,1*43\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,40,1*4D\r
+$GNRMC,095641.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095641.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-56,3998,,,,,1,1*25\r
+$PNTH001,2.590346,3.90,3.79,7.25,0,15,9*1A\r
+$PNTH002,095641.00,N,-1261.689357,3,0,0.000000,0,0.712842*67\r
+$GNGGA,095642.00,2235.192064,N,11357.914919,E,1,9,2.6,47.8,M,,M,,*64\r
+$GNGLL,2235.192064,N,11357.914919,E,095642.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,06,03,31,124,32,07,43,194,41,14,,,21,17,,,19,1*67\r
+$GPGSV,2,2,06,22,,,26,30,53,251,28,1*5F\r
+$GLGSV,1,1,03,76,,,23,79,71,114,32,81,29,019,37,1*78\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,40,26,64,159,40,1*42\r
+$GNRMC,095642.00,A,2235.192064,N,11357.914919,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095642.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-57,3923,,,,,1,1*24\r
+$PNTH001,2.590785,3.90,3.79,7.25,0,16,9*12\r
+$PNTH002,095642.00,N,-1260.893246,3,0,0.000000,0,0.712842*61\r
+$GNGGA,095643.00,2235.192403,N,11357.914713,E,1,9,2.6,47.5,M,,M,,*69\r
+$GNGLL,2235.192403,N,11357.914713,E,095643.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,07,03,31,124,31,07,43,194,41,14,,,21,17,,,17,1*6B\r
+$GPGSV,2,2,07,21,,,23,22,,,26,30,53,251,28,1*5C\r
+$GLGSV,1,1,03,76,,,24,79,71,114,32,81,29,019,37,1*7F\r
+$GBGSV,2,1,07,02,,,31,03,,,29,05,,,22,06,47,200,37,1*4C\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,40,26,64,159,39,1*4C\r
+$GNRMC,095643.00,A,2235.192403,N,11357.914713,E,001.8,068.3,060125,,E,A,V*75\r
+$GNVTG,068.3,T,068.3,M,001.8,N,003.3,K,A*34\r
+$GNZDA,095643.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-57,3924,,,,,1,1*23\r
+$PNTH001,2.591214,3.90,3.79,7.01,0,17,9*19\r
+$PNTH002,095643.00,N,-1260.192091,3,0,0.000000,0,0.633155*6D\r
+$GNGGA,095644.00,2235.192403,N,11357.914713,E,1,9,2.6,47.5,M,,M,,*6E\r
+$GNGLL,2235.192403,N,11357.914713,E,095644.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,07,03,31,124,31,07,43,194,41,14,,,22,17,,,14,1*6B\r
+$GPGSV,2,2,07,21,,,20,22,,,26,30,53,251,28,1*5F\r
+$GLGSV,1,1,03,76,,,25,79,71,114,31,81,29,019,37,1*7D\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,25,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095644.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095644.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-57,3862,,,,,1,1*20\r
+$PNTH001,2.591636,3.90,3.79,7.01,0,17,9*1D\r
+$PNTH002,095644.00,N,-1258.917244,3,0,0.000000,0,0.633155*6E\r
+$GNGGA,095645.00,2235.192403,N,11357.914713,E,1,9,2.6,47.5,M,,M,,*6F\r
+$GNGLL,2235.192403,N,11357.914713,E,095645.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.7,2.6,3.9,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.7,2.6,3.9,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.7,2.6,3.9,4*35\r
+$GPGSV,2,1,07,03,31,124,30,07,43,194,41,14,,,22,17,,,09,1*66\r
+$GPGSV,2,2,07,21,,,20,22,,,25,30,53,251,28,1*5C\r
+$GLGSV,1,1,03,76,,,24,79,71,114,31,81,29,019,37,1*7C\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095645.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095645.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-56,4092,,,,,1,1*21\r
+$PNTH001,2.592062,3.90,3.79,7.01,0,17,9*19\r
+$PNTH002,095645.00,N,-1257.591998,3,0,0.000000,0,0.633155*68\r
+$GNGGA,095646.00,2235.192403,N,11357.914713,E,1,9,5.3,47.5,M,,M,,*6E\r
+$GNGLL,2235.192403,N,11357.914713,E,095646.00,A,A*7C\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,14.4,5.3,13.4,1*37\r
+$GNGSA,A,3,79,81,,,,,,,,,,,14.4,5.3,13.4,2*34\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,14.4,5.3,13.4,4*39\r
+$GPGSV,2,1,07,03,31,124,29,07,43,194,41,14,,,22,17,,,09,1*6E\r
+$GPGSV,2,2,07,21,,,20,22,,,24,30,53,251,28,1*5D\r
+$GLGSV,1,1,03,76,,,23,79,71,114,32,81,29,019,37,1*78\r
+$GBGSV,2,1,07,02,,,31,03,,,28,05,,,23,06,47,200,37,1*4C\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,40,26,64,159,39,1*4C\r
+$GNRMC,095646.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*79\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095646.00,06,01,2025,00,00*72\r
+$PNTH000,2,,-57,3865,,,,,1,1*27\r
+$PNTH001,5.313826,13.35,13.03,7.01,0,17,9*1B\r
+$PNTH002,095646.00,N,-1257.493977,3,0,0.000000,0,0.633155*69\r
+$GNGGA,095647.00,2235.192403,N,11357.914713,E,1,9,1.3,47.5,M,,M,,*6B\r
+$GNGLL,2235.192403,N,11357.914713,E,095647.00,A,A*7D\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,06,03,31,124,28,07,43,194,41,14,,,22,21,,,20,1*60\r
+$GPGSV,2,2,06,22,,,25,30,53,251,27,1*53\r
+$GLGSV,1,1,03,76,,,22,79,71,114,31,81,29,019,37,1*7A\r
+$GBGSV,2,1,07,02,,,29,03,,,28,05,,,24,06,47,200,37,1*42\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095647.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*78\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095647.00,06,01,2025,00,00*73\r
+$PNTH000,2,,-57,3861,,,,,1,1*23\r
+$PNTH001,1.272766,2.52,1.83,7.01,0,16,9*19\r
+$PNTH002,095647.00,N,-1256.514058,3,0,0.000000,0,0.633155*63\r
+$GNGGA,095648.00,2235.192403,N,11357.914713,E,1,9,1.3,47.5,M,,M,,*64\r
+$GNGLL,2235.192403,N,11357.914713,E,095648.00,A,A*72\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,06,03,31,124,28,07,43,194,41,14,,,22,21,,,19,1*6A\r
+$GPGSV,2,2,06,22,,,24,30,53,251,27,1*52\r
+$GLGSV,1,1,03,76,,,22,79,71,114,31,81,29,019,37,1*7A\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095648.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*77\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095648.00,06,01,2025,00,00*7C\r
+$PNTH000,2,,-57,3903,,,,,1,1*26\r
+$PNTH001,1.272753,2.52,1.83,7.01,0,16,9*1F\r
+$PNTH002,095648.00,N,-1256.292271,3,0,0.000000,0,0.633155*6C\r
+$GNGGA,095649.00,2235.192403,N,11357.914713,E,1,9,1.8,47.5,M,,M,,*6E\r
+$GNGLL,2235.192403,N,11357.914713,E,095649.00,A,A*73\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.5,1.8,3.1,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.5,1.8,3.1,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.5,1.8,3.1,4*35\r
+$GPGSV,2,1,06,03,31,124,28,07,43,194,41,14,,,21,21,,,20,1*63\r
+$GPGSV,2,2,06,22,,,24,30,53,251,27,1*52\r
+$GLGSV,1,1,03,76,,,23,79,71,114,31,81,29,019,38,1*74\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095649.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*76\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095649.00,06,01,2025,00,00*7D\r
+$PNTH000,2,,-57,3819,,,,,1,1*2C\r
+$PNTH001,1.791148,3.05,2.25,7.01,0,16,9*17\r
+$PNTH002,095649.00,N,-1255.588896,3,0,0.000000,0,0.633155*61\r
+$GNGGA,095650.00,2235.192403,N,11357.914713,E,1,9,1.8,47.5,M,,M,,*66\r
+$GNGLL,2235.192403,N,11357.914713,E,095650.00,A,A*7B\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.5,1.8,3.1,1*3B\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.5,1.8,3.1,2*38\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.5,1.8,3.1,4*35\r
+$GPGSV,2,1,06,03,31,124,28,07,43,194,40,14,,,23,21,,,20,1*60\r
+$GPGSV,2,2,06,22,,,24,30,53,251,27,1*52\r
+$GLGSV,1,1,03,76,,,24,79,71,114,31,81,29,019,38,1*73\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,37,1*4A\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095650.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7E\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095650.00,06,01,2025,00,00*75\r
+$PNTH000,2,,-57,3784,,,,,1,1*27\r
+$PNTH001,1.791089,3.05,2.25,7.01,0,16,9*1B\r
+$PNTH002,095650.00,N,-1254.772126,3,0,0.000000,0,0.633155*6D\r
+$GNGGA,095651.00,2235.192403,N,11357.914713,E,1,9,2.0,47.5,M,,M,,*6C\r
+$GNGLL,2235.192403,N,11357.914713,E,095651.00,A,A*7A\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,2,1,06,03,31,124,27,07,43,194,40,14,,,21,21,,,21,1*6C\r
+$GPGSV,2,2,06,22,,,24,30,53,251,27,1*52\r
+$GLGSV,1,1,03,76,,,26,79,71,114,31,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095651.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7F\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095651.00,06,01,2025,00,00*74\r
+$PNTH000,2,,-57,3764,,,,,1,1*29\r
+$PNTH001,1.982923,4.05,2.80,7.01,0,16,9*16\r
+$PNTH002,095651.00,N,-1254.467711,3,0,0.000000,0,0.633155*69\r
+$GNGGA,095652.00,2235.192403,N,11357.914713,E,1,9,2.0,47.5,M,,M,,*6F\r
+$GNGLL,2235.192403,N,11357.914713,E,095652.00,A,A*79\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,4.5,2.0,4.1,1*30\r
+$GNGSA,A,3,79,81,,,,,,,,,,,4.5,2.0,4.1,2*33\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,4.5,2.0,4.1,4*3E\r
+$GPGSV,2,1,06,03,31,124,27,07,43,194,40,14,,,22,21,,,21,1*6F\r
+$GPGSV,2,2,06,22,,,25,30,53,251,28,1*5C\r
+$GLGSV,1,1,03,76,,,26,79,71,114,31,81,29,019,38,1*71\r
+$GBGSV,2,1,07,02,,,30,03,,,29,05,,,24,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,64,159,39,1*43\r
+$GNRMC,095652.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7C\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095652.00,06,01,2025,00,00*77\r
+$PNTH000,2,,-55,4371,,,,,1,1*2C\r
+$PNTH001,1.982916,4.05,2.80,7.01,0,16,9*10\r
+$PNTH002,095652.00,N,-1253.959806,3,0,0.000000,0,0.633155*64\r
+$GNGGA,095653.00,2235.192403,N,11357.914713,E,1,9,1.3,47.5,M,,M,,*6E\r
+$GNGLL,2235.192403,N,11357.914713,E,095653.00,A,A*78\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,2.8,1.3,2.5,1*39\r
+$GNGSA,A,3,79,81,,,,,,,,,,,2.8,1.3,2.5,2*3A\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,2.8,1.3,2.5,4*37\r
+$GPGSV,2,1,06,03,31,124,27,07,43,194,40,14,,,23,21,,,21,1*6E\r
+$GPGSV,2,2,06,22,,,25,30,53,251,27,1*53\r
+$GLGSV,1,1,03,76,,,26,79,71,114,31,81,29,019,37,1*7E\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,23,06,47,200,37,1*4D\r
+$GBGSV,2,2,07,09,56,222,35,16,45,198,39,26,63,159,39,1*45\r
+$GNRMC,095653.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7D\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095653.00,06,01,2025,00,00*76\r
+$PNTH000,2,,-56,4036,,,,,1,1*2F\r
+$PNTH001,1.272686,2.52,1.83,7.01,0,16,9*16\r
+$PNTH002,095653.00,N,-1254.351911,3,0,0.000000,0,0.633155*67\r
+$GNGGA,095654.00,2235.192403,N,11357.914713,E,1,9,1.8,47.5,M,,M,,*62\r
+$GNGLL,2235.192403,N,11357.914713,E,095654.00,A,A*7F\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.5,1.8,3.0,1*3A\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.5,1.8,3.0,2*39\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.5,1.8,3.0,4*34\r
+$GPGSV,2,1,06,03,31,124,27,07,43,194,40,14,,,22,21,,,21,1*6F\r
+$GPGSV,2,2,06,22,,,24,30,53,251,28,1*5D\r
+$GLGSV,1,1,03,76,,,27,79,71,114,31,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,25,06,47,200,37,1*4B\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,63,159,39,1*44\r
+$GNRMC,095654.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7A\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095654.00,06,01,2025,00,00*71\r
+$PNTH000,2,,-56,4122,,,,,1,1*2B\r
+$PNTH001,1.790848,3.05,2.25,7.01,0,16,9*1F\r
+$PNTH002,095654.00,N,-1255.029287,3,0,0.000000,0,0.633155*69\r
+$GNGGA,095655.00,2235.192403,N,11357.914713,E,1,9,1.8,47.5,M,,M,,*63\r
+$GNGLL,2235.192403,N,11357.914713,E,095655.00,A,A*7E\r
+$GNGSA,A,3,3,7,30,,,,,,,,,,3.5,1.8,3.0,1*3A\r
+$GNGSA,A,3,79,81,,,,,,,,,,,3.5,1.8,3.0,2*39\r
+$GNGSA,A,3,6,9,16,26,,,,,,,,,3.5,1.8,3.0,4*34\r
+$GPGSV,2,1,06,03,31,124,28,07,43,194,40,14,,,24,21,,,21,1*66\r
+$GPGSV,2,2,06,22,,,26,30,53,251,28,1*5F\r
+$GLGSV,1,1,03,76,,,27,79,71,114,31,81,29,019,38,1*70\r
+$GBGSV,2,1,07,02,,,30,03,,,28,05,,,24,06,47,200,38,1*45\r
+$GBGSV,2,2,07,09,56,222,34,16,45,198,39,26,63,159,39,1*44\r
+$GNRMC,095655.00,A,2235.192403,N,11357.914713,E,000.0,068.3,060125,,E,A,V*7B\r
+$GNVTG,068.3,T,068.3,M,000.0,N,000.0,K,A*3D\r
+$GNZDA,095655.00,06,01,2025,00,00*70\r
+$PNTH000,2,,-56,4026,,,,,1,1*2E\r
+$PNTH001,1.790788,3.05,2.25,7.01,0,16,9*1C\r
+$PNTH002,095655.00,N,-1254.601271,3,0,0.000000,0,0.633155*6C
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c b/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c
new file mode 100644 (file)
index 0000000..63d4b91
--- /dev/null
@@ -0,0 +1,251 @@
+// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
+//
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "driver/uart.h"
+
+#include "pinctrl.h"
+#include "debug_print.h"
+#include "soc_osal.h"
+#include "tcxo.h"
+#include "irmalloc.h"
+#include "errcode.h"
+#include "common_def.h"
+#include "wearable_log.h"
+#include "thread_init.h"
+#include "custom_utils.h"
+#include "uart_gnss.h"
+#include "gnss_ctl.h"
+#include "tiot_board_pin_port.h"
+// errcode_t gnss_get_next_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen);
+// errcode_t gnss_get_current_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen);
+// errcode_t gnss_get_nmea_cfg_cmd(uint8_t** cmdbuf,int *cmdlen);
+// errcode_t gnss_get_stop_cmd(uint8_t** cmdbuf,int *cmdlen);
+// errcode_t gnss_get_start_cmd(uint8_t** cmdbuf,int *cmdlen);
+static unsigned long g_gnss_cmd_queue= 0xFFFFFFFF;
+#define MAX_BUFFER_SIZE (256)
+typedef struct {
+    uint8_t cmd;
+    uint8_t cmd_type;
+    uint32_t size;
+    uint8_t *buffer;
+} gnss_cmd_t;
+void do_gnss_cmd_head(int cmd,uint8_t *buffer,uint32_t size)
+{
+    int ret;
+
+    gnss_cmd_t mail = {0};
+    if(cmd == GNSS_CMD_READDATA)
+    {   //只有接收的缓存需要malloc,发送的都是静态数组,无需申请缓存
+        mail.buffer = osal_kmalloc(size+1, OSAL_GFP_KERNEL);
+        if (mail.buffer == NULL) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"uart message buffer memory alloc fail, length is %d "NEWLINE, size);
+            return;
+        }
+        memset_s(mail.buffer,size+1,0,size+1);
+        memcpy_s(mail.buffer,MAX_BUFFER_SIZE,buffer,size);
+        mail.cmd_type=0;
+    }else{
+        mail.cmd_type= *buffer;
+        mail.buffer = buffer;
+    }
+    mail.cmd = cmd;
+    mail.size = size;
+    // unsigned int quesize=osal_msg_queue_get_msg_num(g_gnss_cmd_queue);
+    //  WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"do_uart_gnss_cmd quesize %d\n",quesize);
+    ret = osal_msg_queue_write_head_copy(g_gnss_cmd_queue, (void *)&mail,
+                                    sizeof(gnss_cmd_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"Error gnss cmd msg %d send failed! err=0x%02X!"NEWLINE,cmd, ret);
+    }
+    
+}
+void do_gnss_cmd(int cmd,uint8_t *buffer,uint32_t size)
+{
+    int ret;
+
+    if (buffer == NULL || size == 0 ) 
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"input buffer is NULL or size == 0"NEWLINE );
+        return ;
+    }
+    gnss_cmd_t mail = {0};
+    if(cmd == GNSS_CMD_READDATA)
+    {   //只有接收的缓存需要malloc,发送的都是静态数组,无需申请缓存
+        mail.buffer = osal_kmalloc(size+1, OSAL_GFP_KERNEL);
+        if (mail.buffer == NULL) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"uart message buffer memory alloc fail, length is %d "NEWLINE, size);
+            return;
+        }
+        memset_s(mail.buffer,size+1,0,size+1);
+        memcpy_s(mail.buffer,MAX_BUFFER_SIZE,buffer,size);
+        mail.cmd_type=0;
+    }else{
+        mail.cmd_type= *buffer;
+        mail.buffer = buffer;
+    }
+    mail.cmd = cmd;
+    mail.size = size;
+    // unsigned int quesize=osal_msg_queue_get_msg_num(g_gnss_cmd_queue);
+    //  WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"do_uart_gnss_cmd quesize %d\n",quesize);
+    ret = osal_msg_queue_write_copy(g_gnss_cmd_queue, (void *)&mail,
+                                    sizeof(gnss_cmd_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_MAIN_SERVICE,"Error gnss cmd msg %d send failed! err=0x%02X!"NEWLINE,cmd, ret);
+    }
+    
+}
+
+uint32_t gnss_write_cmd(uint8_t * cmdbuf,uint16_t cmdlen)
+{
+    return uapi_uart_write(TIOT_UART_PORT, cmdbuf, cmdlen,0);
+}
+uint32_t gnss_data_read(uint8_t * cmdbuf,uint16_t cmdlen)
+{
+    return uapi_uart_read(TIOT_UART_PORT, cmdbuf, cmdlen,0);
+}
+static void uart_event_task(void const *arg)
+{
+    unused(arg);
+    int32_t ret;
+    gnss_cmd_t mail;
+    uint32_t msgsize = (uint32_t)sizeof(gnss_cmd_t);
+    static uint8_t last_cfg_cmd_index=0xFF;
+    
+    while (1) {
+
+        (void)memset_s(&mail, sizeof(gnss_cmd_t), 0, sizeof(gnss_cmd_t));
+
+        ret = osal_msg_queue_read_copy(g_gnss_cmd_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            continue;
+        }
+
+        if (mail.cmd == GNSS_CMD_READDATA) {
+       
+            WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"recv size=%d! %s \r\n",mail.size,mail.buffer);
+            if (last_cfg_cmd_index != 0xFF) //说明正在执行GNSS_CMD_CFG_INIT 且是第二次以后写
+            {
+                last_cfg_cmd_index++;
+                uint32_t wlen=0;
+                uint8_t *buf=NULL;
+                uint16_t len=0;
+                // if (gnss_get_current_cmd(last_cfg_cmd_index,&buf,&len)==0)
+                {
+                    WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"write next cmd[%d] size=%d! %s \r\n",last_cfg_cmd_index,len);
+                    wlen=gnss_write_cmd(buf,len);
+                }
+                // else
+                {
+                    WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"no next cmd, stopped! \r\n");
+                    last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表结束写入
+                }
+            }
+
+
+        }else if (mail.cmd == GNSS_CMD_WRITEDATA)
+        {
+            uint32_t wlen=0;
+            uint8_t *buf=NULL;
+            uint16_t len=0;
+            switch(mail.cmd_type)
+            {
+                case GNSS_CMD_CFG_INIT:
+                    WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"last_cfg_cmd_index %d \r\n",last_cfg_cmd_index);
+                    if (last_cfg_cmd_index == 0xFF) //第一次写
+                    {
+                        // if (gnss_get_current_cmd(0,&buf,&len)==0)
+                        {
+                            WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"last_cfg_cmd_index %d \r\n",last_cfg_cmd_index);
+                            last_cfg_cmd_index = 0;
+                        }
+                    } 
+                break;
+                case GNSS_CMD_NMEA_CFG:
+                    // gnss_get_nmea_cfg_cmd(&buf,&len);
+                    last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令
+                break;
+                case GNSS_CMD_START:
+                    // gnss_get_start_cmd(&buf,&len);
+                    GnssServerStart();
+                    last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令
+                break;
+                case GNSS_CMD_STOP:
+                    // gnss_get_stop_cmd(&buf,&len);
+                    last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令
+                break;
+                default:
+                    buf = mail.buffer;
+                    len = mail.size;
+                    break;
+            }
+            if (buf!=NULL)
+            {
+                // wlen=gnss_write_cmd(buf,len);
+                WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"GNSS_CMD_WRITEDATA cmdtype %d, written len %d\r\n",mail.cmd_type,wlen);
+            }else{
+                WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"GNSS_CMD_WRITEDATA cmdtype %d failed \r\n",mail.cmd_type);
+            }
+        }
+        if(mail.cmd == GNSS_CMD_READDATA)
+            osal_kfree(mail.buffer); //只有接收的缓存需要free,发送的都是静态数组,无需申请缓存
+    }
+}
+
+void gnss_receive_handler(uint8_t *buffer, int32_t size)
+{
+       // WEARABLE_LOGD(WEARABLE_LOG_MODULE_MAIN_SERVICE,"gnss_receive_handler %d \n",size);
+    if (g_gnss_cmd_queue!= 0xFFFFFFFF)
+    {
+        do_gnss_cmd(GNSS_CMD_READDATA,buffer,size);
+    }  
+}
+
+#define GNSS_CMD_TASK_MSG_COUNT 128
+#define GNSS_CMD_TASK_SIZE (0x1000)
+#define GNSS_CMD_TASK_PRIO 4
+void create_gnss_uart_queue(void)
+{
+
+    if (osal_msg_queue_create("uart_gnss_cmd_queue", GNSS_CMD_TASK_MSG_COUNT, &g_gnss_cmd_queue,
+                              0, sizeof(gnss_cmd_t)) != ERRCODE_SUCC) {
+        PRINT("[service] gnss server create mail fail\n");
+    }
+}
+int gnss_uart_init(void)
+{
+
+
+    PRINT("gnss_uart_init !\r\n");
+
+    app_task_definition_t taskcfg={0};
+    taskcfg.create_queue_handle = create_gnss_uart_queue;
+    taskcfg.attr.name="uart_gnss_service";
+    taskcfg.attr.priority = osPriorityHigh;//osPriorityNormal; GUI osPriorityAboveNormal2
+    taskcfg.attr.stack_size = GNSS_CMD_TASK_SIZE;
+    taskcfg.func = uart_event_task;
+    taskcfg.use_mem = USE_DTCM_MEM;
+    
+    errcode_t ret=uapi_create_osThread_custom(&taskcfg);
+    if(ret != ERRCODE_SUCC)
+    {
+        PRINT("create uart_gnss_service failed %d!\r\n",ret);
+        return ERRCODE_FAIL;
+    }
+    return ERRCODE_SUCC;
+}
+
index d894f51..eb54055 100644 (file)
@@ -88,10 +88,17 @@ const lcd_cmd_sequ g_common_cmd_display_off[] = {
 
 /* display off sequence for common lcd */
 const lcd_cmd_sequ g_common_466x466_cmd_display_off[] = {
+#ifdef BOARD_W9
+    {1, 2, {0xfe, 0x00}, 0},   /* select default cmd page */
+    {1, 1, {0x28}, 10},         /* display off */
+    {1, 1, {0x10}, 120},       /* sleep in */
+    {1, 2, {0x4f, 0x01}, 100},        /* sleep in */
+#else
     {1, 2, {0xfe, 0x00}, 0},   /* select default cmd page */
     {1, 1, {0x28}, 0},         /* display off */
     {1, 1, {0x10}, 120},       /* sleep in */
-    {1, 2, {0x4f, 0x01}, 0},   /* 进deepstandby 状态 */
+    {1, 2, {0x4f, 0x01}, 0},   /* ��deepstandby ״̬ */
+#endif
 };
 
 /* sleep in sequence for common lcd */
index d629fd0..1bf3f37 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-07 15:32:08
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-06 10:36:23
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/lcd/lcd_private.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
 /*
  * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved.
  * Description: Lcd private interface.
@@ -37,13 +45,15 @@ static void lcd_drv_power_off(void)
     uapi_gpio_set_dir(VCI_LCD_GPIO, GPIO_DIRECTION_OUTPUT);
     uapi_gpio_set_val(VCI_LCD_GPIO, GPIO_LEVEL_LOW);
     #endif
+#ifndef BOARD_W9
     uapi_tcxo_delay_ms(10); /* delay 10 ms */
+#endif
     int resetvalue = uapi_gpio_get_output_val(RESET_LCD_GPIO);
     int lcd_envalue = uapi_gpio_get_output_val(VCI_LCD_GPIO);
     printf("Output RESET_LCD_GPIO %d , VCI_LCD_GPIO %d\r\n",resetvalue,lcd_envalue);
 #else
     uapi_gpio_set_val(RESET_LCD_GPIO, GPIO_LEVEL_LOW);
-    uapi_gpio_set_dir(RESET_LCD_GPIO, GPIO_DIRECTION_INPUT); //设置成Input,是为了解决漏电 ??
+    uapi_gpio_set_dir(RESET_LCD_GPIO, GPIO_DIRECTION_INPUT); //���ó�Input����Ϊ�˽��©�� ����
     uapi_pin_set_pull(RESET_LCD_GPIO, PIN_PULL_DOWN);
     #ifndef QSPI_DISPLAY
     uapi_gpio_set_val(VCI_LCD_GPIO, GPIO_LEVEL_LOW);
index 958ca1f..bf1e1b2 100644 (file)
@@ -1,3 +1,5 @@
 add_subdirectory_if_exist(service)
 add_subdirectory_if_exist(hx3695)
-add_subdirectory_if_exist(ppgBleService)
\ No newline at end of file
+add_subdirectory_if_exist(ppgBleService)
+add_subdirectory_if_exist(hal)
+add_subdirectory_if_exist(pah8009)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/ppg/hal/CMakeLists.txt b/code/sdk/drivers/peripheral/ppg/hal/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b2a51f6
--- /dev/null
@@ -0,0 +1,41 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved.
+#===============================================================================
+
+set(COMPONENT_NAME "ppg_hal")
+
+set(PUBLIC_HEADER
+${CMAKE_CURRENT_SOURCE_DIR}
+)
+set(PRIVATE_HEADER
+)
+
+set(SOURCES
+${CMAKE_CURRENT_SOURCE_DIR}/ppg_hal.c
+
+)
+
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+-Wno-incompatible-function-pointer-types
+-Wno-unused-function
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+set(PUBLIC_DEFINES
+)
+
+set(PRIVATE_DEFINES
+)
+
+build_component()
diff --git a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c
new file mode 100644 (file)
index 0000000..4c48871
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-03-13 15:08:38
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-05 15:25:30
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.c
+ * @Description: 
+ * 
+ * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+#include "ppg_hal.h"
+#include "pinctrl_porting.h"
+#include "hal_gpio.h"
+#include "pm_control.h"
+
+
+#include "custom_utils.h"
+
+
+#ifdef PPG_HX3695
+#include "tyhx_hrs_custom.h"
+#include "hx3695.h"
+#include "hx3695_factory_test.h"
+#endif
+
+#ifdef PPG_PAH8009
+#include "pah800x_main.h"
+#endif
+
+#ifdef SUPPORT_CYWEE_SERVICE
+#include "cywee_service.h"
+#endif
+
+
+// S_AGPIO_L26 心率复位 PPG reset
+#define GPIO_PIN_PRG_RESET S_AGPIO_L26
+// S_AGPIO_R0 PRG_LED_POWER ON  心率等电源控制脚
+#define GPIO_PIN_PRG_LED_ON S_AGPIO_R0
+
+void ppg_power_on(void)
+{
+    // printf("ppg_power_on\n");
+    uapi_pin_set_mode(GPIO_PIN_PRG_RESET, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_RESET, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_RESET, GPIO_LEVEL_HIGH);
+   
+    uapi_pin_set_mode(GPIO_PIN_PRG_LED_ON, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_LED_ON, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_LED_ON, GPIO_LEVEL_HIGH);
+    LOS_Mdelay(50);
+}
+
+void ppg_power_off(void)
+{
+    // printf("ppg_power_off\n");
+    uapi_pin_set_mode(GPIO_PIN_PRG_RESET, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_RESET, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_RESET, GPIO_LEVEL_LOW);
+   
+    uapi_pin_set_mode(GPIO_PIN_PRG_LED_ON, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_LED_ON, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_LED_ON, GPIO_LEVEL_LOW);
+    LOS_Mdelay(50);
+}
+
+uint8_t ppg_get_hrs(void)
+{
+    uint8_t hrs = 0;
+#ifdef PPG_HX3695
+    hrs = hx3695_get_hrs();
+    // printf("ppg_get_hrs : %d\n",hrs);
+#endif
+    return hrs;
+}
+
+uint8_t ppg_get_spo2(void)
+{
+    uint8_t spo2 = 0;
+#ifdef PPG_HX3695
+    spo2 = hx3695_get_spo2();
+#endif
+    return spo2;
+}
+
+uint8_t ppg_get_wear_status(void)
+{
+    uint8_t wear_status = 0;
+#ifdef PPG_HX3695
+    wear_status = hx3695_get_wear_status();
+#endif
+    return wear_status;
+}
+
+uint16_t ppg_get_chip_id(void)
+{
+    uint16_t chip_id = 0;
+    ppg_power_on();
+#ifdef PPG_HX3695
+    chip_id = hx3695_chip_check();
+#elif defined PPG_PAH8009
+    chip_id = pah8009_get_chip_id();
+#endif
+        ppg_power_off();
+    return chip_id;
+}
+
+void ppg_timer_handler(uint8_t mode)
+{
+    // printf("ppg_agc_timer_handler\n");
+#ifdef PPG_HX3695
+    if(mode == AGC_TIMER_MODE)
+        agc_timeout_handler(NULL);
+    else if(mode == HRS_TIMER_MODE)
+        heart_rate_meas_timeout_handler(NULL);
+    else if(mode == WEAR_TIMER_MODE)
+        wear_mode_timeout_handler(NULL);
+#elif defined PPG_PAH8009
+    pah8009_timer_handler();
+#endif
+}
+
+
+void ppg_int_handler(void)
+{
+#ifdef PPG_PAH8009
+    pah8009_int_handler();
+#endif
+}
+
+void ppg_send_cmd_to_driver(char* mode, uint8_t enable)
+{
+    // printf("ppg_send_cmd_to_driver \n");
+    if(enable)
+        ppg_power_on();
+#ifdef PPG_HX3695
+    hx3695_control(mode,enable);
+#elif defined PPG_PAH8009
+    pah8009_control(mode,enable);
+#endif
+    if(!enable)
+        ppg_power_off();
+}
+
+void ppg_get_leaklight_data(uint32_t *ch0,uint32_t *ch1,uint32_t *ch2)
+{
+#ifdef PPG_HX3695
+    hx3695_get_factory_data(ch0,ch1,ch2);
+#elif defined PPG_VC9202
+    vc9202_get_leaklight_data(ch0,ch1,ch2);
+#elif defined PPG_PAH8009
+    pah8009_get_leaklight_data(ch0,ch1,ch2);
+#endif
+}
+
+uint32_t ppg_get_factory_data(void)
+{
+    uint32_t data = 0;
+#ifdef PPG_PAH8009  
+    data =  pah8009_get_factory_data();
+#elif defined PPG_HX3695
+
+#endif
+    return data;
+}
+
+ppg_msg_callback_t g_send_msg_toUI = NULL;
+
+// typedef void (*hx3695_msg_callback_t)(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen);
+uint32_t ppg_register_msg_callback(ppg_msg_callback_t func)
+{
+    g_send_msg_toUI = func;
+    return 0;
+}
+
+ppg_msg_callback_t ppg_get_send_msg_callback_func(void)
+{
+    return g_send_msg_toUI;
+}
diff --git a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h
new file mode 100644 (file)
index 0000000..d878a71
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-06-07 11:18:26
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-05 14:46:32
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/ppg/ppg_hal.h
+ * @Description: 
+ * 
+ * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
+ */
+#ifndef PPG_HAL_H__
+#define PPG_HAL_H__
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "tyhx_hrs_custom.h"
+
+#define AGC_TIMER_MODE 0
+#define HRS_TIMER_MODE 1
+#define WEAR_TIMER_MODE 2
+
+#ifdef PPG_HX3695
+#define PPG_CHIP_ID 0x65
+#elif defined PPG_PAH8009
+#define PPG_CHIP_ID 0x8008
+#else
+#define PPG_CHIP_ID 0
+#endif
+
+typedef uint32_t PPG_CMD_TYPE_T ;
+
+typedef enum{
+    PPG_MSG_TYPE_HRS_UPDATE,
+    PPG_MSG_TYPE_HRV_UPDATE,
+    PPG_MSG_TYPE_SPO2_UPDATE,
+    PPG_MSG_TYPE_WEARSTAT_UPDATE,
+    PPG_MSG_TYPE_STATIC_HRS_UPDATE,
+} ppg_msg_type_t;
+
+typedef void (*ppg_msg_callback_t)(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen);
+uint32_t ppg_register_msg_callback(ppg_msg_callback_t func);
+ppg_msg_callback_t ppg_get_send_msg_callback_func(void);
+
+void ppg_send_cmd_to_driver(char* mode, uint8_t enable);
+void ppg_timer_handler(uint8_t mode);
+uint16_t ppg_get_chip_id(void);
+uint8_t ppg_get_hrs(void);
+uint8_t ppg_get_spo2(void);
+uint8_t ppg_get_wear_status(void);
+void ppg_wear_status_update(uint8_t status);
+void ppg_power_on(void);
+void ppg_power_off(void);
+void ppg_int_handler(void);
+void ppg_get_leaklight_data(uint32_t *ch0,uint32_t *ch1,uint32_t *ch2);
+uint32_t ppg_get_factory_data(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
index 8feed29..b98ba29 100644 (file)
 // #include "lv_dev.h"\r
 // #include "app_task.h"\r
 \r
+#ifdef SUPPORT_CYWEE_SERVICE\r
 #include "cywee_hal.h"\r
 #include "cywee_service.h"\r
 #include "custom_utils.h"\r
 #include "custom_runtime.h"\r
+#endif\r
+\r
+#include "ppg_hal.h"\r
+\r
 \r
 FT_CUSTOM_RESULTS_t hrsresult ={0};\r
 \r
@@ -43,7 +48,9 @@ int16_t gsen_fifo_x[64]={0};
 int16_t gsen_fifo_y[64]={0};\r
 int16_t gsen_fifo_z[64]={0};\r
 \r
+#ifdef SUPPORT_CYWEE_SERVICE\r
 gsenson_t gsensordata[32];\r
+#endif\r
 \r
 static uint8_t msg_count = 0;\r
 \r
@@ -364,12 +371,12 @@ void hx3695_gpioint_cfg(bool en)
 }\r
 #endif\r
 \r
-bool hx3695_chip_check(void)\r
+uint8_t hx3695_chip_check(void)\r
 {\r
     uint8_t i = 0;\r
     uint8_t chip_id = 0;\r
     hx3695_chip_id = 0;\r
-    for(i=0; i<10; i++)\r
+    for(i=0; i<5; i++)\r
     {\r
         hx3695_ppg_on();\r
         hx3695_delay_ms(5);\r
@@ -380,13 +387,13 @@ bool hx3695_chip_check(void)
             //printf("hx3695_chip_check ok  chip_id: 0x%x \r\n",chip_id);\r
                        //Efuse_Mode_Check();\r
             hx3695_chip_id = chip_id;\r
-            return true;\r
+            // return hx3695_chip_id;\r
         }\r
     }\r
 \r
-    printf(" hx3695_chip_check fail!  chip_id: 0x%x \r\n", chip_id);\r
+    printf(" hx3695 chip_id: 0x%x \r\n", chip_id);\r
 \r
-    return false;\r
+    return chip_id;\r
 }\r
 \r
 void hx3695_get_id(uint8_t *ppg_id)\r
@@ -2237,9 +2244,6 @@ void hx3695_check_touch_init(void) //
 // 初始化调用入口函数\r
 bool hx3695_init(WORK_MODE_T mode)\r
 {\r
-  hx3695_msg_callback_t func;\r
-\r
-\r
        //TYHX_LOG("this chip hx3695_init  mode: %d !! \r\n", mode);\r
        \r
        hx3695_ppg_on();\r
@@ -2320,7 +2324,7 @@ bool hx3695_init(WORK_MODE_T mode)
         break;\r
 \r
     case FT_LEAK_LIGHT_MODE:\r
-        if (!hx3695_chip_check())\r
+        if (hx3695_chip_check() != 0x65)\r
         {\r
             AGC_LOG("hx3695 check id failed!\r\n");\r
             return false;\r
@@ -2328,15 +2332,10 @@ bool hx3695_init(WORK_MODE_T mode)
         //TYHX_LOG(" hx3695_init mode : LEAK_LIGHT_MODE \n");\r
         hx3695_factroy_test(LEAK_LIGHT_TEST);\r
 \r
-        func =  hx3695_get_send_msg_callback_func();\r
-        if(func != NULL)\r
-        {\r
-          func(HX3695_MSG_TYPE_LEAKLIGHT_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
-        }\r
         break;\r
 \r
     case FT_GRAY_CARD_MODE:\r
-        if (!hx3695_chip_check())\r
+        if (hx3695_chip_check() != 0x65)\r
         {\r
             AGC_LOG("hx3695 check id failed!\r\n");\r
             return false;\r
@@ -2344,11 +2343,6 @@ bool hx3695_init(WORK_MODE_T mode)
         //TYHX_LOG(" hx3695_init mode : GRAY_CARD_MODE \n");\r
         hx3695_factroy_test(GRAY_CARD_TEST);\r
 \r
-        func =  hx3695_get_send_msg_callback_func();\r
-        if(func != NULL)\r
-        {\r
-          func(HX3695_MSG_TYPE_GRAYCARD_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
-        }\r
         break;\r
 \r
     case FT_INT_TEST_MODE:\r
@@ -2356,7 +2350,7 @@ bool hx3695_init(WORK_MODE_T mode)
         break;\r
 \r
     case FT_SINGLE_CHECK_MODE:\r
-         if (!hx3695_chip_check())\r
+        if (hx3695_chip_check() != 0x65)\r
         {\r
             AGC_LOG("hx3695 check id failed!\r\n");\r
             return false;\r
@@ -2733,22 +2727,24 @@ void hx3695_wearstatus_update(void)
     {\r
         history_wear_status = cywee_wear_status;\r
         cywee_data = history_wear_status;\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
         do_cywee_service_check_msg(CYWEE_SERVICE_CMD_WEAR_STATUS_CHANGE,&cywee_data);\r
+#endif\r
     }\r
 }\r
   //脱腕上报未佩戴信息\r
 void hx3695_unwearstatus_update(void)\r
 {\r
-  hx3695_msg_callback_t func =  hx3695_get_send_msg_callback_func();\r
+  ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
   if(func != NULL && !uapi_dev_runtime_get_train_status())\r
   {\r
     hrsresult.lastesthrs = 0;\r
     hrsresult.wearstatus = 0;\r
     //为了主界面脱腕灵敏;需要增加未佩戴\r
-    func(HX3695_MSG_TYPE_HRS_UPDATE, &hrsresult, sizeof(FT_CUSTOM_RESULTS_t));\r
-    func(HX3695_MSG_TYPE_WEARSTAT_UPDATE, &hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
-    func(HX3695_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
-    func(HX3695_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
+    func(PPG_MSG_TYPE_HRS_UPDATE, &hrsresult.lastesthrs, 1);\r
+    func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &hrsresult.wearstatus,1);\r
+    func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult.wearstatus,1);\r
+    func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult.wearstatus,1);\r
   }\r
 \r
   if(uapi_dev_runtime_get_train_status())\r
@@ -2756,7 +2752,9 @@ void hx3695_unwearstatus_update(void)
       cywee_wear_status = 0;\r
       hx3695_wearstatus_update();\r
       cywee_data = 0;\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
       do_cywee_service_check_msg(CYWEE_SERVICE_CMD_HRS_CHANGE,&cywee_data);\r
+#endif\r
   }\r
 }                              \r
 \r
@@ -2843,6 +2841,7 @@ void hx3695_hrs_ppg_Int_handle(void)
     // {\r
     //     return;\r
     // }\r
+  #ifdef SUPPORT_CYWEE_SERVICE\r
     memset(gsensordata,0.0f,sizeof(gsenson_t) * *count);\r
 \r
     gsensor_get_n_data(*count,gsensordata);  \r
@@ -2914,6 +2913,7 @@ void hx3695_hrs_ppg_Int_handle(void)
       //PRINT("hxdata:%d/%d %d %d %.3f %.3f %.3f %d\r\n" ,1+ii,*count,PPG_buf[ii],ir_buf[0],gsensordata[ii].x,gsensordata[ii].y,gsensordata[ii].z,ppg_s_data.green_cur);\r
 \r
     }\r
+#endif\r
     hrs_wear_status = hx3695_hrs_get_wear_status();\r
     //PRINT("hrs_wear_status:    %d !!\r\n", hrs_wear_status);\r
 \r
@@ -2977,7 +2977,7 @@ void hx3695_hrs_ppg_Int_handle(void)
     }\r
 \r
     \r
-    hx3695_msg_callback_t func =  hx3695_get_send_msg_callback_func();\r
+    ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
     if(func != NULL)\r
     {\r
       if(his_wear == hrsresult.wearstatus)\r
@@ -2985,7 +2985,7 @@ void hx3695_hrs_ppg_Int_handle(void)
           wear_cnt++;\r
           if(wear_cnt >= 2 && !his_wear) //未佩戴超过2次 上报未佩戴信息\r
           {\r
-              func(HX3695_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
+              func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult.wearstatus,1);\r
               wear_cnt = 0;\r
           }\r
       }\r
@@ -3017,10 +3017,10 @@ void hx3695_hrs_ppg_Int_handle(void)
           if(func != NULL)\r
           {\r
             //PRINT("hrsresult.lastesthrs : %d \n",hrsresult.lastesthrs);\r
-            func(HX3695_MSG_TYPE_HRS_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
+            func(PPG_MSG_TYPE_HRS_UPDATE,&hrsresult.lastesthrs,1);\r
             if(uapi_get_cywee_static_state())\r
             {\r
-                func(HX3695_MSG_TYPE_STATIC_HRS_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
+                func(PPG_MSG_TYPE_STATIC_HRS_UPDATE,&hrsresult.lastesthrs,1);\r
             }\r
           }\r
 \r
@@ -3028,7 +3028,9 @@ void hx3695_hrs_ppg_Int_handle(void)
           {\r
               hx3695_wearstatus_update();\r
               cywee_data = hrsresult.lastesthrs;\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
               do_cywee_service_check_msg(CYWEE_SERVICE_CMD_HRS_CHANGE,&cywee_data);\r
+#endif\r
           }\r
     }\r
 \r
@@ -3506,12 +3508,12 @@ void hx3695_spo2_ppg_Int_handle(void)
 //             hr_sensor_notify_factory_test();\r
        }\r
            \r
-    hx3695_msg_callback_t func =  hx3695_get_send_msg_callback_func();\r
+    ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
     if(func != NULL)\r
     {\r
       hrsresult.wearstatus = spo2_wear_status;\r
-      func(HX3695_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
-      func(HX3695_MSG_TYPE_SPO2_UPDATE,&hrsresult,sizeof(FT_CUSTOM_RESULTS_t));\r
+      func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&hrsresult.wearstatus,1);\r
+      func(PPG_MSG_TYPE_SPO2_UPDATE,&hrsresult.lastestspo2,1);\r
     }\r
 \r
 \r
@@ -3812,4 +3814,60 @@ void hx3695_lab_test_Int_handle(void)
 }\r
 #endif\r
 \r
+void hx3695_control(char *mode,uint8_t enable)\r
+{\r
+    WORK_MODE_T md = NULL_MODE;\r
+    if (strcmp(mode, "hrs") == 0) {\r
+        md = HRS_MODE;\r
+    } else if (strcmp(mode, "hrv") == 0) {\r
+        md = HRV_MODE;\r
+    } else if (strcmp(mode, "spo2") == 0) {\r
+        md = SPO2_MODE;\r
+    } else if (strcmp(mode, "leaklight") == 0) {\r
+        md = FT_LEAK_LIGHT_MODE;\r
+    } else if (strcmp(mode, "graycard") == 0) {\r
+        md = FT_GRAY_CARD_MODE;\r
+    } else if (strcmp(mode, "ledoff") == 0) {\r
+        md = FT_LED_OFF_MODE;\r
+    } else if (strcmp(mode, "wear") == 0) {\r
+        md = WEAR_MODE;\r
+    } else if (strcmp(mode, "single") == 0) {\r
+        md = FT_SINGLE_CHECK_MODE;\r
+    } \r
+\r
+\r
+    if (enable == 1 || md == FT_LED_OFF_MODE) {\r
+        hx3695_init(md);\r
+    } else {\r
+       if(md == HRS_MODE|| md == FT_LEAK_LIGHT_MODE || md == FT_GRAY_CARD_MODE || md == WEAR_MODE || md == FT_SINGLE_CHECK_MODE)\r
+        {\r
+#ifdef HRS_ALG_LIB   \r
+            hx3695_hrs_disable();\r
+            // PRINT("uapi_dev_runtime_get_sleep_monitoring_status : %d \n",uapi_dev_runtime_get_sleep_monitoring_status());\r
+            // PRINT("uapi_dev_runtime_get_hrs_passivity_flag : %d \n",uapi_dev_runtime_get_hrs_passivity_flag());\r
+            if(uapi_dev_runtime_get_sleep_monitoring_status() && uapi_dev_runtime_get_hrs_passivity_flag())//处于睡眠监测 且在心率周期检测期间 上报活体佩戴 \r
+            {\r
+                hx3695_wearstatus_update();   \r
+                uapi_dev_runtime_set_hrs_passivity(0);//清除被动检测runtime     \r
+            }\r
+#endif\r
+        }else  if(md == HRV_MODE)\r
+        {\r
+#ifdef HRV_ALG_LIB\r
+            hx3695_hrv_disable();\r
+#endif\r
+        }else  if(md == SPO2_MODE)\r
+        {\r
+#ifdef SPO2_ALG_LIB\r
+            hx3695_spo2_disable();\r
+#endif\r
+        }\r
+       else{\r
+#ifdef HRS_ALG_LIB   \r
+            hx3695_hrs_disable();\r
+#endif\r
+        }\r
+    }\r
+}\r
+\r
 #endif  //CHIP_HX3695
\ No newline at end of file
index 228abb1..e259aae 100644 (file)
@@ -245,7 +245,7 @@ void hx3695_delay_ms(uint32_t ms);
 bool hx3695_write_reg(uint8_t addr, uint8_t data); \r
 uint8_t hx3695_read_reg(uint8_t addr); \r
 bool hx3695_brust_read_reg(uint8_t addr , uint8_t *buf, uint16_t length);\r
-bool hx3695_chip_check(void);\r
+uint8_t hx3695_chip_check(void);\r
 void hx3695_get_id(uint8_t *ppg_id);\r
 uint8_t hx3695_read_fifo_size(void);\r
 uint16_t hx3695_read_fifo_data(int32_t *s_buf, uint8_t size, uint8_t phase_num);\r
index 09e9a46..3832f06 100644 (file)
@@ -24,7 +24,7 @@ static uint8_t touch_cnt = 0;
 \r
 SENSOR_ERROR_T hx3695_check_touch_enable(void)\r
 {\r
-    if (!hx3695_chip_check())\r
+    if (hx3695_chip_check() != 0x65)\r
     {\r
         AGC_LOG("hx3695 check id failed!\r\n");\r
         return SENSOR_OP_FAILED;\r
index 2a6dd6a..37992c2 100644 (file)
@@ -8,6 +8,10 @@
 #include "hx3695.h"\r
 #include "hx3695_factory_test.h"\r
 \r
+static uint32_t factory_green = 0;\r
+static uint32_t factory_red = 0;\r
+static uint32_t factory_ir = 0;\r
+\r
 void hx3695_factory_wear_mode_config(void)\r
 {\r
     uint16_t sample_rate = 10;                  /*config the data rate of chip alps2_fm ,uint is Hz*/\r
@@ -2882,23 +2886,18 @@ FT_RESULTS_t hx3695_factroy_test(TEST_MODE_t  test_mode)
         hx3695_factory_ft_leak_light_test_config();\r
         hx3695_delay_ms(50);\r
         ft_result = hx3695_factory_ft_leak_light_test_get_result();\r
-        hrsresult.leak_green = ft_result.gr_data_final;\r
-        hrsresult.leak_red = ft_result.red_data_final;\r
-        hrsresult.leak_ir = ft_result.ir_data_final;\r
-        TYHX_LOG("leak_green =%d\r\n",hrsresult.leak_green);\r
-        TYHX_LOG("leak_red   =%d\r\n",hrsresult.leak_red);\r
-        TYHX_LOG("leak_ir    =%d\r\n",hrsresult.leak_ir);\r
+        factory_green = ft_result.gr_data_final;\r
+        factory_red = ft_result.red_data_final;\r
+        factory_ir = ft_result.ir_data_final;\r
+        printf("factory_green : %d, factory_red:%d, factory_ir:%d\n",factory_green,factory_red,factory_ir);\r
         break;\r
     case GRAY_CARD_TEST:\r
         hx3695_factory_ft_card_test_config();\r
         hx3695_delay_ms(50);\r
         ft_result = hx3695_factory_ft_card_test_get_result();\r
-        hrsresult.card_green = ft_result.gr_data_final;\r
-        hrsresult.card_red = ft_result.red_data_final;\r
-        hrsresult.card_ir = ft_result.ir_data_final;\r
-        TYHX_LOG("card_green =%d\r\n",hrsresult.card_green);\r
-        TYHX_LOG("card_red   =%d\r\n",hrsresult.card_red);\r
-        TYHX_LOG("card_ir    =%d\r\n",hrsresult.card_ir);\r
+        factory_green = ft_result.gr_data_final;\r
+        factory_red = ft_result.red_data_final;\r
+        factory_ir = ft_result.ir_data_final;\r
         break;\r
     case FT_INT_TEST:\r
         hx3695_factory_ft_int_test_config();\r
@@ -2919,3 +2918,14 @@ FT_RESULTS_t hx3695_factroy_test(TEST_MODE_t  test_mode)
 \r
     return ft_result;\r
 }\r
+\r
+void hx3695_get_factory_data(uint32_t *green,uint32_t *red,uint32_t *ir)\r
+{\r
+    *green = factory_green;\r
+    *red = factory_red;\r
+    *ir = factory_ir;\r
+\r
+    factory_green = 0;\r
+    factory_red = 0;\r
+    factory_ir = 0;\r
+}
\ No newline at end of file
index aadb903..93c62bf 100644 (file)
@@ -1,3 +1,11 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-01-06 17:53:47\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-06-05 15:20:11\r
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_factory_test.h\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
 #ifndef _HX3695_FACTORY_TEST_H_\r
 #define _HX3695_FACTORY_TEST_H_\r
 \r
@@ -37,7 +45,8 @@ FT_RESULTS_t hx3695_factroy_test(TEST_MODE_t  test_mode);
 \r
 void hx3695_lab_test(uint32_t  test_mode);\r
 void hx3695_lab_test_read(void);\r
-bool hx3695_chip_check_id(void);\r
+\r
+void hx3695_get_factory_data(uint32_t *green,uint32_t *red,uint32_t *ir);\r
 \r
 #endif // _HX3695_FACTORY_TEST_H_\r
 \r
index 4bad413..9bb8a04 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-03-13 15:08:38
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2024-11-19 19:40:35
+ * @LastEditTime: 2025-06-05 15:28:37
  * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.c
  * @Description: 
  * 
 #include "hx3695.h"
 
 
-hx3695_msg_callback_t g_send_msg_toUI = NULL;
+// hx3695_msg_callback_t g_send_msg_toUI = NULL;
 
-// typedef void (*hx3695_msg_callback_t)(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen);
-uint32_t hx3695_register_msg_callback(hx3695_msg_callback_t func)
-{
-    g_send_msg_toUI = func;
-    return 0;
-}
+// // typedef void (*hx3695_msg_callback_t)(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen);
+// uint32_t hx3695_register_msg_callback(hx3695_msg_callback_t func)
+// {
+//     g_send_msg_toUI = func;
+//     return 0;
+// }
 
-hx3695_msg_callback_t hx3695_get_send_msg_callback_func(void)
-{
-    return g_send_msg_toUI;
-}
+// hx3695_msg_callback_t hx3695_get_send_msg_callback_func(void)
+// {
+//     return g_send_msg_toUI;
+// }
 
 
-#include "hx3695.h"
-#include "tyhx_hrs_custom.h"
+// #include "hx3695.h"
+// #include "tyhx_hrs_custom.h"
 
-void ppg_send_cmd_to_driver(char* mode, uint8_t enable)
-{
+// void ppg_send_cmd_to_driver(char* mode, uint8_t enable)
+// {
 
-    WORK_MODE_T md = NULL_MODE;
-    if (strcmp(mode, "hrs") == 0) {
-        md = HRS_MODE;
-    } else if (strcmp(mode, "hrv") == 0) {
-        md = HRV_MODE;
-    } else if (strcmp(mode, "spo2") == 0) {
-        md = SPO2_MODE;
-    } else if (strcmp(mode, "leaklight") == 0) {
-        md = FT_LEAK_LIGHT_MODE;
-    } else if (strcmp(mode, "graycard") == 0) {
-        md = FT_GRAY_CARD_MODE;
-    } else if (strcmp(mode, "ledoff") == 0) {
-        md = FT_LED_OFF_MODE;
-    } else if (strcmp(mode, "wear") == 0) {
-        md = WEAR_MODE;
-    } else if (strcmp(mode, "single") == 0) {
-        md = FT_SINGLE_CHECK_MODE;
-    } 
+//     WORK_MODE_T md = NULL_MODE;
+//     if (strcmp(mode, "hrs") == 0) {
+//         md = HRS_MODE;
+//     } else if (strcmp(mode, "hrv") == 0) {
+//         md = HRV_MODE;
+//     } else if (strcmp(mode, "spo2") == 0) {
+//         md = SPO2_MODE;
+//     } else if (strcmp(mode, "leaklight") == 0) {
+//         md = FT_LEAK_LIGHT_MODE;
+//     } else if (strcmp(mode, "graycard") == 0) {
+//         md = FT_GRAY_CARD_MODE;
+//     } else if (strcmp(mode, "ledoff") == 0) {
+//         md = FT_LED_OFF_MODE;
+//     } else if (strcmp(mode, "wear") == 0) {
+//         md = WEAR_MODE;
+//     } else if (strcmp(mode, "single") == 0) {
+//         md = FT_SINGLE_CHECK_MODE;
+//     } 
 
    
-    if (enable == 1 || md == FT_LED_OFF_MODE) {
-        // ppg_service_running_stat = true;
-        uapi_pm_control(PM_APP_WAKE_NEEDED);
-        tyhx_poweron();
-        //custom_i2c_reset();
-        hx3695_init(md);
-    } else {
+//     if (enable == 1 || md == FT_LED_OFF_MODE) {
+//         // ppg_service_running_stat = true;
+//         uapi_pm_control(PM_APP_WAKE_NEEDED);
+//         tyhx_poweron();
+//         //custom_i2c_reset();
+//         hx3695_init(md);
+//     } else {
 
-    //    ppg_service_running_stat = false;
-       if(md == HRS_MODE|| md == FT_LEAK_LIGHT_MODE || md == FT_GRAY_CARD_MODE || md == WEAR_MODE || md == FT_SINGLE_CHECK_MODE)
-        {
-#ifdef HRS_ALG_LIB   
-            hx3695_hrs_disable();
-            // PRINT("uapi_dev_runtime_get_sleep_monitoring_status : %d \n",uapi_dev_runtime_get_sleep_monitoring_status());
-            // PRINT("uapi_dev_runtime_get_hrs_passivity_flag : %d \n",uapi_dev_runtime_get_hrs_passivity_flag());
-            if(uapi_dev_runtime_get_sleep_monitoring_status() && uapi_dev_runtime_get_hrs_passivity_flag())//处于睡眠监测 且在心率周期检测期间 上报活体佩戴 
-            {
-                hx3695_wearstatus_update();   
-                uapi_dev_runtime_set_hrs_passivity(0);//清除被动检测runtime     
-            }
-#endif
-        }else  if(md == HRV_MODE)
-        {
-#ifdef HRV_ALG_LIB
-            hx3695_hrv_disable();
-#endif
-        }else  if(md == SPO2_MODE)
-        {
-#ifdef SPO2_ALG_LIB
-            hx3695_spo2_disable();
-#endif
-        }
-       else{
-#ifdef HRS_ALG_LIB   
-            hx3695_hrs_disable();
-#endif
-        }
-        uapi_pm_control(PM_APP_WAKE_NONEED);
-        tyhx_poweroff();
-    } 
-}
\ No newline at end of file
+//     //    ppg_service_running_stat = false;
+//        if(md == HRS_MODE|| md == FT_LEAK_LIGHT_MODE || md == FT_GRAY_CARD_MODE || md == WEAR_MODE || md == FT_SINGLE_CHECK_MODE)
+//         {
+// #ifdef HRS_ALG_LIB   
+//             hx3695_hrs_disable();
+//             // PRINT("uapi_dev_runtime_get_sleep_monitoring_status : %d \n",uapi_dev_runtime_get_sleep_monitoring_status());
+//             // PRINT("uapi_dev_runtime_get_hrs_passivity_flag : %d \n",uapi_dev_runtime_get_hrs_passivity_flag());
+//             if(uapi_dev_runtime_get_sleep_monitoring_status() && uapi_dev_runtime_get_hrs_passivity_flag())//处于睡眠监测 且在心率周期检测期间 上报活体佩戴 
+//             {
+//                 hx3695_wearstatus_update();   
+//                 uapi_dev_runtime_set_hrs_passivity(0);//清除被动检测runtime     
+//             }
+// #endif
+//         }else  if(md == HRV_MODE)
+//         {
+// #ifdef HRV_ALG_LIB
+//             hx3695_hrv_disable();
+// #endif
+//         }else  if(md == SPO2_MODE)
+//         {
+// #ifdef SPO2_ALG_LIB
+//             hx3695_spo2_disable();
+// #endif
+//         }
+//        else{
+// #ifdef HRS_ALG_LIB   
+//             hx3695_hrs_disable();
+// #endif
+//         }
+//         uapi_pm_control(PM_APP_WAKE_NONEED);
+//         tyhx_poweroff();
+//     } 
+// }
\ No newline at end of file
index 0f61427..168c894 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-06-07 11:18:26
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2024-07-25 18:14:12
+ * @LastEditTime: 2025-06-05 15:25:04
  * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.h
  * @Description: 
  * 
@@ -19,24 +19,12 @@ extern "C" {
 #include "stdint.h"
 #include "tyhx_hrs_custom.h"
 
-typedef uint32_t PPG_CMD_TYPE_T ;
-
-typedef enum{
-    HX3695_MSG_TYPE_HRS_UPDATE,
-    HX3695_MSG_TYPE_HRV_UPDATE,
-    HX3695_MSG_TYPE_SPO2_UPDATE,
-    HX3695_MSG_TYPE_LEAKLIGHT_UPDATE,
-    HX3695_MSG_TYPE_GRAYCARD_UPDATE,
-    HX3695_MSG_TYPE_WEARSTAT_UPDATE,
-    HX3695_MSG_TYPE_STATIC_HRS_UPDATE,
-} hx3695_msg_type_t;
-
 
 typedef void (*hx3695_msg_callback_t)(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen);
 uint32_t hx3695_register_msg_callback(hx3695_msg_callback_t func);
 hx3695_msg_callback_t hx3695_get_send_msg_callback_func(void);
 
-void ppg_send_cmd_to_driver(char* mode, uint8_t enable);
+// void ppg_send_cmd_to_driver(char* mode, uint8_t enable);
 
 #ifdef __cplusplus
 #if __cplusplus
index 45936e2..00040ee 100644 (file)
@@ -818,7 +818,7 @@ void hx3695_hrs_set_mode(uint8_t mode_cmd)
 \r
 SENSOR_ERROR_T hx3695_hrs_enable(void)\r
 {\r
-    if (!hx3695_chip_check())\r
+    if (hx3695_chip_check() != 0x65)\r
     {\r
         AGC_LOG("hx3695 check id failed!\r\n");\r
         return SENSOR_OP_FAILED;\r
index c78766d..a8e5706 100644 (file)
@@ -47,19 +47,19 @@ static uint8_t g_hx3695_timer_installed = 0;
 
 static void timer40_func(void)
 {
-    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_40TIMER_CALLBACK);
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_AGC_TIMER_CALLBACK);
     // agc_timeout_handler(NULL);
 }
 
 static void timer320_func(void)
 {
-    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_320TIMER_CALLBACK);
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_HRS_TIMER_CALLBACK);
     // heart_rate_meas_timeout_handler(NULL);
 }
 
 static void timer5000_func(void)
 {
-    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_5000TIMER_CALLBACK);
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_TIMER_CALLBACK);
     // heart_rate_meas_timeout_handler(NULL);
 }
 bool tyhx_timer_init(void)
index 1bf2916..5d90d9f 100644 (file)
@@ -581,7 +581,7 @@ void hx3695_hrv_set_mode(uint8_t mode_cmd)
 \r
 SENSOR_ERROR_T hx3695_hrv_enable(void)\r
 {\r
-    if (!hx3695_chip_check())\r
+    if (hx3695_chip_check() != 0x65)\r
     {\r
         AGC_LOG("hx3695 check id failed!\r\n");\r
         return SENSOR_OP_FAILED;\r
index 9a230be..669f8b6 100644 (file)
@@ -837,7 +837,7 @@ void hx3695_spo2_set_mode(uint8_t mode_cmd)
 \r
 SENSOR_ERROR_T hx3695_spo2_enable(void)\r
 {\r
-    if (!hx3695_chip_check())\r
+    if (hx3695_chip_check() != 0x65)\r
     {\r
         AGC_LOG("hx3695 check id failed!\r\n");\r
         return SENSOR_OP_FAILED;\r
@@ -867,7 +867,7 @@ SENSOR_ERROR_T hx3695_spo2_enable(void)
 \r
 SENSOR_ERROR_T hx3695_hrspo2_enable(void)\r
 {\r
-    if (!hx3695_chip_check())\r
+    if (hx3695_chip_check() != 0x65)\r
     {\r
         AGC_LOG("hx3695 check id failed!\r\n");\r
         return SENSOR_OP_FAILED;\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/CMakeLists.txt b/code/sdk/drivers/peripheral/ppg/pah8009/CMakeLists.txt
new file mode 100644 (file)
index 0000000..31c7b91
--- /dev/null
@@ -0,0 +1,52 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2022-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "ppg_sensor_pah8009")
+
+set(SOURCES ${SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/sensor/pah_800x.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/sensor/pah800x_bsp.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/sensor/pah800x_main.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/factory/pah800x_factory_test.c
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/sensor
+    ${CMAKE_CURRENT_SOURCE_DIR}/factory
+    ${CMAKE_CURRENT_SOURCE_DIR}/algorithm/pah_spo2/V703
+    ${CMAKE_CURRENT_SOURCE_DIR}/algorithm/pah_stress/V6033
+    ${CMAKE_CURRENT_SOURCE_DIR}/algorithm/pah_hr/V303009
+)
+
+set(PRIVATE_HEADER
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(PUBLIC_DEFINES
+    PPG_PAH8009
+)
+
+# use this when you want to add ccflags like -include xxx
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+find_library(LIB_PATH_SPO2 algorithm/pah_spo2/V703/libv703_0_1.a ${CMAKE_CURRENT_SOURCE_DIR})
+find_library(LIB_PATH_HR algorithm/pah_hr/V303009/libv307009_4.a ${CMAKE_CURRENT_SOURCE_DIR})
+
+target_link_libraries(${TARGET_NAME} PRIVATE -Wl,--whole-archive ${LIB_PATH_HR} ${LIB_PATH_SPO2} PRIVATE -Wl,--whole-archive)
+
+build_component()
+
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/Interrupt_function.c b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/Interrupt_function.c
new file mode 100644 (file)
index 0000000..6c91bba
--- /dev/null
@@ -0,0 +1,12 @@
+#include "pxi_interp.h"\r
+\r
+\r
+void  PXI_MEMS_interp(int16_t *src_data, size_t src_data_count, int16_t *dst_data, size_t dst_data_count)\r
+{\r
+         pxi_interp_ex1(src_data,  src_data_count ,dst_data,dst_data_count ,3);\r
+               pxi_interp_ex1(&src_data[1],  src_data_count ,&dst_data[1],dst_data_count ,3);\r
+               pxi_interp_ex1(&src_data[2],  src_data_count ,&dst_data[2],dst_data_count ,3);\r
+}\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.c b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.c
new file mode 100644 (file)
index 0000000..36ed8cd
--- /dev/null
@@ -0,0 +1,42 @@
+#include "pxi_interp.h"\r
+\r
+\r
+/*****\r
+* @brief Example of Platform. In this function we initialize powerkey and register callback.\r
+* @param None.\r
+* @return None.\r
+*\r
+*****/\r
+\r
+void pxi_interp_ex1(int16_t *src_data, size_t src_data_count, int16_t *dst_data, size_t dst_data_count, size_t offset)\r
+{\r
+    float pre_time_acc = 0.0f;\r
+    float time_acc = 0.0f;\r
+    float d_time = (float)dst_data_count / src_data_count;\r
+    size_t idx_ptr = 0;\r
+\r
+    for (size_t i = 0; i < dst_data_count; ++i)\r
+    {\r
+        while (time_acc < (float)i)\r
+        {\r
+            pre_time_acc = time_acc;\r
+            time_acc = time_acc + d_time;\r
+            idx_ptr++;\r
+        }\r
+\r
+        if (idx_ptr == 0)\r
+        {\r
+            dst_data[i * offset] = src_data[idx_ptr * offset];\r
+        }\r
+        else if (idx_ptr == dst_data_count)\r
+        {\r
+            dst_data[i * offset] = src_data[(idx_ptr - 1) * offset];\r
+        }\r
+        else\r
+        {\r
+            float time_ratio = ((float)i - pre_time_acc) / (time_acc - pre_time_acc);\r
+            dst_data[i * offset] = (int16_t)((float)src_data[(idx_ptr - 1) * offset] * (1.0f - time_ratio) + (float)src_data[idx_ptr * offset] * time_ratio + 0.5f);\r
+        }\r
+    }\r
+}\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/MEMS_INT/pxi_interp.h
new file mode 100644 (file)
index 0000000..15c4149
--- /dev/null
@@ -0,0 +1,7 @@
+//#pragma once\r
+\r
+#include <stdint.h>\r
+#include <stddef.h>\r
+\r
+void pxi_interp_ex1(int16_t *src_data, size_t src_data_count, int16_t *dst_data, size_t dst_data_count, size_t offset);\r
+void  PXI_MEMS_interp(int16_t *src_data, size_t src_data_count, int16_t *dst_data, size_t dst_data_count);\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/libv307009_4.a b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/libv307009_4.a
new file mode 100644 (file)
index 0000000..d0d7a95
Binary files /dev/null and b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/libv307009_4.a differ
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pah8009_testpattern_HRD.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pah8009_testpattern_HRD.h
new file mode 100644 (file)
index 0000000..44b62ae
--- /dev/null
@@ -0,0 +1,23944 @@
+#ifndef _PAH8009_TESTPATTERN_\r
+#define _PAH8009_TESTPATTERN_\r
+\r
+#include <stdint.h>\r
+#define NF_PPG_CHANNEL 3\r
+#define NF_PPG_PER_CHANNEL 3\r
+static const int32_t PAH8009_rawdata_HRD[][NF_PPG_PER_CHANNEL*NF_PPG_CHANNEL] = \r
+{\r
+{0, 123629, 5910},\r
+{0, 118569, 5918},\r
+{0, 113318, 5916},\r
+{0, 106371, 5944},\r
+{0, 105522, 5928},\r
+{0, 96770, 5938},\r
+{0, 91486, 5928},\r
+{0, 86122, 5918},\r
+{0, 81476, 5906},\r
+{0, 80788, 5908},\r
+{0, 80266, 5904},\r
+{0, 79770, 5909},\r
+{0, 79298, 5908},\r
+{0, 78950, 5892},\r
+{0, 78704, 5900},\r
+{0, 78700, 5897},\r
+{0, 78620, 5897},\r
+{0, 78202, 5900},\r
+{0, 77595, 5903},\r
+{0, 77266, 5899},\r
+{0, 77183, 5888},\r
+{0, 77194, 5893},\r
+{0, 77168, 5884},\r
+{0, 76801, 5883},\r
+{0, 76396, 5875},\r
+{0, 75904, 5877},\r
+{0, 75403, 5886},\r
+{0, 74506, 5860},\r
+{0, 72984, 5866},\r
+{0, 71718, 5857},\r
+{0, 70789, 5854},\r
+{0, 70106, 5851},\r
+{0, 69559, 5845},\r
+{0, 69000, 5840},\r
+{0, 68416, 5827},\r
+{0, 67926, 5840},\r
+{0, 67615, 5840},\r
+{0, 67369, 5826},\r
+{0, 66701, 5816},\r
+{0, 65556, 5820},\r
+{0, 64648, 5827},\r
+{0, 63936, 5806},\r
+{0, 63453, 5806},\r
+{0, 63170, 5815},\r
+{0, 62967, 5818},\r
+{0, 62761, 5801},\r
+{0, 62594, 5806},\r
+{0, 62541, 5807},\r
+{0, 62525, 5799},\r
+{0, 62088, 5792},\r
+{0, 61096, 5784},\r
+{0, 60432, 5782},\r
+{0, 60066, 5777},\r
+{0, 59871, 5789},\r
+{0, 59953, 5791},\r
+{0, 60000, 5791},\r
+{0, 60065, 5788},\r
+{0, 60235, 5786},\r
+{0, 60431, 5797},\r
+{0, 60713, 5797},\r
+{0, 60770, 5797},\r
+{0, 60015, 5801},\r
+{0, 59364, 5796},\r
+{0, 59129, 5776},\r
+{0, 59016, 5790},\r
+{0, 59049, 5791},\r
+{0, 59116, 5783},\r
+{0, 59132, 5786},\r
+{0, 59220, 5786},\r
+{0, 59394, 5795},\r
+{0, 59670, 5788},\r
+{0, 59727, 5788},\r
+{0, 59063, 5796},\r
+{0, 58552, 5788},\r
+{0, 58411, 5771},\r
+{0, 58361, 5771},\r
+{0, 58441, 5776},\r
+{0, 58643, 5771},\r
+{0, 58852, 5785},\r
+{0, 59047, 5777},\r
+{0, 59266, 5774},\r
+{0, 59575, 5779},\r
+{0, 59891, 5786},\r
+{0, 59477, 5801},\r
+{0, 58938, 5776},\r
+{0, 58697, 5772},\r
+{0, 58468, 5779},\r
+{0, 58370, 5771},\r
+{0, 58427, 5764},\r
+{0, 58382, 5775},\r
+{0, 58432, 5772},\r
+{0, 58479, 5781},\r
+{0, 58621, 5769},\r
+{0, 58790, 5773},\r
+{0, 58663, 5771},\r
+{0, 58086, 5758},\r
+{0, 57739, 5760},\r
+{0, 57461, 5759},\r
+{0, 57334, 5755},\r
+{0, 57343, 5751},\r
+{0, 57375, 5758},\r
+{0, 57431, 5746},\r
+{0, 57478, 5755},\r
+{0, 57565, 5755},\r
+{0, 57716, 5756},\r
+{0, 57982, 5749},\r
+{0, 57981, 5750},\r
+{0, 57916, 5757},\r
+{0, 57709, 5734},\r
+{0, 57546, 5743},\r
+{0, 57514, 5749},\r
+{0, 57607, 5742},\r
+{0, 57762, 5745},\r
+{0, 57895, 5749},\r
+{0, 58073, 5756},\r
+{0, 58254, 5751},\r
+{0, 58467, 5754},\r
+{0, 58649, 5742},\r
+{0, 58465, 5755},\r
+{0, 58106, 5747},\r
+{0, 57839, 5753},\r
+{0, 57640, 5741},\r
+{0, 57646, 5744},\r
+{0, 57765, 5744},\r
+{0, 57903, 5733},\r
+{0, 58067, 5750},\r
+{0, 58267, 5750},\r
+{0, 58492, 5758},\r
+{0, 58740, 5746},\r
+{0, 58888, 5746},\r
+{0, 58582, 5749},\r
+{0, 58189, 5741},\r
+{0, 58011, 5749},\r
+{0, 58024, 5743},\r
+{0, 58121, 5752},\r
+{0, 58343, 5745},\r
+{0, 58442, 5751},\r
+{0, 58542, 5750},\r
+{0, 58672, 5766},\r
+{0, 58794, 5753},\r
+{0, 58959, 5753},\r
+{0, 58984, 5760},\r
+{0, 58907, 5758},\r
+{0, 58684, 5751},\r
+{0, 58478, 5740},\r
+{0, 58365, 5746},\r
+{0, 58427, 5745},\r
+{0, 58506, 5751},\r
+{0, 58578, 5744},\r
+{0, 58631, 5751},\r
+{0, 58713, 5762},\r
+{0, 58823, 5748},\r
+{0, 58954, 5749},\r
+{0, 59096, 5754},\r
+{0, 58921, 5745},\r
+{0, 58644, 5748},\r
+{0, 58535, 5737},\r
+{0, 58464, 5744},\r
+{0, 58465, 5742},\r
+{0, 58579, 5748},\r
+{0, 58640, 5750},\r
+{0, 58767, 5753},\r
+{0, 58864, 5743},\r
+{0, 59022, 5758},\r
+{0, 59158, 5755},\r
+{0, 59290, 5754},\r
+{0, 59226, 5755},\r
+{0, 58941, 5751},\r
+{0, 58717, 5758},\r
+{0, 58687, 5748},\r
+{0, 58599, 5748},\r
+{0, 58670, 5744},\r
+{0, 58694, 5744},\r
+{0, 58653, 5730},\r
+{0, 58575, 5736},\r
+{0, 58443, 5738},\r
+{0, 58226, 5737},\r
+{0, 57957, 5731},\r
+{0, 57664, 5744},\r
+{0, 57410, 5727},\r
+{0, 57131, 5731},\r
+{0, 57002, 5729},\r
+{0, 56949, 5726},\r
+{0, 56996, 5734},\r
+{0, 57041, 5736},\r
+{0, 57073, 5740},\r
+{0, 57122, 5733},\r
+{0, 57229, 5737},\r
+{0, 57328, 5738},\r
+{0, 57443, 5738},\r
+{0, 57591, 5734},\r
+{0, 57670, 5737},\r
+{0, 57489, 5742},\r
+{0, 57335, 5727},\r
+{0, 57307, 5729},\r
+{0, 57370, 5730},\r
+{0, 57454, 5725},\r
+{0, 57553, 5731},\r
+{0, 57636, 5726},\r
+{0, 57694, 5731},\r
+{0, 57782, 5723},\r
+{0, 57860, 5731},\r
+{0, 57953, 5737},\r
+{0, 57978, 5735},\r
+{0, 57758, 5737},\r
+{0, 57593, 5730},\r
+{0, 57484, 5734},\r
+{0, 57454, 5735},\r
+{0, 57447, 5717},\r
+{0, 57429, 5728},\r
+{0, 57402, 5740},\r
+{0, 57444, 5734},\r
+{0, 57493, 5727},\r
+{0, 57583, 5723},\r
+{0, 57683, 5725},\r
+{0, 57812, 5729},\r
+{0, 57658, 5716},\r
+{0, 57615, 5722},\r
+{0, 57641, 5721},\r
+{0, 57787, 5715},\r
+{0, 57986, 5733},\r
+{0, 58116, 5725},\r
+{0, 58211, 5727},\r
+{0, 58335, 5724},\r
+{0, 58464, 5724},\r
+{0, 58575, 5719},\r
+{0, 58657, 5734},\r
+{0, 58753, 5740},\r
+{0, 58533, 5730},\r
+{0, 58259, 5721},\r
+{0, 58161, 5726},\r
+{0, 58156, 5737},\r
+{0, 58106, 5727},\r
+{0, 58076, 5737},\r
+{0, 58128, 5731},\r
+{0, 58129, 5735},\r
+{0, 58213, 5727},\r
+{0, 58282, 5733},\r
+{0, 58282, 5728},\r
+{0, 58252, 5728},\r
+{0, 57998, 5721},\r
+{0, 57697, 5706},\r
+{0, 57559, 5719},\r
+{0, 57528, 5713},\r
+{0, 57520, 5723},\r
+{0, 57651, 5727},\r
+{0, 57819, 5719},\r
+{0, 58009, 5717},\r
+{0, 58287, 5733},\r
+{0, 58597, 5741},\r
+{0, 58811, 5732},\r
+{0, 59046, 5744},\r
+{0, 59025, 5726},\r
+{0, 58912, 5734},\r
+{0, 58919, 5738},\r
+{0, 59012, 5732},\r
+{0, 59143, 5748},\r
+{0, 59188, 5745},\r
+{0, 59227, 5749},\r
+{0, 59316, 5743},\r
+{0, 59358, 5740},\r
+{0, 59496, 5750},\r
+{0, 59627, 5751},\r
+{0, 59740, 5746},\r
+{0, 59647, 5735},\r
+{0, 59492, 5738},\r
+{0, 59361, 5725},\r
+{0, 59307, 5727},\r
+{0, 59357, 5728},\r
+{0, 59335, 5731},\r
+{0, 59163, 5729},\r
+{0, 58947, 5736},\r
+{0, 58960, 5747},\r
+{0, 59110, 5739},\r
+{0, 59246, 5744},\r
+{0, 59243, 5742},\r
+{0, 58958, 5732},\r
+{0, 58742, 5735},\r
+{0, 58692, 5725},\r
+{0, 58708, 5746},\r
+{0, 58787, 5744},\r
+{0, 59036, 5750},\r
+{0, 59671, 5735},\r
+{0, 60295, 5756},\r
+{0, 60927, 5763},\r
+{0, 61483, 5775},\r
+{0, 62005, 5778},\r
+{0, 62364, 5775},\r
+{0, 62685, 5780},\r
+{0, 63073, 5793},\r
+{0, 63430, 5798},\r
+{0, 63809, 5806},\r
+{0, 64149, 5810},\r
+{0, 64475, 5804},\r
+{0, 64774, 5810},\r
+{0, 65019, 5809},\r
+{0, 65321, 5807},\r
+{0, 65612, 5812},\r
+{0, 65791, 5818},\r
+{0, 65710, 5815},\r
+{0, 65624, 5802},\r
+{0, 65575, 5809},\r
+{0, 65443, 5800},\r
+{0, 65313, 5812},\r
+{0, 65198, 5812},\r
+{0, 65152, 5796},\r
+{0, 65148, 5795},\r
+{0, 65237, 5799},\r
+{0, 65317, 5799},\r
+{0, 65423, 5803},\r
+{0, 65467, 5800},\r
+{0, 65256, 5792},\r
+{0, 65124, 5790},\r
+{0, 65061, 5803},\r
+{0, 65012, 5796},\r
+{0, 64980, 5796},\r
+{0, 64932, 5792},\r
+{0, 64922, 5795},\r
+{0, 64895, 5803},\r
+{0, 64900, 5798},\r
+{0, 64872, 5798},\r
+{0, 64872, 5793},\r
+{0, 64747, 5789},\r
+{0, 64413, 5798},\r
+{0, 64165, 5794},\r
+{0, 63986, 5790},\r
+{0, 63882, 5781},\r
+{0, 63760, 5789},\r
+{0, 63792, 5780},\r
+{0, 63732, 5794},\r
+{0, 63781, 5788},\r
+{0, 63736, 5803},\r
+{0, 63854, 5791},\r
+{0, 63865, 5789},\r
+{0, 63866, 5799},\r
+{0, 63594, 5778},\r
+{0, 63433, 5777},\r
+{0, 63378, 5791},\r
+{0, 63409, 5779},\r
+{0, 63463, 5764},\r
+{0, 63486, 5775},\r
+{0, 63487, 5787},\r
+{0, 63572, 5778},\r
+{0, 63735, 5783},\r
+{0, 63803, 5773},\r
+{0, 63922, 5785},\r
+{0, 64029, 5783},\r
+{0, 63849, 5789},\r
+{0, 63604, 5785},\r
+{0, 63504, 5782},\r
+{0, 63472, 5774},\r
+{0, 63538, 5777},\r
+{0, 63570, 5775},\r
+{0, 63577, 5784},\r
+{0, 63590, 5776},\r
+{0, 63669, 5778},\r
+{0, 63772, 5782},\r
+{0, 63856, 5779},\r
+{0, 63959, 5779},\r
+{0, 63837, 5784},\r
+{0, 63557, 5776},\r
+{0, 63414, 5778},\r
+{0, 63370, 5781},\r
+{0, 63343, 5787},\r
+{0, 63346, 5781},\r
+{0, 63259, 5773},\r
+{0, 63253, 5771},\r
+{0, 63201, 5782},\r
+{0, 63234, 5782},\r
+{0, 63266, 5773},\r
+{0, 63307, 5774},\r
+{0, 63246, 5774},\r
+{0, 62919, 5769},\r
+{0, 62727, 5774},\r
+{0, 62685, 5779},\r
+{0, 62739, 5766},\r
+{0, 62789, 5759},\r
+{0, 62847, 5762},\r
+{0, 63030, 5765},\r
+{0, 63262, 5770},\r
+{0, 63561, 5784},\r
+{0, 63943, 5792},\r
+{0, 64274, 5795},\r
+{0, 64520, 5789},\r
+{0, 64439, 5796},\r
+{0, 64276, 5802},\r
+{0, 64338, 5792},\r
+{0, 64500, 5801},\r
+{0, 64753, 5805},\r
+{0, 65005, 5806},\r
+{0, 65246, 5809},\r
+{0, 65430, 5798},\r
+{0, 65691, 5809},\r
+{0, 65870, 5815},\r
+{0, 66098, 5807},\r
+{0, 66239, 5814},\r
+{0, 65989, 5813},\r
+{0, 65656, 5812},\r
+{0, 65523, 5810},\r
+{0, 65470, 5802},\r
+{0, 65429, 5798},\r
+{0, 65380, 5802},\r
+{0, 65218, 5793},\r
+{0, 65087, 5787},\r
+{0, 64942, 5787},\r
+{0, 64877, 5793},\r
+{0, 64720, 5796},\r
+{0, 64662, 5780},\r
+{0, 64332, 5772},\r
+{0, 63902, 5763},\r
+{0, 63639, 5763},\r
+{0, 63495, 5766},\r
+{0, 63367, 5760},\r
+{0, 63324, 5764},\r
+{0, 63315, 5772},\r
+{0, 63263, 5764},\r
+{0, 63258, 5755},\r
+{0, 63344, 5763},\r
+{0, 63369, 5758},\r
+{0, 63416, 5762},\r
+{0, 63060, 5755},\r
+{0, 62872, 5763},\r
+{0, 62919, 5769},\r
+{0, 63045, 5764},\r
+{0, 63173, 5786},\r
+{0, 63278, 5775},\r
+{0, 63357, 5774},\r
+{0, 63445, 5773},\r
+{0, 63543, 5781},\r
+{0, 63648, 5780},\r
+{0, 63715, 5782},\r
+{0, 63488, 5777},\r
+{0, 62867, 5780},\r
+{0, 62518, 5783},\r
+{0, 62258, 5773},\r
+{0, 62083, 5771},\r
+{0, 61984, 5770},\r
+{0, 61896, 5759},\r
+{0, 61733, 5761},\r
+{0, 61567, 5759},\r
+{0, 61535, 5768},\r
+{0, 61595, 5758},\r
+{0, 61726, 5775},\r
+{0, 61675, 5762},\r
+{0, 61330, 5759},\r
+{0, 61190, 5756},\r
+{0, 61269, 5765},\r
+{0, 61508, 5774},\r
+{0, 61756, 5778},\r
+{0, 62028, 5785},\r
+{0, 62209, 5787},\r
+{0, 62461, 5787},\r
+{0, 62716, 5793},\r
+{0, 63008, 5787},\r
+{0, 63274, 5792},\r
+{0, 63253, 5789},\r
+{0, 62966, 5791},\r
+{0, 62966, 5788},\r
+{0, 62994, 5784},\r
+{0, 63066, 5796},\r
+{0, 63155, 5789},\r
+{0, 63205, 5792},\r
+{0, 63262, 5789},\r
+{0, 63272, 5793},\r
+{0, 63273, 5791},\r
+{0, 63206, 5779},\r
+{0, 63087, 5779},\r
+{0, 62588, 5777},\r
+{0, 62075, 5771},\r
+{0, 61794, 5769},\r
+{0, 61577, 5768},\r
+{0, 61466, 5766},\r
+{0, 61429, 5764},\r
+{0, 61455, 5758},\r
+{0, 61475, 5757},\r
+{0, 61626, 5755},\r
+{0, 61776, 5768},\r
+{0, 61934, 5752},\r
+{0, 61846, 5756},\r
+{0, 61389, 5753},\r
+{0, 61208, 5746},\r
+{0, 61084, 5748},\r
+{0, 61091, 5751},\r
+{0, 61154, 5746},\r
+{0, 61209, 5748},\r
+{0, 61262, 5759},\r
+{0, 61363, 5743},\r
+{0, 61588, 5752},\r
+{0, 61931, 5766},\r
+{0, 62269, 5764},\r
+{0, 62412, 5769},\r
+{0, 62312, 5770},\r
+{0, 62235, 5771},\r
+{0, 62334, 5778},\r
+{0, 62378, 5772},\r
+{0, 62394, 5772},\r
+{0, 62360, 5760},\r
+{0, 62291, 5763},\r
+{0, 62295, 5761},\r
+{0, 62378, 5751},\r
+{0, 62481, 5762},\r
+{0, 62624, 5774},\r
+{0, 62644, 5772},\r
+{0, 62389, 5770},\r
+{0, 62120, 5764},\r
+{0, 61878, 5753},\r
+{0, 61725, 5762},\r
+{0, 61746, 5757},\r
+{0, 61881, 5766},\r
+{0, 62153, 5760},\r
+{0, 62325, 5761},\r
+{0, 62548, 5761},\r
+{0, 62669, 5754},\r
+{0, 62879, 5764},\r
+{0, 62629, 5756},\r
+{0, 62332, 5769},\r
+{0, 62140, 5761},\r
+{0, 62120, 5757},\r
+{0, 62169, 5762},\r
+{0, 62272, 5766},\r
+{0, 62331, 5762},\r
+{0, 62382, 5769},\r
+{0, 62445, 5763},\r
+{0, 62407, 5762},\r
+{0, 62353, 5774},\r
+{0, 62361, 5773},\r
+{0, 62135, 5773},\r
+{0, 61827, 5766},\r
+{0, 61601, 5750},\r
+{0, 61589, 5761},\r
+{0, 61690, 5749},\r
+{0, 61801, 5744},\r
+{0, 61820, 5740},\r
+{0, 61842, 5747},\r
+{0, 61860, 5766},\r
+{0, 62029, 5760},\r
+{0, 62251, 5762},\r
+{0, 62550, 5769},\r
+{0, 62878, 5776},\r
+{0, 62925, 5768},\r
+{0, 62918, 5763},\r
+{0, 63128, 5777},\r
+{0, 63394, 5775},\r
+{0, 63669, 5780},\r
+{0, 63835, 5778},\r
+{0, 64013, 5789},\r
+{0, 64079, 5779},\r
+{0, 64186, 5784},\r
+{0, 64308, 5778},\r
+{0, 64334, 5784},\r
+{0, 64282, 5794},\r
+{0, 63926, 5776},\r
+{0, 63585, 5769},\r
+{0, 63334, 5760},\r
+{0, 63121, 5765},\r
+{0, 63129, 5768},\r
+{0, 63284, 5767},\r
+{0, 63503, 5765},\r
+{0, 63541, 5765},\r
+{0, 63550, 5769},\r
+{0, 63622, 5780},\r
+{0, 63724, 5771},\r
+{0, 63704, 5767},\r
+{0, 63429, 5774},\r
+{0, 63210, 5761},\r
+{0, 63150, 5774},\r
+{0, 63176, 5783},\r
+{0, 63244, 5765},\r
+{0, 63444, 5773},\r
+{0, 63690, 5795},\r
+{0, 63968, 5803},\r
+{0, 64241, 5807},\r
+{0, 64575, 5809},\r
+{0, 65009, 5814},\r
+{0, 65276, 5815},\r
+{0, 65257, 5803},\r
+{0, 65316, 5824},\r
+{0, 65368, 5818},\r
+{0, 65327, 5811},\r
+{0, 65260, 5814},\r
+{0, 65179, 5804},\r
+{0, 65040, 5801},\r
+{0, 64913, 5807},\r
+{0, 64802, 5797},\r
+{0, 64718, 5799},\r
+{0, 64611, 5797},\r
+{0, 64415, 5800},\r
+{0, 64046, 5793},\r
+{0, 63772, 5780},\r
+{0, 63499, 5775},\r
+{0, 63292, 5772},\r
+{0, 63055, 5758},\r
+{0, 62893, 5769},\r
+{0, 62851, 5762},\r
+{0, 62815, 5777},\r
+{0, 62848, 5775},\r
+{0, 62991, 5762},\r
+{0, 63131, 5772},\r
+{0, 62987, 5772},\r
+{0, 62700, 5771},\r
+{0, 62261, 5772},\r
+{0, 61915, 5753},\r
+{0, 61787, 5761},\r
+{0, 61831, 5763},\r
+{0, 61778, 5762},\r
+{0, 61723, 5754},\r
+{0, 61759, 5757},\r
+{0, 61860, 5750},\r
+{0, 61924, 5764},\r
+{0, 61758, 5756},\r
+{0, 61283, 5755},\r
+{0, 60873, 5753},\r
+{0, 60417, 5741},\r
+{0, 60167, 5751},\r
+{0, 59971, 5744},\r
+{0, 59851, 5749},\r
+{0, 59669, 5757},\r
+{0, 59506, 5756},\r
+{0, 59345, 5757},\r
+{0, 59243, 5752},\r
+{0, 59105, 5761},\r
+{0, 58659, 5769},\r
+{0, 57940, 5761},\r
+{0, 57566, 5749},\r
+{0, 57450, 5748},\r
+{0, 57445, 5745},\r
+{0, 57486, 5738},\r
+{0, 57651, 5744},\r
+{0, 57905, 5750},\r
+{0, 58216, 5751},\r
+{0, 58463, 5750},\r
+{0, 58707, 5755},\r
+{0, 58813, 5761},\r
+{0, 58531, 5752},\r
+{0, 58351, 5752},\r
+{0, 58368, 5753},\r
+{0, 58483, 5749},\r
+{0, 58537, 5752},\r
+{0, 58424, 5758},\r
+{0, 58200, 5751},\r
+{0, 58067, 5754},\r
+{0, 58120, 5753},\r
+{0, 58109, 5758},\r
+{0, 58206, 5758},\r
+{0, 58438, 5759},\r
+{0, 58333, 5757},\r
+{0, 58264, 5761},\r
+{0, 58408, 5762},\r
+{0, 58653, 5771},\r
+{0, 58882, 5773},\r
+{0, 59063, 5785},\r
+{0, 59244, 5778},\r
+{0, 59428, 5782},\r
+{0, 59686, 5780},\r
+{0, 59884, 5786},\r
+{0, 60120, 5780},\r
+{0, 59927, 5770},\r
+{0, 59720, 5783},\r
+{0, 59758, 5768},\r
+{0, 59921, 5776},\r
+{0, 60162, 5772},\r
+{0, 60400, 5777},\r
+{0, 60629, 5786},\r
+{0, 60963, 5788},\r
+{0, 61245, 5785},\r
+{0, 61478, 5798},\r
+{0, 61742, 5795},\r
+{0, 61906, 5801},\r
+{0, 61764, 5779},\r
+{0, 61563, 5771},\r
+{0, 61160, 5783},\r
+{0, 60853, 5774},\r
+{0, 60623, 5767},\r
+{0, 60401, 5764},\r
+{0, 60175, 5760},\r
+{0, 60017, 5747},\r
+{0, 59984, 5741},\r
+{0, 60044, 5749},\r
+{0, 60098, 5757},\r
+{0, 60058, 5750},\r
+{0, 59791, 5745},\r
+{0, 59593, 5738},\r
+{0, 59563, 5749},\r
+{0, 59562, 5745},\r
+{0, 59708, 5750},\r
+{0, 59850, 5761},\r
+{0, 60212, 5763},\r
+{0, 60788, 5772},\r
+{0, 61619, 5794},\r
+{0, 62580, 5807},\r
+{0, 63490, 5819},\r
+{0, 64080, 5810},\r
+{0, 64358, 5800},\r
+{0, 64702, 5810},\r
+{0, 65016, 5820},\r
+{0, 65346, 5815},\r
+{0, 65728, 5818},\r
+{0, 66106, 5825},\r
+{0, 66387, 5819},\r
+{0, 66487, 5803},\r
+{0, 66536, 5816},\r
+{0, 66665, 5812},\r
+{0, 66835, 5817},\r
+{0, 66918, 5815},\r
+{0, 66891, 5813},\r
+{0, 67104, 5823},\r
+{0, 67512, 5839},\r
+{0, 68016, 5847},\r
+{0, 68617, 5847},\r
+{0, 69134, 5837},\r
+{0, 69657, 5851},\r
+{0, 70277, 5850},\r
+{0, 70854, 5863},\r
+{0, 71531, 5868},\r
+{0, 72171, 5862},\r
+{0, 72584, 5858},\r
+{0, 72533, 5855},\r
+{0, 72529, 5860},\r
+{0, 72557, 5862},\r
+{0, 72559, 5848},\r
+{0, 72536, 5844},\r
+{0, 72540, 5857},\r
+{0, 72433, 5841},\r
+{0, 72360, 5839},\r
+{0, 72366, 5852},\r
+{0, 72429, 5853},\r
+{0, 72535, 5851},\r
+{0, 72559, 5844},\r
+{0, 72224, 5850},\r
+{0, 71803, 5831},\r
+{0, 71524, 5836},\r
+{0, 71237, 5830},\r
+{0, 70999, 5843},\r
+{0, 70703, 5831},\r
+{0, 70440, 5836},\r
+{0, 70200, 5825},\r
+{0, 70089, 5816},\r
+{0, 70102, 5825},\r
+{0, 70163, 5826},\r
+{0, 70264, 5824},\r
+{0, 69955, 5808},\r
+{0, 69458, 5817},\r
+{0, 69074, 5824},\r
+{0, 68792, 5815},\r
+{0, 68544, 5812},\r
+{0, 68363, 5816},\r
+{0, 68082, 5811},\r
+{0, 67793, 5806},\r
+{0, 67555, 5821},\r
+{0, 67313, 5802},\r
+{0, 67154, 5801},\r
+{0, 67135, 5806},\r
+{0, 66807, 5797},\r
+{0, 66342, 5796},\r
+{0, 65999, 5786},\r
+{0, 65750, 5789},\r
+{0, 65594, 5800},\r
+{0, 65564, 5798},\r
+{0, 65579, 5805},\r
+{0, 65708, 5793},\r
+{0, 65976, 5812},\r
+{0, 66309, 5818},\r
+{0, 66750, 5820},\r
+{0, 67196, 5828},\r
+{0, 67576, 5835},\r
+{0, 67401, 5824},\r
+{0, 67390, 5817},\r
+{0, 67687, 5828},\r
+{0, 68049, 5825},\r
+{0, 68289, 5837},\r
+{0, 68354, 5834},\r
+{0, 68266, 5829},\r
+{0, 68110, 5824},\r
+{0, 68086, 5824},\r
+{0, 68194, 5830},\r
+{0, 68355, 5820},\r
+{0, 68271, 5830},\r
+{0, 67668, 5818},\r
+{0, 67010, 5799},\r
+{0, 66590, 5790},\r
+{0, 66325, 5801},\r
+{0, 66197, 5803},\r
+{0, 66116, 5811},\r
+{0, 66067, 5796},\r
+{0, 66104, 5801},\r
+{0, 66128, 5794},\r
+{0, 66202, 5801},\r
+{0, 66259, 5798},\r
+{0, 66405, 5796},\r
+{0, 66178, 5803},\r
+{0, 65969, 5809},\r
+{0, 65970, 5826},\r
+{0, 66127, 5832},\r
+{0, 66350, 5823},\r
+{0, 66644, 5831},\r
+{0, 66948, 5833},\r
+{0, 67228, 5830},\r
+{0, 67423, 5831},\r
+{0, 67608, 5829},\r
+{0, 67628, 5835},\r
+{0, 67624, 5834},\r
+{0, 67072, 5819},\r
+{0, 66363, 5809},\r
+{0, 65909, 5814},\r
+{0, 65618, 5802},\r
+{0, 65434, 5811},\r
+{0, 65385, 5802},\r
+{0, 65371, 5799},\r
+{0, 65307, 5803},\r
+{0, 65389, 5807},\r
+{0, 65475, 5803},\r
+{0, 65600, 5797},\r
+{0, 65817, 5791},\r
+{0, 65903, 5795},\r
+{0, 65955, 5785},\r
+{0, 66018, 5803},\r
+{0, 66068, 5803},\r
+{0, 66256, 5823},\r
+{0, 66470, 5814},\r
+{0, 66754, 5827},\r
+{0, 66957, 5815},\r
+{0, 67166, 5819},\r
+{0, 67434, 5823},\r
+{0, 67766, 5814},\r
+{0, 67944, 5823},\r
+{0, 67453, 5815},\r
+{0, 66912, 5822},\r
+{0, 66562, 5816},\r
+{0, 66312, 5808},\r
+{0, 66113, 5809},\r
+{0, 66043, 5800},\r
+{0, 66037, 5791},\r
+{0, 66111, 5790},\r
+{0, 66138, 5798},\r
+{0, 66118, 5794},\r
+{0, 66166, 5803},\r
+{0, 65942, 5807},\r
+{0, 65162, 5806},\r
+{0, 64551, 5788},\r
+{0, 64171, 5790},\r
+{0, 64015, 5781},\r
+{0, 63944, 5776},\r
+{0, 63951, 5782},\r
+{0, 63982, 5786},\r
+{0, 64003, 5775},\r
+{0, 64111, 5764},\r
+{0, 64352, 5773},\r
+{0, 64586, 5778},\r
+{0, 64494, 5786},\r
+{0, 63841, 5793},\r
+{0, 63485, 5772},\r
+{0, 63356, 5772},\r
+{0, 63387, 5781},\r
+{0, 63461, 5781},\r
+{0, 63500, 5785},\r
+{0, 63508, 5800},\r
+{0, 63672, 5794},\r
+{0, 63958, 5790},\r
+{0, 64148, 5802},\r
+{0, 64287, 5803},\r
+{0, 64042, 5794},\r
+{0, 63661, 5795},\r
+{0, 63571, 5774},\r
+{0, 63626, 5783},\r
+{0, 63707, 5791},\r
+{0, 63814, 5801},\r
+{0, 63880, 5785},\r
+{0, 63927, 5803},\r
+{0, 64073, 5797},\r
+{0, 64378, 5796},\r
+{0, 64669, 5804},\r
+{0, 64946, 5804},\r
+{0, 64931, 5813},\r
+{0, 64756, 5802},\r
+{0, 64879, 5801},\r
+{0, 65114, 5806},\r
+{0, 65326, 5811},\r
+{0, 65482, 5805},\r
+{0, 65343, 5802},\r
+{0, 65069, 5793},\r
+{0, 64859, 5782},\r
+{0, 64643, 5790},\r
+{0, 64495, 5801},\r
+{0, 64215, 5786},\r
+{0, 63659, 5771},\r
+{0, 63267, 5771},\r
+{0, 63058, 5777},\r
+{0, 63026, 5772},\r
+{0, 63035, 5765},\r
+{0, 63062, 5765},\r
+{0, 62976, 5773},\r
+{0, 63006, 5776},\r
+{0, 63091, 5769},\r
+{0, 63301, 5774},\r
+{0, 63552, 5779},\r
+{0, 63545, 5769},\r
+{0, 63334, 5769},\r
+{0, 63208, 5782},\r
+{0, 63195, 5785},\r
+{0, 63141, 5778},\r
+{0, 63223, 5777},\r
+{0, 63365, 5770},\r
+{0, 63532, 5776},\r
+{0, 63595, 5770},\r
+{0, 63604, 5771},\r
+{0, 63612, 5767},\r
+{0, 63617, 5763},\r
+{0, 63330, 5759},\r
+{0, 63173, 5761},\r
+{0, 63254, 5759},\r
+{0, 63392, 5767},\r
+{0, 63557, 5776},\r
+{0, 63637, 5778},\r
+{0, 63674, 5785},\r
+{0, 63563, 5781},\r
+{0, 63390, 5773},\r
+{0, 63113, 5785},\r
+{0, 62949, 5781},\r
+{0, 62921, 5764},\r
+{0, 62731, 5772},\r
+{0, 62536, 5787},\r
+{0, 62566, 5779},\r
+{0, 62709, 5770},\r
+{0, 62973, 5761},\r
+{0, 62930, 5760},\r
+{0, 62722, 5768},\r
+{0, 62678, 5783},\r
+{0, 62750, 5773},\r
+{0, 62701, 5787},\r
+{0, 62641, 5766},\r
+{0, 62456, 5768},\r
+{0, 62061, 5769},\r
+{0, 61566, 5766},\r
+{0, 61094, 5759},\r
+{0, 60794, 5753},\r
+{0, 60716, 5763},\r
+{0, 60749, 5765},\r
+{0, 60691, 5766},\r
+{0, 60600, 5764},\r
+{0, 60608, 5762},\r
+{0, 60806, 5777},\r
+{0, 60900, 5761},\r
+{0, 60554, 5757},\r
+{0, 60184, 5767},\r
+{0, 60018, 5775},\r
+{0, 60038, 5756},\r
+{0, 60070, 5762},\r
+{0, 60201, 5765},\r
+{0, 60224, 5762},\r
+{0, 60226, 5762},\r
+{0, 60238, 5760},\r
+{0, 60294, 5759},\r
+{0, 60325, 5760},\r
+{0, 59975, 5763},\r
+{0, 59527, 5752},\r
+{0, 59243, 5747},\r
+{0, 59081, 5761},\r
+{0, 58982, 5754},\r
+{0, 59055, 5752},\r
+{0, 59020, 5769},\r
+{0, 58892, 5757},\r
+{0, 58811, 5770},\r
+{0, 58830, 5755},\r
+{0, 59012, 5760},\r
+{0, 58978, 5756},\r
+{0, 58707, 5739},\r
+{0, 58480, 5747},\r
+{0, 58500, 5750},\r
+{0, 58540, 5749},\r
+{0, 58683, 5751},\r
+{0, 58817, 5755},\r
+{0, 58919, 5747},\r
+{0, 59049, 5758},\r
+{0, 59185, 5754},\r
+{0, 59365, 5753},\r
+{0, 59505, 5756},\r
+{0, 59120, 5746},\r
+{0, 58775, 5738},\r
+{0, 58560, 5743},\r
+{0, 58458, 5742},\r
+{0, 58326, 5742},\r
+{0, 58099, 5744},\r
+{0, 57782, 5750},\r
+{0, 57663, 5747},\r
+{0, 57583, 5751},\r
+{0, 57501, 5759},\r
+{0, 57472, 5747},\r
+{0, 57352, 5762},\r
+{0, 57101, 5763},\r
+{0, 57000, 5754},\r
+{0, 57037, 5744},\r
+{0, 57180, 5745},\r
+{0, 57364, 5750},\r
+{0, 57533, 5755},\r
+{0, 57798, 5751},\r
+{0, 58047, 5752},\r
+{0, 58303, 5758},\r
+{0, 58605, 5755},\r
+{0, 58525, 5741},\r
+{0, 58442, 5743},\r
+{0, 58462, 5742},\r
+{0, 58490, 5739},\r
+{0, 58560, 5748},\r
+{0, 58525, 5749},\r
+{0, 58540, 5750},\r
+{0, 58503, 5746},\r
+{0, 58493, 5761},\r
+{0, 58545, 5739},\r
+{0, 58611, 5745},\r
+{0, 58398, 5744},\r
+{0, 58150, 5735},\r
+{0, 57974, 5747},\r
+{0, 57910, 5753},\r
+{0, 57873, 5755},\r
+{0, 57974, 5747},\r
+{0, 58039, 5739},\r
+{0, 58109, 5743},\r
+{0, 58262, 5747},\r
+{0, 58475, 5745},\r
+{0, 58743, 5746},\r
+{0, 58708, 5744},\r
+{0, 58682, 5740},\r
+{0, 58788, 5742},\r
+{0, 58870, 5735},\r
+{0, 59011, 5753},\r
+{0, 59102, 5744},\r
+{0, 59174, 5757},\r
+{0, 59160, 5765},\r
+{0, 59160, 5750},\r
+{0, 59133, 5736},\r
+{0, 59067, 5755},\r
+{0, 58809, 5752},\r
+{0, 58558, 5738},\r
+{0, 58407, 5739},\r
+{0, 58292, 5748},\r
+{0, 58251, 5740},\r
+{0, 58202, 5753},\r
+{0, 58198, 5752},\r
+{0, 58281, 5752},\r
+{0, 58366, 5745},\r
+{0, 58480, 5749},\r
+{0, 58661, 5750},\r
+{0, 58558, 5754},\r
+{0, 58560, 5735},\r
+{0, 58650, 5732},\r
+{0, 58802, 5744},\r
+{0, 59016, 5745},\r
+{0, 59198, 5744},\r
+{0, 59345, 5745},\r
+{0, 59413, 5746},\r
+{0, 59437, 5751},\r
+{0, 59463, 5743},\r
+{0, 59468, 5751},\r
+{0, 59121, 5749},\r
+{0, 58823, 5741},\r
+{0, 58629, 5749},\r
+{0, 58602, 5750},\r
+{0, 58552, 5750},\r
+{0, 58340, 5761},\r
+{0, 58175, 5760},\r
+{0, 58375, 5764},\r
+{0, 58742, 5756},\r
+{0, 59153, 5754},\r
+{0, 59574, 5776},\r
+{0, 59689, 5764},\r
+{0, 59730, 5765},\r
+{0, 59944, 5768},\r
+{0, 60291, 5767},\r
+{0, 60651, 5779},\r
+{0, 60970, 5778},\r
+{0, 61158, 5785},\r
+{0, 61301, 5789},\r
+{0, 61367, 5782},\r
+{0, 61452, 5783},\r
+{0, 61498, 5778},\r
+{0, 61177, 5765},\r
+{0, 60974, 5768},\r
+{0, 60937, 5779},\r
+{0, 60978, 5776},\r
+{0, 61039, 5773},\r
+{0, 61187, 5773},\r
+{0, 61391, 5770},\r
+{0, 61560, 5781},\r
+{0, 61708, 5771},\r
+{0, 61897, 5788},\r
+{0, 62062, 5781},\r
+{0, 61847, 5776},\r
+{0, 61679, 5774},\r
+{0, 61729, 5767},\r
+{0, 61817, 5762},\r
+{0, 62033, 5774},\r
+{0, 62435, 5781},\r
+{0, 62691, 5789},\r
+{0, 62874, 5778},\r
+{0, 62944, 5777},\r
+{0, 62923, 5779},\r
+{0, 62701, 5777},\r
+{0, 62265, 5769},\r
+{0, 61947, 5761},\r
+{0, 61728, 5770},\r
+{0, 61531, 5762},\r
+{0, 61388, 5766},\r
+{0, 61354, 5762},\r
+{0, 61261, 5760},\r
+{0, 61357, 5755},\r
+{0, 61658, 5767},\r
+{0, 61964, 5754},\r
+{0, 61978, 5752},\r
+{0, 61821, 5752},\r
+{0, 62047, 5752},\r
+{0, 62480, 5765},\r
+{0, 63117, 5784},\r
+{0, 63920, 5797},\r
+{0, 64722, 5820},\r
+{0, 65481, 5820},\r
+{0, 66153, 5840},\r
+{0, 66805, 5832},\r
+{0, 67430, 5830},\r
+{0, 67616, 5827},\r
+{0, 67176, 5799},\r
+{0, 66784, 5793},\r
+{0, 66504, 5784},\r
+{0, 66281, 5794},\r
+{0, 66279, 5800},\r
+{0, 66315, 5789},\r
+{0, 66427, 5794},\r
+{0, 66577, 5804},\r
+{0, 66901, 5812},\r
+{0, 67291, 5803},\r
+{0, 67197, 5807},\r
+{0, 66853, 5810},\r
+{0, 66640, 5799},\r
+{0, 66557, 5807},\r
+{0, 66489, 5808},\r
+{0, 66766, 5793},\r
+{0, 67121, 5817},\r
+{0, 67509, 5830},\r
+{0, 67877, 5826},\r
+{0, 68346, 5854},\r
+{0, 68755, 5840},\r
+{0, 68684, 5826},\r
+{0, 68376, 5810},\r
+{0, 68194, 5825},\r
+{0, 68102, 5820},\r
+{0, 68062, 5832},\r
+{0, 68109, 5815},\r
+{0, 68151, 5820},\r
+{0, 68191, 5810},\r
+{0, 68216, 5814},\r
+{0, 68286, 5829},\r
+{0, 68272, 5818},\r
+{0, 67857, 5811},\r
+{0, 67430, 5811},\r
+{0, 67198, 5808},\r
+{0, 67092, 5813},\r
+{0, 67054, 5812},\r
+{0, 67066, 5813},\r
+{0, 67162, 5817},\r
+{0, 67365, 5803},\r
+{0, 67515, 5823},\r
+{0, 67768, 5809},\r
+{0, 67856, 5817},\r
+{0, 67338, 5802},\r
+{0, 66942, 5818},\r
+{0, 66703, 5805},\r
+{0, 66609, 5818},\r
+{0, 66564, 5809},\r
+{0, 66526, 5814},\r
+{0, 66527, 5801},\r
+{0, 66432, 5804},\r
+{0, 66472, 5800},\r
+{0, 66588, 5799},\r
+{0, 66481, 5805},\r
+{0, 66056, 5796},\r
+{0, 65725, 5797},\r
+{0, 65665, 5795},\r
+{0, 65769, 5788},\r
+{0, 66041, 5791},\r
+{0, 66367, 5804},\r
+{0, 66625, 5811},\r
+{0, 66977, 5813},\r
+{0, 67326, 5818},\r
+{0, 67674, 5827},\r
+{0, 67523, 5818},\r
+{0, 67166, 5816},\r
+{0, 67022, 5814},\r
+{0, 67012, 5822},\r
+{0, 67069, 5810},\r
+{0, 67155, 5814},\r
+{0, 67175, 5823},\r
+{0, 67157, 5822},\r
+{0, 67220, 5814},\r
+{0, 67291, 5816},\r
+{0, 67360, 5808},\r
+{0, 66878, 5802},\r
+{0, 66324, 5808},\r
+{0, 65974, 5804},\r
+{0, 65771, 5792},\r
+{0, 65684, 5800},\r
+{0, 65698, 5797},\r
+{0, 65929, 5791},\r
+{0, 66161, 5804},\r
+{0, 66476, 5800},\r
+{0, 66790, 5811},\r
+{0, 66773, 5811},\r
+{0, 66449, 5805},\r
+{0, 66313, 5807},\r
+{0, 66311, 5804},\r
+{0, 66367, 5808},\r
+{0, 66407, 5801},\r
+{0, 66416, 5802},\r
+{0, 66329, 5807},\r
+{0, 66250, 5804},\r
+{0, 66168, 5804},\r
+{0, 65886, 5804},\r
+{0, 65142, 5794},\r
+{0, 64512, 5789},\r
+{0, 64154, 5792},\r
+{0, 63912, 5786},\r
+{0, 63745, 5783},\r
+{0, 63634, 5792},\r
+{0, 63618, 5781},\r
+{0, 63589, 5780},\r
+{0, 63621, 5784},\r
+{0, 63667, 5788},\r
+{0, 63723, 5775},\r
+{0, 63663, 5783},\r
+{0, 63543, 5781},\r
+{0, 63339, 5782},\r
+{0, 63415, 5785},\r
+{0, 63624, 5789},\r
+{0, 63856, 5790},\r
+{0, 64020, 5794},\r
+{0, 64166, 5786},\r
+{0, 64343, 5784},\r
+{0, 64011, 5788},\r
+{0, 63315, 5786},\r
+{0, 62970, 5781},\r
+{0, 62792, 5780},\r
+{0, 62726, 5779},\r
+{0, 62643, 5787},\r
+{0, 62619, 5769},\r
+{0, 62679, 5784},\r
+{0, 62745, 5781},\r
+{0, 62700, 5791},\r
+{0, 62715, 5785},\r
+{0, 62752, 5778},\r
+{0, 62799, 5784},\r
+{0, 62886, 5779},\r
+{0, 63014, 5777},\r
+{0, 63144, 5783},\r
+{0, 63154, 5773},\r
+{0, 63229, 5780},\r
+{0, 63342, 5798},\r
+{0, 63509, 5792},\r
+{0, 63717, 5777},\r
+{0, 63398, 5785},\r
+{0, 63108, 5783},\r
+{0, 63116, 5775},\r
+{0, 63216, 5775},\r
+{0, 63266, 5778},\r
+{0, 63243, 5771},\r
+{0, 63181, 5772},\r
+{0, 63147, 5782},\r
+{0, 63098, 5775},\r
+{0, 63081, 5767},\r
+{0, 62881, 5777},\r
+{0, 62521, 5773},\r
+{0, 62174, 5766},\r
+{0, 61926, 5762},\r
+{0, 62018, 5769},\r
+{0, 62183, 5772},\r
+{0, 62361, 5782},\r
+{0, 62569, 5774},\r
+{0, 62877, 5796},\r
+{0, 63329, 5813},\r
+{0, 63713, 5811},\r
+{0, 63611, 5812},\r
+{0, 63706, 5814},\r
+{0, 63983, 5806},\r
+{0, 64201, 5814},\r
+{0, 64393, 5814},\r
+{0, 64477, 5801},\r
+{0, 64463, 5795},\r
+{0, 64578, 5821},\r
+{0, 64567, 5806},\r
+{0, 64551, 5809},\r
+{0, 63995, 5803},\r
+{0, 63444, 5792},\r
+{0, 63179, 5788},\r
+{0, 63083, 5786},\r
+{0, 62980, 5785},\r
+{0, 63076, 5790},\r
+{0, 63157, 5795},\r
+{0, 63215, 5796},\r
+{0, 63245, 5782},\r
+{0, 63377, 5789},\r
+{0, 63108, 5779},\r
+{0, 62438, 5768},\r
+{0, 62142, 5767},\r
+{0, 62083, 5768},\r
+{0, 62217, 5782},\r
+{0, 62529, 5786},\r
+{0, 62895, 5785},\r
+{0, 63360, 5783},\r
+{0, 63766, 5790},\r
+{0, 63999, 5791},\r
+{0, 63939, 5785},\r
+{0, 63510, 5796},\r
+{0, 63254, 5793},\r
+{0, 63078, 5789},\r
+{0, 62948, 5798},\r
+{0, 62889, 5789},\r
+{0, 62802, 5789},\r
+{0, 62642, 5783},\r
+{0, 62496, 5771},\r
+{0, 62349, 5788},\r
+{0, 62173, 5776},\r
+{0, 61617, 5770},\r
+{0, 61141, 5772},\r
+{0, 60906, 5762},\r
+{0, 60834, 5761},\r
+{0, 60871, 5751},\r
+{0, 60932, 5757},\r
+{0, 61100, 5759},\r
+{0, 61308, 5760},\r
+{0, 61524, 5780},\r
+{0, 61754, 5773},\r
+{0, 61506, 5766},\r
+{0, 61086, 5773},\r
+{0, 61049, 5770},\r
+{0, 61115, 5770},\r
+{0, 61247, 5781},\r
+{0, 61427, 5769},\r
+{0, 61613, 5773},\r
+{0, 61668, 5765},\r
+{0, 61806, 5766},\r
+{0, 62008, 5774},\r
+{0, 61886, 5763},\r
+{0, 61188, 5751},\r
+{0, 60639, 5748},\r
+{0, 60412, 5752},\r
+{0, 60316, 5757},\r
+{0, 60310, 5761},\r
+{0, 60356, 5763},\r
+{0, 60405, 5761},\r
+{0, 60464, 5760},\r
+{0, 60630, 5762},\r
+{0, 60863, 5763},\r
+{0, 60954, 5765},\r
+{0, 60572, 5751},\r
+{0, 60416, 5757},\r
+{0, 60448, 5754},\r
+{0, 60505, 5759},\r
+{0, 60713, 5773},\r
+{0, 60769, 5766},\r
+{0, 60714, 5757},\r
+{0, 60657, 5755},\r
+{0, 60591, 5760},\r
+{0, 60567, 5755},\r
+{0, 60112, 5743},\r
+{0, 59439, 5753},\r
+{0, 59128, 5731},\r
+{0, 59000, 5746},\r
+{0, 59138, 5739},\r
+{0, 59421, 5744},\r
+{0, 59689, 5752},\r
+{0, 60117, 5751},\r
+{0, 60761, 5757},\r
+{0, 61771, 5789},\r
+{0, 62517, 5791},\r
+{0, 62664, 5798},\r
+{0, 62968, 5801},\r
+{0, 63303, 5791},\r
+{0, 63803, 5800},\r
+{0, 64494, 5805},\r
+{0, 65280, 5821},\r
+{0, 66256, 5819},\r
+{0, 67130, 5848},\r
+{0, 67923, 5853},\r
+{0, 68576, 5847},\r
+{0, 68487, 5828},\r
+{0, 67761, 5822},\r
+{0, 67183, 5810},\r
+{0, 66736, 5800},\r
+{0, 66396, 5800},\r
+{0, 66196, 5800},\r
+{0, 66150, 5812},\r
+{0, 66140, 5808},\r
+{0, 66223, 5807},\r
+{0, 66268, 5807},\r
+{0, 66370, 5801},\r
+{0, 65916, 5803},\r
+{0, 65289, 5797},\r
+{0, 64821, 5792},\r
+{0, 64674, 5784},\r
+{0, 64593, 5783},\r
+{0, 64812, 5790},\r
+{0, 65189, 5802},\r
+{0, 65670, 5820},\r
+{0, 66247, 5823},\r
+{0, 66900, 5832},\r
+{0, 67635, 5835},\r
+{0, 67749, 5830},\r
+{0, 67574, 5832},\r
+{0, 67596, 5835},\r
+{0, 67845, 5853},\r
+{0, 68130, 5834},\r
+{0, 68102, 5839},\r
+{0, 67864, 5832},\r
+{0, 67565, 5817},\r
+{0, 67381, 5813},\r
+{0, 67659, 5813},\r
+{0, 67756, 5819},\r
+{0, 67225, 5809},\r
+{0, 66788, 5813},\r
+{0, 66727, 5810},\r
+{0, 66886, 5812},\r
+{0, 67216, 5828},\r
+{0, 67493, 5832},\r
+{0, 67616, 5831},\r
+{0, 67729, 5828},\r
+{0, 67878, 5821},\r
+{0, 68146, 5828},\r
+{0, 68091, 5833},\r
+{0, 67867, 5838},\r
+{0, 68003, 5833},\r
+{0, 68079, 5834},\r
+{0, 67937, 5828},\r
+{0, 67850, 5834},\r
+{0, 67800, 5833},\r
+{0, 67676, 5819},\r
+{0, 67331, 5828},\r
+{0, 66976, 5818},\r
+{0, 66549, 5813},\r
+{0, 65528, 5792},\r
+{0, 64550, 5784},\r
+{0, 63974, 5792},\r
+{0, 63567, 5775},\r
+{0, 63210, 5783},\r
+{0, 63037, 5785},\r
+{0, 63024, 5771},\r
+{0, 62869, 5789},\r
+{0, 62621, 5779},\r
+{0, 62435, 5776},\r
+{0, 62339, 5775},\r
+{0, 61775, 5769},\r
+{0, 61353, 5765},\r
+{0, 61326, 5760},\r
+{0, 61299, 5772},\r
+{0, 61406, 5767},\r
+{0, 61483, 5767},\r
+{0, 61587, 5776},\r
+{0, 61659, 5764},\r
+{0, 61663, 5775},\r
+{0, 61582, 5779},\r
+{0, 61102, 5767},\r
+{0, 60299, 5770},\r
+{0, 59889, 5750},\r
+{0, 59580, 5755},\r
+{0, 59491, 5756},\r
+{0, 59531, 5760},\r
+{0, 59514, 5756},\r
+{0, 59516, 5766},\r
+{0, 59580, 5769},\r
+{0, 59621, 5763},\r
+{0, 59592, 5770},\r
+{0, 59062, 5761},\r
+{0, 58561, 5749},\r
+{0, 58431, 5756},\r
+{0, 58411, 5751},\r
+{0, 58573, 5750},\r
+{0, 58764, 5749},\r
+{0, 58822, 5753},\r
+{0, 58958, 5756},\r
+{0, 58950, 5749},\r
+{0, 58893, 5751},\r
+{0, 58397, 5752},\r
+{0, 57606, 5737},\r
+{0, 57424, 5743},\r
+{0, 57486, 5744},\r
+{0, 57633, 5747},\r
+{0, 57848, 5741},\r
+{0, 58040, 5749},\r
+{0, 58217, 5757},\r
+{0, 58392, 5764},\r
+{0, 58635, 5751},\r
+{0, 58852, 5764},\r
+{0, 58597, 5767},\r
+{0, 58185, 5757},\r
+{0, 58137, 5756},\r
+{0, 58330, 5762},\r
+{0, 58589, 5770},\r
+{0, 58916, 5764},\r
+{0, 59214, 5765},\r
+{0, 59515, 5769},\r
+{0, 59834, 5779},\r
+{0, 60227, 5769},\r
+{0, 60469, 5777},\r
+{0, 59967, 5764},\r
+{0, 59520, 5759},\r
+{0, 59356, 5752},\r
+{0, 59217, 5761},\r
+{0, 59071, 5750},\r
+{0, 59034, 5751},\r
+{0, 59003, 5744},\r
+{0, 58991, 5752},\r
+{0, 58937, 5750},\r
+{0, 58924, 5748},\r
+{0, 58454, 5738},\r
+{0, 58087, 5738},\r
+{0, 58107, 5734},\r
+{0, 58230, 5745},\r
+{0, 58340, 5740},\r
+{0, 58388, 5737},\r
+{0, 58381, 5745},\r
+{0, 58354, 5728},\r
+{0, 58366, 5737},\r
+{0, 58590, 5741},\r
+{0, 58713, 5734},\r
+{0, 58377, 5737},\r
+{0, 58177, 5748},\r
+{0, 58197, 5749},\r
+{0, 58062, 5748},\r
+{0, 57978, 5741},\r
+{0, 57882, 5752},\r
+{0, 57678, 5731},\r
+{0, 57587, 5724},\r
+{0, 57539, 5726},\r
+{0, 57666, 5733},\r
+{0, 57404, 5729},\r
+{0, 56725, 5725},\r
+{0, 56332, 5715},\r
+{0, 56194, 5713},\r
+{0, 56214, 5723},\r
+{0, 56322, 5732},\r
+{0, 56364, 5712},\r
+{0, 56641, 5722},\r
+{0, 57064, 5729},\r
+{0, 57575, 5739},\r
+{0, 57817, 5747},\r
+{0, 57687, 5748},\r
+{0, 57893, 5775},\r
+{0, 58419, 5768},\r
+{0, 58955, 5779},\r
+{0, 59378, 5779},\r
+{0, 59833, 5787},\r
+{0, 60090, 5779},\r
+{0, 60183, 5782},\r
+{0, 60170, 5779},\r
+{0, 60060, 5773},\r
+{0, 59675, 5754},\r
+{0, 59371, 5761},\r
+{0, 59183, 5759},\r
+{0, 59076, 5766},\r
+{0, 59091, 5759},\r
+{0, 59158, 5763},\r
+{0, 59216, 5767},\r
+{0, 59323, 5768},\r
+{0, 59399, 5748},\r
+{0, 59512, 5755},\r
+{0, 59429, 5746},\r
+{0, 59066, 5752},\r
+{0, 58959, 5743},\r
+{0, 59186, 5754},\r
+{0, 59638, 5765},\r
+{0, 60181, 5784},\r
+{0, 60936, 5800},\r
+{0, 61657, 5809},\r
+{0, 62331, 5817},\r
+{0, 62850, 5829},\r
+{0, 63079, 5819},\r
+{0, 62691, 5803},\r
+{0, 62403, 5797},\r
+{0, 62247, 5786},\r
+{0, 62108, 5783},\r
+{0, 61555, 5762},\r
+{0, 61147, 5759},\r
+{0, 61019, 5762},\r
+{0, 61070, 5766},\r
+{0, 61315, 5766},\r
+{0, 61772, 5788},\r
+{0, 61988, 5776},\r
+{0, 62173, 5791},\r
+{0, 62663, 5803},\r
+{0, 63542, 5812},\r
+{0, 64690, 5832},\r
+{0, 66229, 5843},\r
+{0, 67894, 5855},\r
+{0, 69538, 5866},\r
+{0, 71053, 5877},\r
+{0, 72442, 5889},\r
+{0, 73620, 5884},\r
+{0, 74230, 5880},\r
+{0, 74560, 5873},\r
+{0, 74737, 5875},\r
+{0, 74832, 5874},\r
+{0, 74956, 5873},\r
+{0, 74951, 5864},\r
+{0, 74822, 5857},\r
+{0, 74693, 5866},\r
+{0, 74461, 5861},\r
+{0, 74480, 5857},\r
+{0, 74253, 5856},\r
+{0, 74028, 5859},\r
+{0, 74087, 5863},\r
+{0, 74329, 5869},\r
+{0, 74604, 5869},\r
+{0, 74985, 5872},\r
+{0, 75312, 5874},\r
+{0, 75745, 5877},\r
+{0, 76194, 5893},\r
+{0, 76682, 5889},\r
+{0, 76737, 5877},\r
+{0, 76508, 5883},\r
+{0, 76662, 5895},\r
+{0, 76768, 5873},\r
+{0, 76785, 5878},\r
+{0, 76680, 5875},\r
+{0, 76524, 5863},\r
+{0, 76236, 5869},\r
+{0, 75933, 5864},\r
+{0, 75706, 5864},\r
+{0, 75246, 5848},\r
+{0, 74109, 5834},\r
+{0, 73140, 5829},\r
+{0, 72645, 5818},\r
+{0, 72371, 5817},\r
+{0, 72475, 5824},\r
+{0, 72654, 5823},\r
+{0, 72765, 5830},\r
+{0, 72691, 5835},\r
+{0, 72530, 5832},\r
+{0, 72256, 5837},\r
+{0, 71277, 5825},\r
+{0, 70128, 5815},\r
+{0, 69529, 5806},\r
+{0, 69262, 5810},\r
+{0, 69252, 5816},\r
+{0, 69429, 5813},\r
+{0, 69521, 5814},\r
+{0, 69398, 5808},\r
+{0, 69071, 5809},\r
+{0, 68771, 5810},\r
+{0, 68021, 5803},\r
+{0, 66642, 5792},\r
+{0, 65608, 5774},\r
+{0, 65018, 5777},\r
+{0, 64687, 5772},\r
+{0, 64674, 5762},\r
+{0, 65014, 5768},\r
+{0, 65759, 5787},\r
+{0, 66432, 5799},\r
+{0, 66646, 5787},\r
+{0, 67223, 5804},\r
+{0, 67929, 5815},\r
+{0, 68566, 5820},\r
+{0, 69257, 5830},\r
+{0, 69328, 5843},\r
+{0, 68808, 5829},\r
+{0, 68356, 5832},\r
+{0, 67702, 5829},\r
+{0, 67236, 5818},\r
+{0, 67059, 5822},\r
+{0, 67074, 5812},\r
+{0, 66592, 5811},\r
+{0, 66123, 5826},\r
+{0, 65668, 5814},\r
+{0, 65264, 5805},\r
+{0, 64861, 5811},\r
+{0, 64532, 5808},\r
+{0, 64333, 5818},\r
+{0, 64260, 5824},\r
+{0, 64172, 5831},\r
+{0, 64121, 5830},\r
+{0, 63886, 5824},\r
+{0, 63395, 5839},\r
+{0, 63283, 5831},\r
+{0, 63627, 5836},\r
+{0, 64740, 5851},\r
+{0, 66508, 5878},\r
+{0, 68738, 5908},\r
+{0, 70560, 5895},\r
+{0, 71276, 5922},\r
+{0, 72054, 5922},\r
+{0, 72124, 5912},\r
+{0, 71485, 5917},\r
+{0, 71691, 5902},\r
+{0, 70895, 5857},\r
+{0, 70368, 5851},\r
+{0, 70082, 5845},\r
+{0, 69925, 5843},\r
+{0, 69905, 5847},\r
+{0, 69942, 5852},\r
+{0, 70040, 5841},\r
+{0, 69994, 5837},\r
+{0, 69472, 5839},\r
+{0, 69057, 5846},\r
+{0, 68970, 5842},\r
+{0, 69231, 5851},\r
+{0, 69660, 5851},\r
+{0, 70155, 5869},\r
+{0, 70734, 5875},\r
+{0, 71378, 5881},\r
+{0, 72055, 5891},\r
+{0, 72588, 5879},\r
+{0, 72942, 5898},\r
+{0, 72781, 5882},\r
+{0, 73013, 5897},\r
+{0, 73351, 5887},\r
+{0, 73884, 5902},\r
+{0, 74289, 5901},\r
+{0, 74571, 5887},\r
+{0, 74683, 5891},\r
+{0, 74872, 5906},\r
+{0, 75047, 5900},\r
+{0, 74844, 5905},\r
+{0, 74167, 5891},\r
+{0, 73993, 5890},\r
+{0, 74094, 5896},\r
+{0, 74312, 5888},\r
+{0, 74558, 5894},\r
+{0, 74754, 5885},\r
+{0, 74920, 5899},\r
+{0, 75189, 5895},\r
+{0, 75489, 5888},\r
+{0, 75178, 5893},\r
+{0, 74596, 5882},\r
+{0, 74433, 5879},\r
+{0, 74408, 5886},\r
+{0, 74345, 5884},\r
+{0, 74341, 5877},\r
+{0, 74239, 5877},\r
+{0, 74135, 5869},\r
+{0, 74031, 5869},\r
+{0, 73905, 5879},\r
+{0, 73164, 5860},\r
+{0, 72268, 5851},\r
+{0, 71838, 5867},\r
+{0, 71706, 5854},\r
+{0, 71727, 5861},\r
+{0, 71907, 5857},\r
+{0, 72125, 5872},\r
+{0, 72408, 5868},\r
+{0, 72895, 5877},\r
+{0, 73338, 5881},\r
+{0, 73321, 5878},\r
+{0, 72919, 5878},\r
+{0, 72972, 5873},\r
+{0, 73083, 5870},\r
+{0, 73309, 5878},\r
+{0, 73530, 5869},\r
+{0, 73618, 5872},\r
+{0, 73596, 5885},\r
+{0, 73587, 5864},\r
+{0, 73547, 5868},\r
+{0, 73019, 5858},\r
+{0, 72151, 5853},\r
+{0, 71781, 5846},\r
+{0, 71687, 5852},\r
+{0, 71796, 5853},\r
+{0, 71949, 5857},\r
+{0, 72062, 5857},\r
+{0, 72167, 5856},\r
+{0, 72338, 5863},\r
+{0, 72655, 5873},\r
+{0, 72417, 5856},\r
+{0, 71948, 5861},\r
+{0, 71695, 5852},\r
+{0, 71640, 5850},\r
+{0, 71668, 5853},\r
+{0, 71761, 5849},\r
+{0, 71731, 5851},\r
+{0, 71692, 5849},\r
+{0, 71601, 5835},\r
+{0, 71472, 5843},\r
+{0, 70814, 5831},\r
+{0, 69756, 5818},\r
+{0, 69035, 5816},\r
+{0, 68569, 5805},\r
+{0, 68414, 5808},\r
+{0, 68345, 5801},\r
+{0, 68178, 5804},\r
+{0, 67999, 5794},\r
+{0, 67861, 5810},\r
+{0, 67663, 5807},\r
+{0, 66724, 5808},\r
+{0, 65861, 5795},\r
+{0, 65417, 5801},\r
+{0, 65260, 5785},\r
+{0, 65332, 5793},\r
+{0, 65283, 5795},\r
+{0, 64988, 5792},\r
+{0, 64675, 5786},\r
+{0, 64347, 5788},\r
+{0, 63951, 5783},\r
+{0, 62852, 5765},\r
+{0, 61867, 5770},\r
+{0, 61368, 5769},\r
+{0, 61239, 5778},\r
+{0, 61486, 5767},\r
+{0, 61988, 5774},\r
+{0, 62632, 5799},\r
+{0, 63408, 5796},\r
+{0, 64151, 5805},\r
+{0, 64517, 5813},\r
+{0, 63974, 5807},\r
+{0, 63699, 5805},\r
+{0, 63722, 5807},\r
+{0, 63989, 5806},\r
+{0, 64370, 5819},\r
+{0, 64688, 5805},\r
+{0, 64879, 5813},\r
+{0, 65024, 5816},\r
+{0, 65176, 5815},\r
+{0, 65004, 5808},\r
+{0, 64410, 5809},\r
+{0, 64106, 5817},\r
+{0, 63971, 5800},\r
+{0, 63992, 5799},\r
+{0, 64194, 5820},\r
+{0, 64332, 5812},\r
+{0, 64431, 5805},\r
+{0, 64604, 5800},\r
+{0, 64817, 5813},\r
+{0, 64292, 5806},\r
+{0, 63632, 5795},\r
+{0, 63383, 5804},\r
+{0, 63220, 5796},\r
+{0, 63175, 5793},\r
+{0, 63247, 5796},\r
+{0, 63233, 5804},\r
+{0, 63277, 5804},\r
+{0, 63287, 5797},\r
+{0, 63344, 5799},\r
+{0, 62868, 5787},\r
+{0, 62286, 5785},\r
+{0, 62076, 5784},\r
+{0, 62090, 5775},\r
+{0, 62301, 5781},\r
+{0, 62520, 5784},\r
+{0, 62761, 5789},\r
+{0, 62998, 5788},\r
+{0, 63236, 5788},\r
+{0, 63448, 5790},\r
+{0, 62970, 5788},\r
+{0, 62468, 5779},\r
+{0, 62254, 5775},\r
+{0, 62212, 5777},\r
+{0, 62281, 5775},\r
+{0, 62401, 5772},\r
+{0, 62447, 5780},\r
+{0, 62508, 5773},\r
+{0, 62578, 5768},\r
+{0, 62634, 5771},\r
+{0, 62224, 5761},\r
+{0, 61786, 5764},\r
+{0, 61571, 5758},\r
+{0, 61532, 5764},\r
+{0, 61525, 5764},\r
+{0, 61630, 5759},\r
+{0, 61746, 5766},\r
+{0, 61978, 5764},\r
+{0, 62241, 5771},\r
+{0, 62393, 5766},\r
+{0, 62041, 5760},\r
+{0, 61717, 5759},\r
+{0, 61744, 5750},\r
+{0, 61798, 5768},\r
+{0, 61958, 5764},\r
+{0, 62164, 5765},\r
+{0, 62281, 5764},\r
+{0, 62350, 5759},\r
+{0, 62417, 5768},\r
+{0, 62321, 5760},\r
+{0, 61874, 5756},\r
+{0, 61570, 5763},\r
+{0, 61516, 5769},\r
+{0, 61562, 5749},\r
+{0, 61738, 5742},\r
+{0, 61918, 5758},\r
+{0, 62105, 5751},\r
+{0, 62273, 5760},\r
+{0, 62529, 5749},\r
+{0, 62418, 5747},\r
+{0, 62035, 5750},\r
+{0, 61840, 5746},\r
+{0, 61803, 5759},\r
+{0, 61857, 5757},\r
+{0, 62023, 5745},\r
+{0, 62152, 5746},\r
+{0, 62293, 5747},\r
+{0, 62456, 5754},\r
+{0, 62602, 5756},\r
+{0, 62479, 5760},\r
+{0, 62059, 5758},\r
+{0, 61748, 5763},\r
+{0, 61755, 5754},\r
+{0, 62085, 5762},\r
+{0, 62519, 5778},\r
+{0, 63003, 5785},\r
+{0, 63486, 5788},\r
+{0, 63995, 5786},\r
+{0, 64508, 5784},\r
+{0, 64561, 5794},\r
+{0, 64397, 5786},\r
+{0, 64457, 5788},\r
+{0, 64575, 5796},\r
+{0, 64673, 5792},\r
+{0, 64803, 5785},\r
+{0, 64980, 5778},\r
+{0, 65071, 5783},\r
+{0, 65174, 5780},\r
+{0, 65294, 5781},\r
+{0, 65023, 5777},\r
+{0, 64700, 5781},\r
+{0, 64722, 5794},\r
+{0, 64954, 5779},\r
+{0, 65308, 5796},\r
+{0, 65654, 5803},\r
+{0, 66008, 5808},\r
+{0, 66386, 5811},\r
+{0, 66740, 5810},\r
+{0, 67062, 5798},\r
+{0, 66763, 5791},\r
+{0, 66183, 5779},\r
+{0, 65919, 5783},\r
+{0, 65646, 5777},\r
+{0, 65664, 5776},\r
+{0, 65711, 5785},\r
+{0, 65683, 5773},\r
+{0, 65671, 5785},\r
+{0, 65738, 5774},\r
+{0, 65819, 5787},\r
+{0, 65451, 5779},\r
+{0, 65118, 5771},\r
+{0, 65027, 5774},\r
+{0, 65271, 5782},\r
+{0, 65605, 5789},\r
+{0, 65948, 5793},\r
+{0, 66186, 5783},\r
+{0, 66328, 5788},\r
+{0, 66427, 5789},\r
+{0, 66466, 5792},\r
+{0, 65897, 5776},\r
+{0, 65270, 5771},\r
+{0, 64912, 5764},\r
+{0, 64731, 5766},\r
+{0, 64702, 5767},\r
+{0, 64758, 5761},\r
+{0, 64787, 5759},\r
+{0, 64938, 5753},\r
+{0, 65112, 5759},\r
+{0, 65230, 5762},\r
+{0, 65048, 5765},\r
+{0, 64882, 5767},\r
+{0, 64873, 5778},\r
+{0, 65103, 5769},\r
+{0, 65276, 5784},\r
+{0, 65464, 5784},\r
+{0, 65575, 5772},\r
+{0, 65649, 5774},\r
+{0, 65761, 5780},\r
+{0, 65777, 5775},\r
+{0, 65414, 5770},\r
+{0, 65099, 5769},\r
+{0, 65000, 5764},\r
+{0, 65025, 5770},\r
+{0, 65040, 5759},\r
+{0, 65073, 5765},\r
+{0, 65220, 5765},\r
+{0, 65406, 5760},\r
+{0, 65631, 5766},\r
+{0, 65865, 5770},\r
+{0, 65764, 5769},\r
+{0, 65743, 5777},\r
+{0, 65831, 5778},\r
+{0, 65952, 5775},\r
+{0, 66226, 5781},\r
+{0, 66401, 5784},\r
+{0, 66447, 5791},\r
+{0, 66398, 5780},\r
+{0, 66371, 5779},\r
+{0, 66423, 5780},\r
+{0, 66029, 5771},\r
+{0, 65662, 5765},\r
+{0, 65568, 5775},\r
+{0, 65594, 5771},\r
+{0, 65686, 5774},\r
+{0, 65890, 5776},\r
+{0, 66024, 5787},\r
+{0, 66182, 5775},\r
+{0, 66399, 5779},\r
+{0, 66569, 5771},\r
+{0, 66266, 5783},\r
+{0, 66114, 5786},\r
+{0, 66074, 5772},\r
+{0, 66060, 5784},\r
+{0, 66115, 5785},\r
+{0, 66105, 5783},\r
+{0, 66012, 5780},\r
+{0, 65946, 5782},\r
+{0, 65920, 5778},\r
+{0, 65734, 5790},\r
+{0, 65300, 5771},\r
+{0, 65110, 5768},\r
+{0, 65090, 5767},\r
+{0, 65144, 5777},\r
+{0, 65246, 5773},\r
+{0, 65414, 5770},\r
+{0, 65557, 5781},\r
+{0, 65740, 5768},\r
+{0, 65934, 5782},\r
+{0, 65981, 5768},\r
+{0, 65614, 5770},\r
+{0, 65409, 5768},\r
+{0, 65337, 5783},\r
+{0, 65317, 5779},\r
+{0, 65347, 5775},\r
+{0, 65401, 5779},\r
+{0, 65399, 5776},\r
+{0, 65420, 5777},\r
+{0, 65465, 5782},\r
+{0, 65206, 5776},\r
+{0, 64708, 5765},\r
+{0, 64445, 5773},\r
+{0, 64390, 5759},\r
+{0, 64474, 5761},\r
+{0, 64616, 5760},\r
+{0, 64708, 5766},\r
+{0, 64787, 5768},\r
+{0, 64904, 5764},\r
+{0, 65010, 5760},\r
+{0, 64665, 5743},\r
+{0, 64290, 5753},\r
+{0, 64118, 5758},\r
+{0, 64036, 5746},\r
+{0, 64071, 5753},\r
+{0, 64079, 5771},\r
+{0, 64008, 5758},\r
+{0, 63954, 5757},\r
+{0, 63947, 5762},\r
+{0, 63745, 5769},\r
+{0, 63147, 5749},\r
+{0, 62753, 5751},\r
+{0, 62511, 5745},\r
+{0, 62522, 5743},\r
+{0, 62658, 5738},\r
+{0, 62850, 5751},\r
+{0, 63096, 5758},\r
+{0, 63219, 5764},\r
+{0, 63397, 5760},\r
+{0, 63139, 5750},\r
+{0, 62637, 5742},\r
+{0, 62332, 5758},\r
+{0, 62161, 5737},\r
+{0, 62134, 5744},\r
+{0, 62162, 5727},\r
+{0, 62146, 5740},\r
+{0, 62211, 5742},\r
+{0, 62268, 5741},\r
+{0, 62296, 5735},\r
+{0, 61821, 5727},\r
+{0, 61329, 5731},\r
+{0, 61131, 5733},\r
+{0, 61167, 5723},\r
+{0, 61340, 5729},\r
+{0, 61444, 5732},\r
+{0, 61536, 5734},\r
+{0, 61631, 5747},\r
+{0, 61716, 5743},\r
+{0, 61505, 5735},\r
+{0, 60787, 5722},\r
+{0, 60345, 5731},\r
+{0, 60181, 5741},\r
+{0, 60248, 5729},\r
+{0, 60367, 5737},\r
+{0, 60461, 5731},\r
+{0, 60632, 5730},\r
+{0, 60762, 5744},\r
+{0, 60915, 5718},\r
+{0, 60493, 5732},\r
+{0, 60104, 5731},\r
+{0, 59990, 5723},\r
+{0, 60105, 5727},\r
+{0, 60318, 5729},\r
+{0, 60557, 5738},\r
+{0, 60774, 5735},\r
+{0, 60965, 5726},\r
+{0, 61098, 5739},\r
+{0, 60909, 5738},\r
+{0, 60327, 5738},\r
+{0, 59928, 5732},\r
+{0, 59877, 5738},\r
+{0, 59907, 5723},\r
+{0, 60155, 5737},\r
+{0, 60278, 5744},\r
+{0, 60408, 5733},\r
+{0, 60642, 5738},\r
+{0, 60747, 5738},\r
+{0, 60382, 5735},\r
+{0, 60107, 5730},\r
+{0, 60189, 5733},\r
+{0, 60398, 5731},\r
+{0, 60675, 5735},\r
+{0, 60925, 5743},\r
+{0, 61206, 5762},\r
+{0, 61511, 5754},\r
+{0, 61864, 5773},\r
+{0, 61935, 5746},\r
+{0, 61608, 5752},\r
+{0, 61605, 5754},\r
+{0, 61722, 5757},\r
+{0, 61819, 5756},\r
+{0, 61935, 5754},\r
+{0, 62005, 5755},\r
+{0, 62119, 5737},\r
+{0, 62356, 5755},\r
+{0, 62664, 5758},\r
+{0, 62743, 5758},\r
+{0, 62874, 5759},\r
+{0, 63192, 5772},\r
+{0, 63557, 5776},\r
+{0, 63993, 5791},\r
+{0, 64457, 5788},\r
+{0, 64667, 5808},\r
+{0, 64672, 5779},\r
+{0, 64583, 5778},\r
+{0, 64148, 5768},\r
+{0, 63687, 5762},\r
+{0, 63436, 5761},\r
+{0, 63363, 5751},\r
+{0, 63396, 5768},\r
+{0, 63591, 5753},\r
+{0, 63767, 5756},\r
+{0, 63919, 5763},\r
+{0, 64148, 5773},\r
+{0, 64423, 5776},\r
+{0, 64354, 5782},\r
+{0, 64326, 5774},\r
+{0, 64347, 5775},\r
+{0, 64417, 5781},\r
+{0, 64483, 5770},\r
+{0, 64511, 5768},\r
+{0, 64398, 5758},\r
+{0, 64234, 5750},\r
+{0, 64125, 5749},\r
+{0, 63702, 5748},\r
+{0, 63276, 5737},\r
+{0, 63115, 5742},\r
+{0, 63116, 5736},\r
+{0, 63333, 5760},\r
+{0, 63639, 5754},\r
+{0, 63971, 5768},\r
+{0, 64317, 5771},\r
+{0, 64662, 5779},\r
+{0, 64835, 5766},\r
+{0, 64640, 5774},\r
+{0, 64461, 5762},\r
+{0, 64329, 5772},\r
+{0, 64323, 5765},\r
+{0, 64358, 5771},\r
+{0, 64365, 5752},\r
+{0, 64315, 5762},\r
+{0, 64374, 5760},\r
+{0, 64409, 5775},\r
+{0, 64065, 5755},\r
+{0, 63710, 5764},\r
+{0, 63622, 5751},\r
+{0, 63622, 5763},\r
+{0, 63793, 5758},\r
+{0, 64031, 5763},\r
+{0, 64245, 5764},\r
+{0, 64488, 5756},\r
+{0, 64749, 5766},\r
+{0, 64617, 5757},\r
+{0, 64352, 5759},\r
+{0, 64136, 5758},\r
+{0, 64014, 5749},\r
+{0, 64040, 5754},\r
+{0, 64046, 5756},\r
+{0, 64095, 5763},\r
+{0, 64098, 5755},\r
+{0, 64138, 5759},\r
+{0, 63955, 5753},\r
+{0, 63361, 5760},\r
+{0, 63008, 5748},\r
+{0, 62864, 5747},\r
+{0, 62913, 5756},\r
+{0, 63108, 5748},\r
+{0, 63239, 5748},\r
+{0, 63376, 5747},\r
+{0, 63590, 5752},\r
+{0, 63659, 5756},\r
+{0, 63189, 5736},\r
+{0, 62855, 5750},\r
+{0, 62591, 5741},\r
+{0, 62464, 5747},\r
+{0, 62395, 5736},\r
+{0, 62361, 5739},\r
+{0, 62420, 5746},\r
+{0, 62539, 5740},\r
+{0, 62640, 5733},\r
+{0, 62287, 5744},\r
+{0, 61802, 5721},\r
+{0, 61712, 5732},\r
+{0, 61717, 5734},\r
+{0, 61936, 5731},\r
+{0, 62140, 5733},\r
+{0, 62389, 5746},\r
+{0, 62592, 5751},\r
+{0, 62793, 5754},\r
+{0, 62674, 5743},\r
+{0, 62331, 5746},\r
+{0, 62134, 5745},\r
+{0, 62047, 5740},\r
+{0, 62065, 5749},\r
+{0, 62175, 5738},\r
+{0, 62296, 5762},\r
+{0, 62479, 5745},\r
+{0, 62641, 5745},\r
+{0, 62776, 5754},\r
+{0, 62507, 5738},\r
+{0, 62360, 5742},\r
+{0, 62422, 5746},\r
+{0, 62578, 5742},\r
+{0, 62801, 5740},\r
+{0, 62981, 5744},\r
+{0, 63075, 5748},\r
+{0, 63254, 5757},\r
+{0, 63363, 5748},\r
+{0, 63030, 5745},\r
+{0, 62689, 5741},\r
+{0, 62470, 5740},\r
+{0, 62370, 5744},\r
+{0, 62403, 5750},\r
+{0, 62483, 5742},\r
+{0, 62575, 5738},\r
+{0, 62695, 5745},\r
+{0, 63069, 5756},\r
+{0, 63296, 5751},\r
+{0, 63314, 5749},\r
+{0, 63217, 5758},\r
+{0, 63309, 5760},\r
+{0, 63452, 5758},\r
+{0, 63635, 5744},\r
+{0, 63826, 5756},\r
+{0, 63935, 5759},\r
+{0, 63999, 5757},\r
+{0, 63655, 5750},\r
+{0, 63351, 5755},\r
+{0, 63208, 5745},\r
+{0, 63206, 5748},\r
+{0, 63277, 5749},\r
+{0, 63469, 5753},\r
+{0, 63729, 5755},\r
+{0, 63966, 5764},\r
+{0, 64137, 5752},\r
+{0, 64112, 5757},\r
+{0, 63987, 5759},\r
+{0, 63732, 5781},\r
+{0, 63601, 5766},\r
+{0, 63678, 5769},\r
+{0, 63797, 5772},\r
+{0, 63884, 5769},\r
+{0, 63884, 5768},\r
+{0, 63918, 5761},\r
+{0, 63836, 5765},\r
+{0, 63581, 5762},\r
+{0, 63400, 5760},\r
+{0, 63287, 5760},\r
+{0, 63299, 5762},\r
+{0, 63377, 5759},\r
+{0, 63602, 5756},\r
+{0, 63770, 5753},\r
+{0, 64167, 5770},\r
+{0, 64532, 5774},\r
+{0, 64516, 5779},\r
+{0, 64481, 5769},\r
+{0, 64437, 5773},\r
+{0, 64521, 5778},\r
+{0, 64509, 5767},\r
+{0, 64520, 5778},\r
+{0, 64447, 5777},\r
+{0, 64397, 5770},\r
+{0, 64370, 5765},\r
+{0, 64160, 5768},\r
+{0, 63821, 5759},\r
+{0, 63573, 5761},\r
+{0, 63482, 5763},\r
+{0, 63505, 5757},\r
+{0, 63565, 5761},\r
+{0, 63695, 5755},\r
+{0, 63855, 5770},\r
+{0, 63950, 5762},\r
+{0, 63716, 5763},\r
+{0, 63219, 5762},\r
+{0, 62846, 5748},\r
+{0, 62658, 5752},\r
+{0, 62592, 5761},\r
+{0, 62540, 5735},\r
+{0, 62563, 5750},\r
+{0, 62569, 5757},\r
+{0, 62628, 5747},\r
+{0, 62420, 5743},\r
+{0, 61910, 5741},\r
+{0, 61690, 5742},\r
+{0, 61672, 5757},\r
+{0, 61870, 5747},\r
+{0, 62132, 5740},\r
+{0, 62472, 5755},\r
+{0, 62911, 5765},\r
+{0, 63297, 5773},\r
+{0, 63437, 5765},\r
+{0, 63107, 5773},\r
+{0, 63006, 5772},\r
+{0, 62997, 5769},\r
+{0, 62962, 5762},\r
+{0, 63064, 5765},\r
+{0, 63159, 5763},\r
+{0, 63242, 5770},\r
+{0, 63358, 5761},\r
+{0, 63449, 5761},\r
+{0, 63321, 5766},\r
+{0, 63150, 5761},\r
+{0, 63133, 5762},\r
+{0, 63367, 5782},\r
+{0, 63649, 5759},\r
+{0, 64041, 5781},\r
+{0, 64376, 5779},\r
+{0, 64717, 5792},\r
+{0, 65015, 5789},\r
+{0, 64825, 5787},\r
+{0, 64526, 5781},\r
+{0, 64226, 5784},\r
+{0, 64006, 5777},\r
+{0, 63941, 5784},\r
+{0, 64014, 5776},\r
+{0, 64072, 5789},\r
+{0, 64077, 5770},\r
+{0, 64241, 5770},\r
+{0, 64040, 5772},\r
+{0, 63628, 5763},\r
+{0, 63414, 5762},\r
+{0, 63471, 5768},\r
+{0, 63684, 5773},\r
+{0, 63888, 5776},\r
+{0, 64024, 5770},\r
+{0, 64124, 5775},\r
+{0, 64260, 5777},\r
+{0, 64026, 5763},\r
+{0, 63414, 5776},\r
+{0, 62978, 5760},\r
+{0, 62713, 5760},\r
+{0, 62586, 5756},\r
+{0, 62588, 5743},\r
+{0, 62620, 5759},\r
+{0, 62765, 5748},\r
+{0, 62946, 5760},\r
+{0, 62902, 5754},\r
+{0, 62456, 5748},\r
+{0, 62211, 5749},\r
+{0, 62172, 5759},\r
+{0, 62189, 5746},\r
+{0, 62341, 5764},\r
+{0, 62470, 5762},\r
+{0, 62529, 5759},\r
+{0, 62579, 5764},\r
+{0, 62535, 5747},\r
+{0, 61983, 5739},\r
+{0, 61407, 5751},\r
+{0, 61151, 5747},\r
+{0, 61085, 5743},\r
+{0, 61183, 5736},\r
+{0, 61289, 5736},\r
+{0, 61472, 5737},\r
+{0, 61717, 5748},\r
+{0, 61983, 5754},\r
+{0, 61816, 5744},\r
+{0, 61361, 5754},\r
+{0, 61275, 5736},\r
+{0, 61235, 5741},\r
+{0, 61351, 5747},\r
+{0, 61462, 5755},\r
+{0, 61521, 5754},\r
+{0, 61551, 5747},\r
+{0, 61576, 5754},\r
+{0, 61585, 5764},\r
+{0, 61220, 5745},\r
+{0, 60991, 5743},\r
+{0, 61000, 5747},\r
+{0, 61196, 5740},\r
+{0, 61561, 5753},\r
+{0, 61866, 5754},\r
+{0, 62172, 5747},\r
+{0, 62484, 5759},\r
+{0, 62803, 5768},\r
+{0, 62628, 5752},\r
+{0, 62286, 5766},\r
+{0, 62272, 5762},\r
+{0, 62382, 5767},\r
+{0, 62551, 5763},\r
+{0, 62704, 5758},\r
+{0, 62756, 5755},\r
+{0, 62805, 5769},\r
+{0, 62874, 5762},\r
+{0, 62686, 5758},\r
+{0, 62017, 5756},\r
+{0, 61656, 5755},\r
+{0, 61481, 5747},\r
+{0, 61410, 5752},\r
+{0, 61404, 5751},\r
+{0, 61426, 5754},\r
+{0, 61636, 5756},\r
+{0, 61908, 5752},\r
+{0, 62211, 5760},\r
+{0, 62010, 5755},\r
+{0, 61685, 5756},\r
+{0, 61541, 5749},\r
+{0, 61511, 5746},\r
+{0, 61593, 5757},\r
+{0, 61610, 5760},\r
+{0, 61607, 5762},\r
+{0, 61511, 5753},\r
+{0, 61551, 5748},\r
+{0, 61497, 5747},\r
+{0, 61484, 5748},\r
+{0, 61526, 5750},\r
+{0, 61645, 5739},\r
+{0, 61786, 5751},\r
+{0, 62042, 5756},\r
+{0, 62390, 5757},\r
+{0, 62832, 5771},\r
+{0, 63289, 5769},\r
+{0, 63709, 5784},\r
+{0, 63647, 5782},\r
+{0, 63323, 5767},\r
+{0, 63181, 5771},\r
+{0, 63174, 5771},\r
+{0, 63162, 5763},\r
+{0, 63154, 5768},\r
+{0, 63011, 5762},\r
+{0, 63026, 5759},\r
+{0, 63142, 5753},\r
+{0, 62934, 5757},\r
+{0, 62515, 5760},\r
+{0, 62312, 5757},\r
+{0, 62297, 5754},\r
+{0, 62433, 5751},\r
+{0, 62682, 5754},\r
+{0, 62858, 5770},\r
+{0, 63028, 5755},\r
+{0, 63303, 5764},\r
+{0, 63398, 5755},\r
+{0, 62993, 5757},\r
+{0, 62608, 5753},\r
+{0, 62458, 5751},\r
+{0, 62346, 5743},\r
+{0, 62280, 5754},\r
+{0, 62242, 5763},\r
+{0, 62303, 5758},\r
+{0, 62358, 5765},\r
+{0, 62472, 5752},\r
+{0, 62424, 5752},\r
+{0, 62311, 5755},\r
+{0, 62270, 5752},\r
+{0, 62418, 5742},\r
+{0, 62654, 5760},\r
+{0, 62962, 5759},\r
+{0, 63310, 5777},\r
+{0, 63590, 5766},\r
+{0, 63899, 5772},\r
+{0, 64095, 5770},\r
+{0, 63684, 5757},\r
+{0, 63343, 5759},\r
+{0, 63230, 5759},\r
+{0, 63190, 5761},\r
+{0, 63277, 5762},\r
+{0, 63404, 5762},\r
+{0, 63526, 5775},\r
+{0, 63639, 5768},\r
+{0, 63752, 5771},\r
+{0, 63594, 5767},\r
+{0, 63147, 5760},\r
+{0, 62958, 5761},\r
+{0, 63029, 5754},\r
+{0, 63132, 5751},\r
+{0, 63350, 5763},\r
+{0, 63580, 5762},\r
+{0, 63728, 5762},\r
+{0, 63925, 5768},\r
+{0, 63941, 5769},\r
+{0, 63374, 5768},\r
+{0, 63028, 5750},\r
+{0, 62776, 5750},\r
+{0, 62640, 5756},\r
+{0, 62609, 5752},\r
+{0, 62681, 5755},\r
+{0, 62738, 5758},\r
+{0, 62820, 5763},\r
+{0, 62920, 5766},\r
+{0, 62639, 5759},\r
+{0, 62154, 5747},\r
+{0, 61864, 5743},\r
+{0, 61888, 5754},\r
+{0, 61960, 5753},\r
+{0, 62239, 5756},\r
+{0, 62466, 5758},\r
+{0, 62673, 5744},\r
+{0, 62900, 5764},\r
+{0, 62949, 5756},\r
+{0, 62397, 5750},\r
+{0, 61978, 5739},\r
+{0, 61755, 5753},\r
+{0, 61742, 5750},\r
+{0, 61845, 5753},\r
+{0, 62054, 5757},\r
+{0, 62186, 5766},\r
+{0, 62475, 5747},\r
+{0, 62930, 5770},\r
+{0, 63060, 5779},\r
+{0, 63022, 5779},\r
+{0, 63195, 5789},\r
+{0, 63697, 5783},\r
+{0, 64224, 5793},\r
+{0, 64910, 5810},\r
+{0, 65466, 5818},\r
+{0, 65995, 5809},\r
+{0, 66372, 5816},\r
+{0, 66701, 5813},\r
+{0, 66300, 5808},\r
+{0, 65946, 5809},\r
+{0, 65914, 5801},\r
+{0, 66021, 5804},\r
+{0, 66248, 5800},\r
+{0, 66482, 5807},\r
+{0, 66756, 5813},\r
+{0, 67131, 5814},\r
+{0, 67588, 5818},\r
+{0, 67899, 5825},\r
+{0, 67683, 5829},\r
+{0, 67813, 5826},\r
+{0, 68164, 5831},\r
+{0, 68446, 5820},\r
+{0, 68572, 5827},\r
+{0, 68717, 5829},\r
+{0, 68651, 5818},\r
+{0, 68414, 5813},\r
+{0, 67988, 5809},\r
+{0, 66941, 5788},\r
+{0, 65900, 5771},\r
+{0, 65298, 5767},\r
+{0, 64972, 5767},\r
+{0, 64967, 5779},\r
+{0, 65180, 5779},\r
+{0, 65468, 5791},\r
+{0, 65798, 5789},\r
+{0, 66108, 5798},\r
+{0, 66179, 5801},\r
+{0, 65593, 5790},\r
+{0, 65138, 5785},\r
+{0, 64874, 5788},\r
+{0, 64714, 5776},\r
+{0, 64530, 5775},\r
+{0, 64268, 5760},\r
+{0, 63955, 5763},\r
+{0, 63708, 5756},\r
+{0, 63417, 5753},\r
+{0, 62657, 5751},\r
+{0, 61682, 5742},\r
+{0, 61233, 5736},\r
+{0, 61069, 5742},\r
+{0, 61310, 5746},\r
+{0, 61715, 5746},\r
+{0, 62000, 5746},\r
+{0, 62230, 5752},\r
+{0, 62449, 5757},\r
+{0, 62507, 5774},\r
+{0, 61654, 5746},\r
+{0, 60821, 5744},\r
+{0, 60387, 5737},\r
+{0, 59880, 5735},\r
+{0, 59496, 5728},\r
+{0, 59358, 5732},\r
+{0, 59354, 5723},\r
+{0, 59329, 5742},\r
+{0, 59331, 5737},\r
+{0, 59350, 5734},\r
+{0, 58819, 5728},\r
+{0, 58525, 5740},\r
+{0, 58515, 5728},\r
+{0, 58705, 5738},\r
+{0, 59026, 5744},\r
+{0, 59270, 5742},\r
+{0, 59452, 5751},\r
+{0, 59545, 5756},\r
+{0, 59445, 5766},\r
+{0, 58818, 5743},\r
+{0, 58052, 5742},\r
+{0, 57569, 5734},\r
+{0, 57291, 5741},\r
+{0, 57174, 5719},\r
+{0, 57123, 5728},\r
+{0, 57029, 5735},\r
+{0, 57037, 5725},\r
+{0, 57128, 5732},\r
+{0, 57275, 5739},\r
+{0, 57110, 5733},\r
+{0, 56866, 5719},\r
+{0, 56784, 5736},\r
+{0, 56829, 5726},\r
+{0, 56994, 5735},\r
+{0, 57163, 5734},\r
+{0, 57203, 5731},\r
+{0, 57254, 5731},\r
+{0, 57384, 5735},\r
+{0, 57097, 5737},\r
+{0, 56576, 5730},\r
+{0, 56363, 5713},\r
+{0, 56377, 5712},\r
+{0, 56788, 5709},\r
+{0, 57322, 5724},\r
+{0, 57840, 5728},\r
+{0, 58287, 5746},\r
+{0, 58599, 5765},\r
+{0, 58873, 5755},\r
+{0, 58992, 5759},\r
+{0, 59133, 5769},\r
+{0, 59547, 5776},\r
+{0, 59909, 5776},\r
+{0, 60181, 5785},\r
+{0, 60555, 5793},\r
+{0, 61020, 5794},\r
+{0, 61340, 5797},\r
+{0, 61674, 5807},\r
+{0, 62036, 5793},\r
+{0, 61854, 5794},\r
+{0, 61705, 5814},\r
+{0, 61585, 5800},\r
+{0, 61722, 5805},\r
+{0, 62005, 5809},\r
+{0, 62302, 5810},\r
+{0, 62595, 5805},\r
+{0, 62918, 5820},\r
+{0, 63313, 5820},\r
+{0, 63635, 5831},\r
+{0, 63577, 5836},\r
+{0, 63674, 5823},\r
+{0, 64003, 5819},\r
+{0, 64328, 5816},\r
+{0, 64621, 5828},\r
+{0, 64843, 5829},\r
+{0, 64937, 5817},\r
+{0, 65114, 5801},\r
+{0, 65204, 5813},\r
+{0, 64832, 5809},\r
+{0, 64433, 5810},\r
+{0, 64394, 5802},\r
+{0, 64461, 5801},\r
+{0, 64496, 5809},\r
+{0, 64595, 5796},\r
+{0, 64774, 5791},\r
+{0, 65024, 5797},\r
+{0, 65207, 5801},\r
+{0, 65222, 5796},\r
+{0, 64850, 5784},\r
+{0, 64501, 5796},\r
+{0, 64304, 5796},\r
+{0, 64228, 5791},\r
+{0, 64207, 5780},\r
+{0, 64083, 5781},\r
+{0, 63955, 5779},\r
+{0, 63836, 5782},\r
+{0, 63848, 5786},\r
+{0, 63637, 5773},\r
+{0, 63210, 5761},\r
+{0, 62985, 5764},\r
+{0, 63039, 5767},\r
+{0, 63197, 5760},\r
+{0, 63341, 5778},\r
+{0, 63544, 5769},\r
+{0, 63739, 5767},\r
+{0, 63995, 5772},\r
+{0, 64323, 5767},\r
+{0, 64049, 5771},\r
+{0, 63642, 5765},\r
+{0, 63411, 5776},\r
+{0, 63356, 5765},\r
+{0, 63354, 5760},\r
+{0, 63317, 5751},\r
+{0, 63314, 5766},\r
+{0, 63295, 5763},\r
+{0, 63400, 5766},\r
+{0, 63437, 5758},\r
+{0, 63369, 5753},\r
+{0, 63327, 5767},\r
+{0, 63399, 5759},\r
+{0, 63467, 5750},\r
+{0, 63522, 5749},\r
+{0, 63643, 5760},\r
+{0, 63746, 5760},\r
+{0, 63901, 5755},\r
+{0, 63995, 5758},\r
+{0, 63701, 5752},\r
+{0, 63011, 5745},\r
+{0, 62404, 5752},\r
+{0, 62038, 5750},\r
+{0, 61801, 5749},\r
+{0, 61751, 5745},\r
+{0, 61743, 5751},\r
+{0, 61793, 5749},\r
+{0, 61898, 5745},\r
+{0, 62023, 5747},\r
+{0, 61989, 5745},\r
+{0, 61826, 5761},\r
+{0, 61562, 5750},\r
+{0, 61468, 5744},\r
+{0, 61576, 5749},\r
+{0, 61709, 5746},\r
+{0, 61772, 5750},\r
+{0, 61894, 5748},\r
+{0, 62009, 5755},\r
+{0, 61689, 5750},\r
+{0, 60954, 5751},\r
+{0, 60651, 5746},\r
+{0, 60585, 5749},\r
+{0, 60813, 5753},\r
+{0, 61144, 5773},\r
+{0, 61595, 5769},\r
+{0, 62118, 5771},\r
+{0, 62545, 5772},\r
+{0, 63013, 5782},\r
+{0, 62921, 5776},\r
+{0, 62850, 5789},\r
+{0, 63039, 5782},\r
+{0, 63403, 5789},\r
+{0, 63687, 5795},\r
+{0, 64014, 5791},\r
+{0, 64196, 5800},\r
+{0, 64372, 5798},\r
+{0, 64558, 5792},\r
+{0, 64607, 5795},\r
+{0, 64151, 5787},\r
+{0, 63895, 5787},\r
+{0, 63954, 5799},\r
+{0, 64189, 5779},\r
+{0, 64587, 5797},\r
+{0, 64970, 5815},\r
+{0, 65360, 5812},\r
+{0, 65723, 5796},\r
+{0, 66100, 5807},\r
+{0, 65975, 5796},\r
+{0, 65534, 5808},\r
+{0, 65351, 5795},\r
+{0, 65235, 5793},\r
+{0, 65136, 5783},\r
+{0, 64956, 5786},\r
+{0, 64777, 5778},\r
+{0, 64592, 5776},\r
+{0, 64480, 5778},\r
+{0, 64341, 5773},\r
+{0, 63685, 5778},\r
+{0, 63290, 5765},\r
+{0, 63096, 5767},\r
+{0, 63082, 5765},\r
+{0, 63151, 5769},\r
+{0, 63320, 5775},\r
+{0, 63511, 5790},\r
+{0, 63711, 5780},\r
+{0, 63809, 5779},\r
+{0, 63518, 5773},\r
+{0, 63015, 5767},\r
+{0, 62667, 5757},\r
+{0, 62371, 5760},\r
+{0, 62291, 5769},\r
+{0, 62318, 5751},\r
+{0, 62416, 5759},\r
+{0, 62491, 5772},\r
+{0, 62615, 5768},\r
+{0, 62820, 5780},\r
+{0, 62766, 5766},\r
+{0, 62747, 5767},\r
+{0, 63006, 5772},\r
+{0, 63298, 5786},\r
+{0, 63805, 5800},\r
+{0, 64308, 5792},\r
+{0, 64580, 5798},\r
+{0, 64543, 5797},\r
+{0, 64519, 5794},\r
+{0, 64231, 5788},\r
+{0, 63415, 5779},\r
+{0, 62813, 5780},\r
+{0, 62529, 5770},\r
+{0, 62474, 5761},\r
+{0, 62398, 5768},\r
+{0, 62397, 5763},\r
+{0, 62343, 5759},\r
+{0, 62261, 5762},\r
+{0, 62380, 5747},\r
+{0, 62215, 5753},\r
+{0, 61797, 5751},\r
+{0, 61596, 5748},\r
+{0, 61604, 5756},\r
+{0, 61836, 5762},\r
+{0, 62020, 5772},\r
+{0, 62051, 5761},\r
+{0, 62117, 5753},\r
+{0, 62315, 5767},\r
+{0, 62360, 5753},\r
+{0, 61815, 5764},\r
+{0, 61413, 5765},\r
+{0, 61228, 5760},\r
+{0, 61243, 5763},\r
+{0, 61355, 5763},\r
+{0, 61465, 5763},\r
+{0, 61588, 5761},\r
+{0, 61827, 5756},\r
+{0, 62006, 5774},\r
+{0, 61740, 5766},\r
+{0, 61107, 5748},\r
+{0, 60842, 5763},\r
+{0, 60838, 5763},\r
+{0, 60879, 5764},\r
+{0, 60958, 5768},\r
+{0, 61025, 5765},\r
+{0, 61060, 5758},\r
+{0, 61128, 5766},\r
+{0, 61120, 5766},\r
+{0, 60481, 5756},\r
+{0, 59914, 5755},\r
+{0, 59784, 5756},\r
+{0, 59777, 5762},\r
+{0, 59909, 5754},\r
+{0, 60083, 5757},\r
+{0, 60273, 5750},\r
+{0, 60514, 5752},\r
+{0, 60767, 5765},\r
+{0, 60808, 5754},\r
+{0, 60216, 5760},\r
+{0, 59910, 5738},\r
+{0, 59901, 5752},\r
+{0, 60023, 5769},\r
+{0, 60248, 5747},\r
+{0, 60533, 5744},\r
+{0, 60757, 5758},\r
+{0, 60971, 5770},\r
+{0, 61228, 5762},\r
+{0, 61118, 5753},\r
+{0, 60529, 5747},\r
+{0, 60192, 5745},\r
+{0, 60154, 5760},\r
+{0, 60270, 5749},\r
+{0, 60504, 5748},\r
+{0, 60755, 5762},\r
+{0, 60987, 5762},\r
+{0, 61232, 5763},\r
+{0, 61545, 5772},\r
+{0, 61119, 5764},\r
+{0, 60678, 5754},\r
+{0, 60493, 5762},\r
+{0, 60521, 5758},\r
+{0, 60591, 5754},\r
+{0, 60694, 5764},\r
+{0, 60803, 5757},\r
+{0, 60882, 5765},\r
+{0, 61101, 5764},\r
+{0, 61053, 5762},\r
+{0, 60476, 5753},\r
+{0, 60163, 5745},\r
+{0, 60176, 5754},\r
+{0, 60286, 5753},\r
+{0, 60471, 5761},\r
+{0, 60597, 5762},\r
+{0, 60765, 5750},\r
+{0, 60997, 5761},\r
+{0, 61186, 5760},\r
+{0, 61057, 5762},\r
+{0, 60504, 5741},\r
+{0, 60319, 5755},\r
+{0, 60354, 5755},\r
+{0, 60391, 5750},\r
+{0, 60439, 5751},\r
+{0, 60638, 5759},\r
+{0, 60767, 5754},\r
+{0, 60935, 5758},\r
+{0, 61126, 5760},\r
+{0, 60949, 5745},\r
+{0, 60527, 5750},\r
+{0, 60443, 5760},\r
+{0, 60562, 5750},\r
+{0, 60801, 5748},\r
+{0, 61128, 5754},\r
+{0, 61414, 5750},\r
+{0, 61637, 5757},\r
+{0, 61799, 5764},\r
+{0, 61925, 5765},\r
+{0, 61318, 5750},\r
+{0, 60805, 5743},\r
+{0, 60637, 5753},\r
+{0, 60530, 5749},\r
+{0, 60663, 5751},\r
+{0, 60765, 5756},\r
+{0, 60836, 5761},\r
+{0, 61034, 5764},\r
+{0, 61247, 5756},\r
+{0, 61305, 5746},\r
+{0, 60906, 5748},\r
+{0, 60653, 5750},\r
+{0, 60763, 5755},\r
+{0, 60995, 5751},\r
+{0, 61257, 5750},\r
+{0, 61507, 5756},\r
+{0, 61611, 5763},\r
+{0, 61801, 5767},\r
+{0, 62006, 5761},\r
+{0, 61518, 5762},\r
+{0, 60908, 5756},\r
+{0, 60678, 5741},\r
+{0, 60636, 5741},\r
+{0, 60638, 5755},\r
+{0, 60782, 5742},\r
+{0, 60932, 5749},\r
+{0, 61152, 5753},\r
+{0, 61356, 5757},\r
+{0, 61590, 5752},\r
+{0, 61185, 5753},\r
+{0, 60885, 5744},\r
+{0, 60924, 5749},\r
+{0, 61051, 5745},\r
+{0, 61224, 5755},\r
+{0, 61432, 5758},\r
+{0, 61663, 5753},\r
+{0, 61788, 5757},\r
+{0, 61848, 5763},\r
+{0, 61655, 5762},\r
+{0, 61100, 5749},\r
+{0, 60799, 5753},\r
+{0, 60930, 5756},\r
+{0, 61177, 5769},\r
+{0, 61555, 5760},\r
+{0, 61857, 5761},\r
+{0, 62092, 5772},\r
+{0, 62220, 5776},\r
+{0, 62445, 5767},\r
+{0, 62334, 5773},\r
+{0, 61905, 5771},\r
+{0, 61789, 5772},\r
+{0, 61878, 5775},\r
+{0, 62054, 5771},\r
+{0, 62205, 5772},\r
+{0, 62328, 5766},\r
+{0, 62407, 5769},\r
+{0, 62495, 5765},\r
+{0, 62495, 5759},\r
+{0, 62005, 5761},\r
+{0, 61616, 5767},\r
+{0, 61503, 5766},\r
+{0, 61602, 5758},\r
+{0, 61782, 5765},\r
+{0, 61961, 5753},\r
+{0, 62120, 5769},\r
+{0, 62290, 5768},\r
+{0, 62478, 5762},\r
+{0, 62490, 5762},\r
+{0, 61913, 5760},\r
+{0, 61594, 5758},\r
+{0, 61515, 5765},\r
+{0, 61640, 5761},\r
+{0, 61692, 5759},\r
+{0, 61827, 5755},\r
+{0, 61797, 5751},\r
+{0, 61813, 5742},\r
+{0, 62036, 5745},\r
+{0, 61561, 5728},\r
+{0, 61086, 5738},\r
+{0, 60923, 5739},\r
+{0, 60929, 5749},\r
+{0, 61136, 5744},\r
+{0, 61373, 5761},\r
+{0, 61605, 5756},\r
+{0, 61880, 5768},\r
+{0, 62064, 5774},\r
+{0, 62169, 5777},\r
+{0, 61895, 5761},\r
+{0, 62248, 5790},\r
+{0, 62649, 5785},\r
+{0, 63056, 5790},\r
+{0, 63459, 5794},\r
+{0, 63755, 5790},\r
+{0, 63968, 5803},\r
+{0, 63975, 5787},\r
+{0, 64034, 5803},\r
+{0, 63465, 5792},\r
+{0, 62798, 5789},\r
+{0, 62708, 5780},\r
+{0, 62791, 5788},\r
+{0, 62952, 5778},\r
+{0, 63170, 5772},\r
+{0, 63326, 5790},\r
+{0, 63500, 5789},\r
+{0, 63731, 5793},\r
+{0, 63953, 5791},\r
+{0, 63556, 5791},\r
+{0, 63278, 5797},\r
+{0, 63188, 5799},\r
+{0, 63161, 5783},\r
+{0, 63197, 5793},\r
+{0, 63261, 5793},\r
+{0, 63118, 5795},\r
+{0, 63035, 5797},\r
+{0, 62978, 5804},\r
+{0, 62831, 5781},\r
+{0, 62288, 5783},\r
+{0, 61923, 5779},\r
+{0, 61893, 5786},\r
+{0, 62082, 5781},\r
+{0, 62299, 5780},\r
+{0, 62488, 5772},\r
+{0, 62663, 5784},\r
+{0, 62891, 5785},\r
+{0, 63095, 5783},\r
+{0, 62599, 5780},\r
+{0, 62140, 5774},\r
+{0, 61934, 5768},\r
+{0, 61857, 5781},\r
+{0, 61991, 5782},\r
+{0, 62116, 5770},\r
+{0, 62133, 5780},\r
+{0, 62187, 5793},\r
+{0, 62388, 5779},\r
+{0, 62226, 5771},\r
+{0, 61572, 5774},\r
+{0, 61252, 5767},\r
+{0, 61281, 5764},\r
+{0, 61458, 5774},\r
+{0, 61656, 5776},\r
+{0, 61844, 5780},\r
+{0, 62050, 5790},\r
+{0, 62420, 5782},\r
+{0, 62644, 5777},\r
+{0, 62145, 5781},\r
+{0, 61751, 5780},\r
+{0, 61625, 5777},\r
+{0, 61618, 5789},\r
+{0, 61696, 5782},\r
+{0, 61788, 5782},\r
+{0, 61874, 5777},\r
+{0, 62052, 5785},\r
+{0, 62266, 5778},\r
+{0, 62277, 5786},\r
+{0, 61693, 5772},\r
+{0, 61435, 5778},\r
+{0, 61478, 5774},\r
+{0, 61711, 5764},\r
+{0, 61963, 5774},\r
+{0, 62215, 5776},\r
+{0, 62488, 5775},\r
+{0, 62743, 5788},\r
+{0, 63075, 5777},\r
+{0, 62594, 5783},\r
+{0, 62240, 5774},\r
+{0, 62145, 5775},\r
+{0, 62187, 5777},\r
+{0, 62278, 5776},\r
+{0, 62370, 5787},\r
+{0, 62541, 5776},\r
+{0, 62705, 5782},\r
+{0, 62874, 5783},\r
+{0, 62884, 5776},\r
+{0, 62389, 5773},\r
+{0, 62256, 5777},\r
+{0, 62397, 5768},\r
+{0, 62622, 5762},\r
+{0, 62894, 5773},\r
+{0, 63120, 5786},\r
+{0, 63277, 5773},\r
+{0, 63460, 5786},\r
+{0, 63655, 5783},\r
+{0, 63108, 5776},\r
+{0, 62718, 5775},\r
+{0, 62604, 5767},\r
+{0, 62563, 5769},\r
+{0, 62588, 5765},\r
+{0, 62552, 5769},\r
+{0, 62597, 5777},\r
+{0, 62628, 5780},\r
+{0, 62750, 5772},\r
+{0, 62529, 5768},\r
+{0, 61909, 5758},\r
+{0, 61576, 5762},\r
+{0, 61491, 5766},\r
+{0, 61657, 5759},\r
+{0, 61816, 5770},\r
+{0, 61928, 5765},\r
+{0, 62069, 5770},\r
+{0, 62260, 5770},\r
+{0, 62413, 5767},\r
+{0, 61801, 5770},\r
+{0, 61443, 5760},\r
+{0, 61378, 5762},\r
+{0, 61482, 5765},\r
+{0, 61646, 5765},\r
+{0, 61804, 5770},\r
+{0, 61832, 5771},\r
+{0, 61897, 5765},\r
+{0, 62009, 5767},\r
+{0, 61689, 5760},\r
+{0, 61014, 5750},\r
+{0, 60775, 5767},\r
+{0, 60705, 5755},\r
+{0, 60819, 5763},\r
+{0, 61163, 5762},\r
+{0, 61478, 5768},\r
+{0, 61753, 5764},\r
+{0, 62056, 5767},\r
+{0, 62274, 5765},\r
+{0, 61735, 5768},\r
+{0, 61425, 5760},\r
+{0, 61502, 5765},\r
+{0, 61651, 5762},\r
+{0, 61912, 5769},\r
+{0, 62253, 5775},\r
+{0, 62469, 5770},\r
+{0, 62734, 5774},\r
+{0, 62879, 5780},\r
+{0, 62580, 5783},\r
+{0, 61939, 5776},\r
+{0, 61669, 5771},\r
+{0, 61602, 5767},\r
+{0, 61671, 5786},\r
+{0, 61839, 5781},\r
+{0, 61977, 5771},\r
+{0, 62185, 5776},\r
+{0, 62400, 5783},\r
+{0, 62562, 5778},\r
+{0, 61962, 5760},\r
+{0, 61616, 5757},\r
+{0, 61672, 5776},\r
+{0, 61838, 5778},\r
+{0, 62090, 5758},\r
+{0, 62358, 5772},\r
+{0, 62582, 5779},\r
+{0, 62693, 5792},\r
+{0, 62966, 5791},\r
+{0, 62697, 5791},\r
+{0, 62455, 5783},\r
+{0, 62467, 5769},\r
+{0, 62605, 5783},\r
+{0, 62840, 5782},\r
+{0, 63168, 5786},\r
+{0, 63532, 5784},\r
+{0, 63896, 5794},\r
+{0, 64291, 5805},\r
+{0, 64758, 5804},\r
+{0, 64611, 5794},\r
+{0, 64211, 5797},\r
+{0, 64158, 5792},\r
+{0, 64267, 5801},\r
+{0, 64491, 5802},\r
+{0, 64811, 5805},\r
+{0, 65062, 5815},\r
+{0, 65306, 5812},\r
+{0, 65441, 5804},\r
+{0, 65284, 5799},\r
+{0, 64434, 5774},\r
+{0, 63854, 5784},\r
+{0, 63529, 5769},\r
+{0, 63279, 5760},\r
+{0, 63190, 5774},\r
+{0, 63219, 5760},\r
+{0, 63263, 5769},\r
+{0, 63351, 5765},\r
+{0, 63564, 5787},\r
+{0, 63277, 5774},\r
+{0, 62796, 5769},\r
+{0, 62506, 5764},\r
+{0, 62471, 5767},\r
+{0, 62562, 5770},\r
+{0, 62702, 5773},\r
+{0, 62732, 5769},\r
+{0, 62756, 5769},\r
+{0, 62713, 5764},\r
+{0, 62552, 5751},\r
+{0, 61826, 5756},\r
+{0, 61372, 5737},\r
+{0, 61237, 5751},\r
+{0, 61209, 5748},\r
+{0, 61388, 5754},\r
+{0, 61627, 5755},\r
+{0, 61730, 5766},\r
+{0, 61872, 5759},\r
+{0, 62014, 5754},\r
+{0, 61843, 5745},\r
+{0, 61188, 5759},\r
+{0, 60888, 5747},\r
+{0, 60594, 5760},\r
+{0, 60498, 5748},\r
+{0, 60528, 5757},\r
+{0, 60562, 5760},\r
+{0, 60561, 5753},\r
+{0, 60578, 5761},\r
+{0, 60557, 5750},\r
+{0, 59837, 5740},\r
+{0, 59182, 5725},\r
+{0, 58867, 5734},\r
+{0, 58708, 5732},\r
+{0, 58715, 5737},\r
+{0, 59117, 5744},\r
+{0, 59494, 5750},\r
+{0, 59745, 5759},\r
+{0, 60013, 5751},\r
+{0, 60076, 5742},\r
+{0, 59533, 5746},\r
+{0, 59173, 5744},\r
+{0, 59078, 5750},\r
+{0, 59113, 5750},\r
+{0, 59176, 5736},\r
+{0, 59239, 5744},\r
+{0, 59261, 5742},\r
+{0, 59241, 5745},\r
+{0, 59107, 5738},\r
+{0, 58684, 5723},\r
+{0, 58056, 5724},\r
+{0, 58010, 5735},\r
+{0, 58179, 5725},\r
+{0, 58548, 5737},\r
+{0, 59193, 5734},\r
+{0, 60022, 5738},\r
+{0, 61146, 5744},\r
+{0, 62468, 5761},\r
+{0, 63258, 5771},\r
+{0, 63210, 5769},\r
+{0, 63247, 5785},\r
+{0, 63493, 5783},\r
+{0, 63955, 5803},\r
+{0, 64734, 5807},\r
+{0, 65604, 5823},\r
+{0, 66555, 5835},\r
+{0, 67298, 5832},\r
+{0, 68032, 5844},\r
+{0, 68529, 5855},\r
+{0, 68500, 5848},\r
+{0, 68548, 5838},\r
+{0, 68630, 5840},\r
+{0, 68718, 5842},\r
+{0, 68746, 5839},\r
+{0, 68648, 5832},\r
+{0, 68411, 5830},\r
+{0, 68303, 5823},\r
+{0, 68230, 5824},\r
+{0, 67843, 5833},\r
+{0, 67282, 5807},\r
+{0, 67002, 5809},\r
+{0, 66832, 5822},\r
+{0, 66800, 5821},\r
+{0, 66781, 5823},\r
+{0, 66724, 5813},\r
+{0, 66764, 5822},\r
+{0, 66858, 5811},\r
+{0, 67014, 5811},\r
+{0, 66649, 5821},\r
+{0, 66162, 5810},\r
+{0, 65993, 5806},\r
+{0, 65948, 5800},\r
+{0, 66044, 5805},\r
+{0, 66143, 5811},\r
+{0, 66272, 5808},\r
+{0, 66337, 5807},\r
+{0, 66426, 5796},\r
+{0, 66364, 5809},\r
+{0, 65737, 5791},\r
+{0, 65333, 5797},\r
+{0, 65088, 5803},\r
+{0, 65079, 5785},\r
+{0, 65175, 5788},\r
+{0, 65235, 5798},\r
+{0, 65320, 5797},\r
+{0, 65371, 5797},\r
+{0, 65491, 5798},\r
+{0, 65058, 5780},\r
+{0, 64592, 5780},\r
+{0, 64366, 5793},\r
+{0, 64345, 5779},\r
+{0, 64479, 5778},\r
+{0, 64627, 5785},\r
+{0, 64727, 5778},\r
+{0, 64825, 5788},\r
+{0, 64874, 5782},\r
+{0, 64721, 5783},\r
+{0, 63950, 5786},\r
+{0, 63438, 5779},\r
+{0, 63242, 5777},\r
+{0, 63245, 5777},\r
+{0, 63368, 5781},\r
+{0, 63546, 5783},\r
+{0, 63663, 5789},\r
+{0, 63828, 5786},\r
+{0, 63995, 5789},\r
+{0, 63575, 5788},\r
+{0, 62933, 5784},\r
+{0, 62672, 5774},\r
+{0, 62758, 5769},\r
+{0, 62906, 5767},\r
+{0, 63141, 5777},\r
+{0, 63371, 5775},\r
+{0, 63553, 5780},\r
+{0, 63762, 5789},\r
+{0, 63802, 5792},\r
+{0, 62974, 5774},\r
+{0, 62377, 5777},\r
+{0, 62180, 5768},\r
+{0, 62152, 5770},\r
+{0, 62287, 5782},\r
+{0, 62424, 5782},\r
+{0, 62565, 5777},\r
+{0, 62763, 5785},\r
+{0, 62931, 5785},\r
+{0, 62525, 5779},\r
+{0, 61871, 5769},\r
+{0, 61663, 5767},\r
+{0, 61701, 5765},\r
+{0, 61877, 5774},\r
+{0, 62115, 5768},\r
+{0, 62270, 5775},\r
+{0, 62541, 5777},\r
+{0, 62833, 5772},\r
+{0, 62867, 5769},\r
+{0, 62178, 5770},\r
+{0, 61743, 5766},\r
+{0, 61632, 5765},\r
+{0, 61631, 5767},\r
+{0, 61840, 5772},\r
+{0, 61915, 5773},\r
+{0, 62116, 5774},\r
+{0, 62273, 5785},\r
+{0, 62462, 5782},\r
+{0, 62189, 5763},\r
+{0, 61577, 5771},\r
+{0, 61343, 5765},\r
+{0, 61373, 5776},\r
+{0, 61595, 5779},\r
+{0, 61835, 5772},\r
+{0, 62136, 5770},\r
+{0, 62389, 5774},\r
+{0, 62707, 5767},\r
+{0, 62890, 5778},\r
+{0, 62388, 5772},\r
+{0, 62031, 5768},\r
+{0, 61919, 5766},\r
+{0, 62038, 5766},\r
+{0, 62217, 5767},\r
+{0, 62342, 5770},\r
+{0, 62421, 5779},\r
+{0, 62534, 5775},\r
+{0, 62860, 5787},\r
+{0, 62865, 5785},\r
+{0, 62653, 5787},\r
+{0, 62773, 5770},\r
+{0, 63067, 5791},\r
+{0, 63408, 5789},\r
+{0, 63896, 5794},\r
+{0, 64195, 5796},\r
+{0, 64389, 5795},\r
+{0, 64516, 5796},\r
+{0, 64547, 5792},\r
+{0, 63648, 5790},\r
+{0, 62962, 5769},\r
+{0, 62591, 5780},\r
+{0, 62426, 5771},\r
+{0, 62464, 5774},\r
+{0, 62530, 5775},\r
+{0, 62655, 5774},\r
+{0, 62848, 5764},\r
+{0, 63071, 5762},\r
+{0, 62915, 5775},\r
+{0, 62279, 5765},\r
+{0, 62044, 5761},\r
+{0, 62044, 5760},\r
+{0, 62180, 5768},\r
+{0, 62331, 5767},\r
+{0, 62405, 5779},\r
+{0, 62539, 5781},\r
+{0, 62760, 5778},\r
+{0, 62957, 5778},\r
+{0, 62434, 5768},\r
+{0, 61954, 5766},\r
+{0, 61722, 5762},\r
+{0, 61691, 5765},\r
+{0, 61757, 5767},\r
+{0, 61894, 5758},\r
+{0, 62029, 5770},\r
+{0, 62164, 5769},\r
+{0, 62290, 5776},\r
+{0, 62143, 5773},\r
+{0, 61442, 5766},\r
+{0, 61082, 5754},\r
+{0, 61039, 5755},\r
+{0, 61151, 5761},\r
+{0, 61337, 5762},\r
+{0, 61538, 5760},\r
+{0, 61818, 5772},\r
+{0, 62053, 5768},\r
+{0, 62239, 5763},\r
+{0, 61566, 5760},\r
+{0, 60885, 5753},\r
+{0, 60757, 5757},\r
+{0, 60844, 5753},\r
+{0, 61042, 5757},\r
+{0, 61332, 5756},\r
+{0, 61622, 5756},\r
+{0, 61812, 5770},\r
+{0, 61931, 5763},\r
+{0, 61776, 5761},\r
+{0, 61115, 5756},\r
+{0, 60638, 5749},\r
+{0, 60487, 5749},\r
+{0, 60707, 5761},\r
+{0, 60958, 5741},\r
+{0, 61158, 5756},\r
+{0, 61232, 5749},\r
+{0, 61287, 5747},\r
+{0, 61422, 5757},\r
+{0, 60814, 5744},\r
+{0, 60165, 5735},\r
+{0, 59844, 5727},\r
+{0, 59797, 5725},\r
+{0, 59908, 5732},\r
+{0, 59991, 5739},\r
+{0, 59970, 5736},\r
+{0, 60230, 5727},\r
+{0, 60650, 5722},\r
+{0, 60913, 5729},\r
+{0, 60711, 5720},\r
+{0, 60289, 5718},\r
+{0, 59960, 5734},\r
+{0, 59757, 5715},\r
+{0, 59668, 5722},\r
+{0, 59582, 5723},\r
+{0, 59557, 5726},\r
+{0, 59620, 5734},\r
+{0, 59743, 5732},\r
+{0, 59203, 5731},\r
+{0, 58719, 5717},\r
+{0, 58536, 5716},\r
+{0, 58412, 5724},\r
+{0, 58451, 5723},\r
+{0, 58468, 5720},\r
+{0, 58452, 5733},\r
+{0, 58319, 5726},\r
+{0, 58223, 5732},\r
+{0, 58068, 5725},\r
+{0, 57694, 5717},\r
+{0, 57391, 5719},\r
+{0, 57123, 5707},\r
+{0, 57030, 5715},\r
+{0, 56991, 5721},\r
+{0, 57046, 5732},\r
+{0, 57170, 5730},\r
+{0, 57315, 5726},\r
+{0, 57433, 5728},\r
+{0, 57085, 5717},\r
+{0, 56826, 5730},\r
+{0, 56789, 5732},\r
+{0, 56786, 5714},\r
+{0, 56961, 5734},\r
+{0, 57075, 5743},\r
+{0, 57095, 5732},\r
+{0, 57127, 5726},\r
+{0, 57015, 5728},\r
+{0, 56576, 5730},\r
+{0, 55986, 5730},\r
+{0, 55667, 5724},\r
+{0, 55510, 5734},\r
+{0, 55469, 5732},\r
+{0, 55538, 5731},\r
+{0, 55559, 5733},\r
+{0, 55658, 5733},\r
+{0, 55836, 5742},\r
+{0, 56030, 5735},\r
+{0, 55839, 5739},\r
+{0, 55578, 5724},\r
+{0, 55592, 5732},\r
+{0, 55720, 5734},\r
+{0, 55944, 5735},\r
+{0, 56176, 5745},\r
+{0, 56352, 5748},\r
+{0, 56539, 5737},\r
+{0, 56714, 5750},\r
+{0, 56522, 5728},\r
+{0, 56097, 5738},\r
+{0, 55919, 5735},\r
+{0, 55870, 5735},\r
+{0, 55922, 5740},\r
+{0, 56056, 5751},\r
+{0, 56190, 5758},\r
+{0, 56245, 5751},\r
+{0, 56441, 5750},\r
+{0, 56457, 5745},\r
+{0, 56152, 5742},\r
+{0, 55996, 5746},\r
+{0, 56028, 5738},\r
+{0, 56175, 5745},\r
+{0, 56364, 5746},\r
+{0, 56600, 5746},\r
+{0, 56790, 5741},\r
+{0, 57027, 5749},\r
+{0, 57145, 5758},\r
+{0, 56925, 5744},\r
+{0, 56706, 5738},\r
+{0, 56700, 5745},\r
+{0, 56700, 5735},\r
+{0, 56770, 5746},\r
+{0, 56851, 5742},\r
+{0, 56970, 5743},\r
+{0, 57079, 5742},\r
+{0, 57204, 5748},\r
+{0, 57197, 5756},\r
+{0, 56916, 5738},\r
+{0, 56684, 5732},\r
+{0, 56706, 5730},\r
+{0, 56826, 5735},\r
+{0, 57092, 5732},\r
+{0, 57270, 5748},\r
+{0, 57462, 5739},\r
+{0, 57681, 5743},\r
+{0, 57812, 5743},\r
+{0, 57435, 5732},\r
+{0, 57147, 5740},\r
+{0, 57097, 5731},\r
+{0, 57157, 5734},\r
+{0, 57390, 5735},\r
+{0, 57618, 5750},\r
+{0, 57691, 5749},\r
+{0, 57788, 5748},\r
+{0, 57849, 5754},\r
+{0, 57736, 5756},\r
+{0, 57358, 5752},\r
+{0, 57049, 5732},\r
+{0, 56992, 5749},\r
+{0, 57064, 5739},\r
+{0, 57221, 5745},\r
+{0, 57493, 5737},\r
+{0, 57816, 5739},\r
+{0, 57955, 5753},\r
+{0, 57976, 5752},\r
+{0, 57485, 5749},\r
+{0, 57193, 5732},\r
+{0, 57121, 5742},\r
+{0, 56931, 5745},\r
+{0, 56800, 5743},\r
+{0, 56758, 5740},\r
+{0, 56842, 5736},\r
+{0, 56831, 5736},\r
+{0, 56778, 5749},\r
+{0, 56617, 5737},\r
+{0, 56046, 5736},\r
+{0, 55890, 5734},\r
+{0, 56052, 5730},\r
+{0, 56415, 5740},\r
+{0, 56673, 5735},\r
+{0, 56920, 5747},\r
+{0, 57196, 5743},\r
+{0, 57563, 5739},\r
+{0, 57915, 5749},\r
+{0, 57932, 5749},\r
+{0, 57920, 5732},\r
+{0, 57985, 5747},\r
+{0, 58101, 5759},\r
+{0, 58398, 5756},\r
+{0, 58657, 5749},\r
+{0, 59000, 5760},\r
+{0, 59327, 5760},\r
+{0, 59683, 5764},\r
+{0, 59682, 5757},\r
+{0, 59383, 5768},\r
+{0, 59284, 5749},\r
+{0, 59326, 5754},\r
+{0, 59510, 5762},\r
+{0, 59662, 5765},\r
+{0, 59903, 5764},\r
+{0, 60130, 5764},\r
+{0, 60352, 5753},\r
+{0, 60435, 5782},\r
+{0, 60048, 5753},\r
+{0, 59756, 5758},\r
+{0, 59621, 5756},\r
+{0, 59580, 5752},\r
+{0, 59641, 5761},\r
+{0, 59830, 5760},\r
+{0, 59982, 5766},\r
+{0, 60149, 5766},\r
+{0, 60287, 5766},\r
+{0, 60185, 5761},\r
+{0, 59823, 5761},\r
+{0, 59783, 5752},\r
+{0, 59734, 5753},\r
+{0, 59608, 5752},\r
+{0, 59343, 5744},\r
+{0, 59035, 5766},\r
+{0, 58994, 5754},\r
+{0, 59095, 5757},\r
+{0, 58951, 5751},\r
+{0, 58311, 5753},\r
+{0, 57810, 5751},\r
+{0, 57513, 5739},\r
+{0, 57431, 5744},\r
+{0, 57433, 5757},\r
+{0, 57538, 5760},\r
+{0, 57600, 5756},\r
+{0, 57706, 5760},\r
+{0, 57906, 5766},\r
+{0, 57933, 5761},\r
+{0, 57692, 5753},\r
+{0, 57595, 5759},\r
+{0, 57634, 5749},\r
+{0, 57804, 5753},\r
+{0, 57975, 5766},\r
+{0, 58127, 5756},\r
+{0, 58261, 5764},\r
+{0, 58500, 5764},\r
+{0, 58681, 5764},\r
+{0, 58418, 5741},\r
+{0, 58108, 5760},\r
+{0, 57945, 5755},\r
+{0, 57934, 5753},\r
+{0, 58145, 5755},\r
+{0, 58416, 5773},\r
+{0, 58614, 5759},\r
+{0, 58815, 5765},\r
+{0, 58994, 5764},\r
+{0, 58933, 5762},\r
+{0, 58552, 5761},\r
+{0, 58483, 5755},\r
+{0, 58520, 5769},\r
+{0, 58665, 5753},\r
+{0, 58897, 5752},\r
+{0, 59088, 5760},\r
+{0, 59329, 5766},\r
+{0, 59615, 5761},\r
+{0, 59787, 5763},\r
+{0, 59506, 5768},\r
+{0, 59280, 5761},\r
+{0, 59177, 5762},\r
+{0, 59261, 5756},\r
+{0, 59249, 5760},\r
+{0, 59316, 5765},\r
+{0, 59307, 5767},\r
+{0, 59357, 5772},\r
+{0, 59403, 5771},\r
+{0, 59406, 5764},\r
+{0, 59254, 5754},\r
+{0, 59190, 5761},\r
+{0, 59291, 5763},\r
+{0, 59545, 5762},\r
+{0, 59840, 5762},\r
+{0, 60165, 5765},\r
+{0, 60390, 5763},\r
+{0, 60620, 5769},\r
+{0, 60771, 5775},\r
+{0, 60512, 5761},\r
+{0, 60360, 5761},\r
+{0, 60213, 5770},\r
+{0, 60156, 5766},\r
+{0, 60120, 5765},\r
+{0, 60130, 5784},\r
+{0, 60283, 5778},\r
+{0, 60401, 5769},\r
+{0, 60492, 5776},\r
+{0, 60330, 5764},\r
+{0, 60068, 5763},\r
+{0, 59978, 5767},\r
+{0, 59953, 5759},\r
+{0, 60063, 5773},\r
+{0, 60169, 5752},\r
+{0, 60333, 5762},\r
+{0, 60513, 5755},\r
+{0, 60772, 5757},\r
+{0, 60695, 5764},\r
+{0, 60163, 5752},\r
+{0, 59778, 5756},\r
+{0, 59684, 5753},\r
+{0, 59685, 5753},\r
+{0, 59651, 5761},\r
+{0, 59614, 5756},\r
+{0, 59552, 5757},\r
+{0, 59510, 5753},\r
+{0, 59595, 5755},\r
+{0, 59255, 5753},\r
+{0, 58770, 5759},\r
+{0, 58577, 5757},\r
+{0, 58560, 5755},\r
+{0, 58583, 5753},\r
+{0, 58583, 5752},\r
+{0, 58582, 5750},\r
+{0, 58583, 5757},\r
+{0, 58737, 5757},\r
+{0, 58552, 5744},\r
+{0, 58014, 5751},\r
+{0, 57624, 5744},\r
+{0, 57584, 5737},\r
+{0, 57686, 5745},\r
+{0, 57722, 5751},\r
+{0, 57675, 5747},\r
+{0, 57624, 5748},\r
+{0, 57671, 5756},\r
+{0, 57748, 5740},\r
+{0, 57307, 5740},\r
+{0, 56921, 5737},\r
+{0, 56786, 5749},\r
+{0, 56851, 5745},\r
+{0, 57043, 5747},\r
+{0, 57191, 5747},\r
+{0, 57347, 5734},\r
+{0, 57539, 5741},\r
+{0, 57752, 5738},\r
+{0, 57509, 5721},\r
+{0, 57133, 5731},\r
+{0, 56986, 5728},\r
+{0, 56996, 5738},\r
+{0, 57230, 5743},\r
+{0, 57410, 5739},\r
+{0, 57515, 5739},\r
+{0, 57627, 5743},\r
+{0, 57699, 5740},\r
+{0, 57510, 5735},\r
+{0, 57097, 5742},\r
+{0, 56980, 5734},\r
+{0, 56984, 5725},\r
+{0, 57093, 5748},\r
+{0, 57203, 5733},\r
+{0, 57436, 5742},\r
+{0, 57640, 5750},\r
+{0, 57861, 5746},\r
+{0, 57906, 5730},\r
+{0, 57431, 5722},\r
+{0, 57308, 5725},\r
+{0, 57289, 5729},\r
+{0, 57486, 5730},\r
+{0, 57666, 5740},\r
+{0, 57832, 5742},\r
+{0, 58065, 5735},\r
+{0, 58216, 5731},\r
+{0, 58216, 5734},\r
+{0, 57671, 5735},\r
+{0, 57250, 5733},\r
+{0, 57038, 5727},\r
+{0, 57094, 5731},\r
+{0, 57244, 5733},\r
+{0, 57376, 5728},\r
+{0, 57454, 5735},\r
+{0, 57602, 5727},\r
+{0, 57737, 5719},\r
+{0, 57455, 5718},\r
+{0, 57109, 5721},\r
+{0, 57022, 5720},\r
+{0, 57099, 5732},\r
+{0, 57309, 5724},\r
+{0, 57564, 5732},\r
+{0, 57830, 5735},\r
+{0, 57975, 5728},\r
+{0, 58161, 5740},\r
+{0, 58118, 5737},\r
+{0, 57710, 5719},\r
+{0, 57527, 5728},\r
+{0, 57501, 5724},\r
+{0, 57592, 5722},\r
+{0, 57661, 5727},\r
+{0, 57671, 5732},\r
+{0, 57641, 5741},\r
+{0, 57605, 5734},\r
+{0, 57559, 5734},\r
+{0, 57396, 5723},\r
+{0, 57569, 5738},\r
+{0, 58093, 5756},\r
+{0, 58718, 5779},\r
+{0, 59324, 5776},\r
+{0, 59817, 5780},\r
+{0, 60291, 5792},\r
+{0, 60676, 5785},\r
+{0, 60910, 5786},\r
+{0, 60723, 5785},\r
+{0, 60731, 5783},\r
+{0, 60825, 5783},\r
+{0, 60989, 5788},\r
+{0, 61151, 5780},\r
+{0, 61360, 5794},\r
+{0, 61532, 5795},\r
+{0, 61786, 5794},\r
+{0, 61971, 5790},\r
+{0, 61843, 5791},\r
+{0, 61696, 5798},\r
+{0, 61734, 5793},\r
+{0, 61824, 5790},\r
+{0, 61995, 5783},\r
+{0, 62082, 5795},\r
+{0, 62183, 5798},\r
+{0, 62341, 5794},\r
+{0, 62467, 5798},\r
+{0, 62186, 5797},\r
+{0, 61929, 5794},\r
+{0, 61792, 5793},\r
+{0, 61775, 5788},\r
+{0, 61872, 5790},\r
+{0, 61929, 5782},\r
+{0, 61920, 5787},\r
+{0, 61914, 5790},\r
+{0, 61872, 5778},\r
+{0, 61670, 5778},\r
+{0, 61182, 5774},\r
+{0, 60971, 5761},\r
+{0, 60887, 5776},\r
+{0, 60914, 5772},\r
+{0, 61053, 5777},\r
+{0, 61298, 5777},\r
+{0, 61471, 5766},\r
+{0, 61733, 5766},\r
+{0, 61731, 5761},\r
+{0, 61416, 5763},\r
+{0, 61276, 5766},\r
+{0, 60872, 5759},\r
+{0, 60318, 5765},\r
+{0, 59821, 5768},\r
+{0, 59663, 5762},\r
+{0, 59724, 5768},\r
+{0, 59571, 5774},\r
+{0, 59225, 5767},\r
+{0, 58531, 5752},\r
+{0, 58153, 5761},\r
+{0, 58064, 5755},\r
+{0, 58052, 5752},\r
+{0, 58131, 5769},\r
+{0, 58161, 5762},\r
+{0, 58336, 5765},\r
+{0, 58513, 5767},\r
+{0, 58586, 5757},\r
+{0, 58015, 5762},\r
+{0, 57681, 5744},\r
+{0, 57555, 5753},\r
+{0, 57602, 5755},\r
+{0, 57802, 5748},\r
+{0, 57908, 5763},\r
+{0, 58042, 5768},\r
+{0, 58226, 5754},\r
+{0, 58298, 5745},\r
+{0, 57702, 5743},\r
+{0, 57215, 5751},\r
+{0, 57052, 5760},\r
+{0, 56961, 5749},\r
+{0, 57115, 5746},\r
+{0, 57342, 5768},\r
+{0, 57435, 5762},\r
+{0, 57506, 5762},\r
+{0, 57588, 5764},\r
+{0, 57205, 5760},\r
+{0, 56804, 5761},\r
+{0, 56664, 5745},\r
+{0, 56707, 5753},\r
+{0, 56811, 5762},\r
+{0, 56943, 5762},\r
+{0, 57149, 5754},\r
+{0, 57383, 5758},\r
+{0, 57559, 5767},\r
+{0, 57256, 5752},\r
+{0, 56872, 5742},\r
+{0, 56762, 5746},\r
+{0, 56790, 5745},\r
+{0, 56834, 5749},\r
+{0, 57029, 5737},\r
+{0, 57260, 5736},\r
+{0, 57682, 5739},\r
+{0, 58314, 5754},\r
+{0, 58656, 5770},\r
+{0, 58643, 5764},\r
+{0, 58539, 5761},\r
+{0, 58542, 5768},\r
+{0, 58596, 5765},\r
+{0, 58691, 5765},\r
+{0, 58731, 5774},\r
+{0, 58934, 5772},\r
+{0, 59123, 5761},\r
+{0, 59054, 5768},\r
+{0, 58660, 5759},\r
+{0, 58449, 5757},\r
+{0, 58359, 5759},\r
+{0, 58418, 5751},\r
+{0, 58399, 5759},\r
+{0, 58423, 5759},\r
+{0, 58394, 5764},\r
+{0, 58424, 5756},\r
+{0, 58387, 5754},\r
+{0, 58087, 5749},\r
+{0, 57859, 5749},\r
+{0, 57822, 5747},\r
+{0, 57919, 5751},\r
+{0, 58108, 5753},\r
+{0, 58344, 5748},\r
+{0, 58588, 5747},\r
+{0, 58813, 5756},\r
+{0, 58906, 5751},\r
+{0, 58689, 5746},\r
+{0, 58544, 5744},\r
+{0, 58565, 5745},\r
+{0, 58666, 5745},\r
+{0, 58771, 5744},\r
+{0, 58778, 5738},\r
+{0, 58750, 5758},\r
+{0, 58706, 5738},\r
+{0, 58619, 5747},\r
+{0, 58347, 5752},\r
+{0, 58253, 5750},\r
+{0, 58209, 5737},\r
+{0, 58327, 5749},\r
+{0, 58465, 5747},\r
+{0, 58677, 5773},\r
+{0, 58822, 5754},\r
+{0, 58988, 5770},\r
+{0, 59120, 5763},\r
+{0, 58836, 5753},\r
+{0, 58669, 5756},\r
+{0, 58673, 5750},\r
+{0, 58754, 5765},\r
+{0, 58889, 5752},\r
+{0, 59021, 5757},\r
+{0, 59062, 5777},\r
+{0, 59104, 5766},\r
+{0, 59146, 5760},\r
+{0, 58839, 5765},\r
+{0, 58500, 5767},\r
+{0, 58373, 5749},\r
+{0, 58279, 5756},\r
+{0, 58422, 5762},\r
+{0, 58559, 5765},\r
+{0, 58758, 5764},\r
+{0, 58937, 5768},\r
+{0, 59153, 5770},\r
+{0, 58995, 5766},\r
+{0, 58621, 5757},\r
+{0, 58507, 5756},\r
+{0, 58526, 5759},\r
+{0, 58618, 5752},\r
+{0, 58798, 5757},\r
+{0, 58994, 5757},\r
+{0, 59106, 5759},\r
+{0, 59158, 5761},\r
+{0, 58934, 5764},\r
+{0, 58364, 5763},\r
+{0, 58120, 5759},\r
+{0, 58090, 5757},\r
+{0, 58150, 5760},\r
+{0, 58238, 5758},\r
+{0, 58464, 5767},\r
+{0, 58693, 5760},\r
+{0, 58911, 5771},\r
+{0, 59013, 5762},\r
+{0, 58653, 5762},\r
+{0, 58510, 5743},\r
+{0, 58587, 5754},\r
+{0, 58661, 5758},\r
+{0, 58808, 5754},\r
+{0, 58986, 5763},\r
+{0, 59128, 5760},\r
+{0, 59136, 5765},\r
+{0, 59133, 5764},\r
+{0, 58746, 5762},\r
+{0, 58407, 5751},\r
+{0, 58295, 5754},\r
+{0, 58307, 5751},\r
+{0, 58368, 5763},\r
+{0, 58517, 5758},\r
+{0, 58731, 5752},\r
+{0, 58854, 5756},\r
+{0, 59067, 5765},\r
+{0, 58864, 5749},\r
+{0, 58655, 5752},\r
+{0, 58601, 5741},\r
+{0, 58679, 5745},\r
+{0, 58786, 5756},\r
+{0, 58916, 5763},\r
+{0, 58981, 5758},\r
+{0, 58914, 5763},\r
+{0, 58891, 5759},\r
+{0, 58888, 5764},\r
+{0, 58676, 5747},\r
+{0, 58834, 5759},\r
+{0, 59073, 5776},\r
+{0, 59332, 5767},\r
+{0, 59562, 5773},\r
+{0, 59824, 5773},\r
+{0, 60261, 5768},\r
+{0, 60683, 5770},\r
+{0, 61001, 5771},\r
+};\r
+static const int16_t PAH8009_mems_HRD[][3*NF_PPG_PER_CHANNEL] = \r
+{\r
+{6305, -1007, 8865},\r
+{5777, -95, 9889},\r
+{6385, 1137, 8897},\r
+{4401, 833, 5425},\r
+{4465, -1647, 3153},\r
+{19985, 3937, 1713},\r
+{-2447, -3775, 8273},\r
+{5009, 4017, 12657},\r
+{6769, 1329, 6033},\r
+{5025, -1567, 6145},\r
+{6225, 1025, 5889},\r
+{5681, -351, 5057},\r
+{5905, 113, 5745},\r
+{5793, -31, 6369},\r
+{5297, 193, 5857},\r
+{5121, 657, 6321},\r
+{5121, 1041, 5937},\r
+{5873, 17, 6753},\r
+{6577, -1583, 6065},\r
+{5825, -63, 6385},\r
+{5601, 33, 4961},\r
+{6097, -303, 4785},\r
+{6001, 433, 5697},\r
+{6001, 929, 5553},\r
+{6145, 561, 5201},\r
+{6353, 1009, 5009},\r
+{6481, 1697, 5153},\r
+{6049, 1633, 5441},\r
+{6033, 1361, 5697},\r
+{6113, 1313, 5681},\r
+{6161, 1697, 5409},\r
+{6145, 1345, 5537},\r
+{6081, 1889, 5505},\r
+{5985, 1425, 5409},\r
+{5985, 1809, 5505},\r
+{5953, 1729, 5553},\r
+{5953, 1569, 5681},\r
+{5889, 1649, 5489},\r
+{6065, 1409, 5713},\r
+{6017, 1761, 5457},\r
+{6001, 1953, 5521},\r
+{5985, 2065, 5617},\r
+{5777, 1793, 5633},\r
+{5633, 1601, 5745},\r
+{5809, 1601, 5857},\r
+{5809, 1633, 5665},\r
+{5713, 1761, 5633},\r
+{5841, 1697, 5777},\r
+{5745, 1713, 5617},\r
+{5825, 1713, 5793},\r
+{5905, 1633, 5713},\r
+{5841, 1601, 5681},\r
+{5921, 1761, 5649},\r
+{5889, 1649, 5553},\r
+{5985, 1649, 5569},\r
+{5825, 1857, 5937},\r
+{5809, 1585, 5601},\r
+{6017, 1569, 5441},\r
+{5601, 1377, 5697},\r
+{5841, 1265, 5825},\r
+{6049, 1857, 6145},\r
+{5889, 1585, 4977},\r
+{6609, 1185, 5521},\r
+{6161, 1697, 5441},\r
+{6065, 1633, 5489},\r
+{6193, 1633, 5505},\r
+{6225, 1569, 5441},\r
+{6129, 1521, 5329},\r
+{6129, 1569, 5409},\r
+{6081, 1473, 5345},\r
+{5857, 1377, 5537},\r
+{5905, 1153, 5665},\r
+{6113, 1217, 5441},\r
+{6209, 1441, 5409},\r
+{6145, 1121, 5505},\r
+{6097, 1121, 5585},\r
+{6177, 1089, 5473},\r
+{6193, 1281, 5345},\r
+{6225, 1265, 5457},\r
+{5985, 1249, 5361},\r
+{6209, 1425, 5761},\r
+{6049, 1057, 5585},\r
+{5969, 1009, 5793},\r
+{6017, 1153, 5649},\r
+{6065, 1377, 5569},\r
+{6001, 1345, 5617},\r
+{6033, 1345, 5457},\r
+{6241, 1473, 5457},\r
+{6097, 1425, 5473},\r
+{6161, 1521, 5441},\r
+{6129, 1569, 5441},\r
+{6097, 1537, 5441},\r
+{6065, 1505, 5425},\r
+{6177, 1681, 5441},\r
+{6113, 1745, 5505},\r
+{6337, 1505, 5233},\r
+{6129, 1649, 5393},\r
+{6225, 1617, 5361},\r
+{6177, 1553, 5329},\r
+{6305, 1569, 5201},\r
+{6209, 1633, 5265},\r
+{6401, 1745, 5233},\r
+{6225, 1569, 5281},\r
+{6385, 1585, 5217},\r
+{6321, 1665, 5217},\r
+{6289, 1521, 5121},\r
+{6321, 1761, 5249},\r
+{6289, 1569, 5201},\r
+{6273, 1601, 5217},\r
+{6273, 1649, 5233},\r
+{6321, 1649, 5313},\r
+{6321, 1601, 5249},\r
+{6321, 1569, 5249},\r
+{6273, 1569, 5297},\r
+{6161, 1441, 5249},\r
+{6257, 1537, 5329},\r
+{6225, 1425, 5313},\r
+{6289, 1697, 5425},\r
+{6257, 1281, 5153},\r
+{6305, 1281, 5249},\r
+{6337, 1393, 5393},\r
+{6321, 1201, 5313},\r
+{6369, 1425, 5361},\r
+{6257, 1537, 5201},\r
+{6385, 1473, 5137},\r
+{6433, 1569, 5137},\r
+{6369, 1745, 4977},\r
+{6417, 1585, 5153},\r
+{6289, 1585, 5105},\r
+{6289, 1585, 5185},\r
+{6321, 1649, 5185},\r
+{6241, 1569, 5329},\r
+{6337, 1713, 5313},\r
+{6209, 1537, 5281},\r
+{6369, 1569, 5265},\r
+{6049, 1713, 5265},\r
+{6241, 1649, 5489},\r
+{6353, 1409, 5169},\r
+{6177, 1409, 5041},\r
+{6369, 1505, 5377},\r
+{6273, 1521, 5393},\r
+{6289, 1553, 5329},\r
+{6289, 1633, 5185},\r
+{6273, 1617, 5217},\r
+{6257, 1761, 5089},\r
+{6337, 1777, 5201},\r
+{6209, 1617, 5297},\r
+{6257, 1729, 5185},\r
+{6401, 1841, 5121},\r
+{6353, 1745, 5169},\r
+{6273, 1601, 5137},\r
+{6369, 1793, 5153},\r
+{6337, 1713, 5153},\r
+{6369, 1713, 5201},\r
+{6385, 1665, 5217},\r
+{6241, 2017, 5025},\r
+{6369, 1761, 5025},\r
+{6337, 1697, 5105},\r
+{6369, 1761, 5137},\r
+{6401, 1809, 5057},\r
+{6353, 1793, 5089},\r
+{6417, 1841, 5073},\r
+{6385, 1873, 5041},\r
+{6385, 1809, 5073},\r
+{6417, 1905, 5089},\r
+{6353, 1841, 5057},\r
+{6353, 1873, 5073},\r
+{6337, 1873, 5073},\r
+{6353, 1889, 5025},\r
+{6385, 1857, 5153},\r
+{6305, 1873, 5121},\r
+{6337, 1857, 5089},\r
+{6289, 1889, 4961},\r
+{6241, 1825, 4769},\r
+{6225, 1841, 4737},\r
+{6305, 1921, 4977},\r
+{6353, 2177, 4561},\r
+{6161, 1697, 4225},\r
+{6401, 3089, 6225},\r
+{6321, 2769, 5537},\r
+{6177, 2449, 5153},\r
+{6177, 2545, 5057},\r
+{6145, 2545, 5153},\r
+{6177, 2561, 5025},\r
+{6161, 2561, 5073},\r
+{6145, 2513, 5057},\r
+{6161, 2385, 5025},\r
+{6161, 2657, 5121},\r
+{6161, 2753, 4897},\r
+{6145, 2689, 4913},\r
+{6145, 2753, 4977},\r
+{6145, 2801, 5009},\r
+{6161, 2673, 5073},\r
+{6129, 2657, 5025},\r
+{6145, 2705, 5041},\r
+{6145, 2625, 5041},\r
+{6129, 2577, 5089},\r
+{6113, 2625, 5073},\r
+{6081, 2641, 5041},\r
+{6081, 2593, 5105},\r
+{6161, 2689, 5233},\r
+{6033, 2449, 5121},\r
+{6081, 2497, 5137},\r
+{6097, 2577, 5233},\r
+{6097, 2465, 5169},\r
+{6113, 2481, 5153},\r
+{6097, 2561, 5121},\r
+{6081, 2513, 5105},\r
+{6113, 2561, 5153},\r
+{6129, 2545, 5105},\r
+{6129, 2529, 5089},\r
+{6097, 2497, 5169},\r
+{6113, 2513, 5185},\r
+{6097, 2401, 5169},\r
+{6193, 2529, 5217},\r
+{6161, 2801, 5153},\r
+{6113, 2737, 5009},\r
+{6129, 2577, 4961},\r
+{6081, 2561, 5217},\r
+{6049, 2449, 5057},\r
+{6049, 2321, 5169},\r
+{6097, 2497, 5249},\r
+{6065, 2449, 5313},\r
+{6017, 2513, 5185},\r
+{6049, 2529, 5201},\r
+{6097, 2481, 5201},\r
+{6065, 2369, 5297},\r
+{6001, 2401, 5233},\r
+{6017, 2417, 5313},\r
+{6033, 2385, 5281},\r
+{5985, 2337, 5217},\r
+{5969, 2385, 5329},\r
+{6049, 2337, 5457},\r
+{6081, 2577, 5329},\r
+{5969, 2481, 5249},\r
+{5953, 2257, 5409},\r
+{5953, 2353, 5521},\r
+{5873, 2289, 5393},\r
+{5473, 3185, 5297},\r
+{6081, 2817, 3889},\r
+{6161, 3313, 5569},\r
+{5745, 2769, 5249},\r
+{6449, 2849, 4913},\r
+{5857, 2593, 5009},\r
+{5953, 2481, 5233},\r
+{6273, 2369, 4817},\r
+{6353, 2609, 4929},\r
+{6209, 2385, 4849},\r
+{6337, 2177, 5073},\r
+{6225, 2129, 5041},\r
+{6353, 2033, 5057},\r
+{6321, 2193, 4945},\r
+{6417, 2017, 5057},\r
+{6321, 2001, 4993},\r
+{6417, 2017, 4833},\r
+{6385, 1969, 4961},\r
+{6353, 1953, 4961},\r
+{6321, 2049, 5025},\r
+{6401, 2209, 4945},\r
+{6449, 2049, 5041},\r
+{6465, 2161, 4961},\r
+{6337, 2113, 5009},\r
+{6417, 2225, 4897},\r
+{6481, 2305, 4961},\r
+{6465, 2049, 4673},\r
+{6225, 2897, 5377},\r
+{6193, 2657, 5537},\r
+{6449, 2385, 4673},\r
+{6353, 2273, 4753},\r
+{6273, 2369, 4529},\r
+{6369, 3169, 6049},\r
+{6337, 2753, 5361},\r
+{6113, 2417, 5009},\r
+{6273, 2257, 5009},\r
+{6225, 2433, 4897},\r
+{6225, 2129, 5153},\r
+{6257, 2641, 5137},\r
+{6001, 2353, 5281},\r
+{6193, 2241, 4849},\r
+{6305, 2481, 5617},\r
+{6529, 2817, 5809},\r
+{6337, 3473, 5441},\r
+{6129, 1345, 3569},\r
+{6049, 1585, 3985},\r
+{6241, 1633, 4177},\r
+{6225, 2081, 5009},\r
+{6273, 1985, 4977},\r
+{6145, 1969, 5265},\r
+{6289, 1713, 4577},\r
+{6401, 1649, 4769},\r
+{6273, 1505, 4993},\r
+{6305, 1553, 5521},\r
+{6145, 1617, 5393},\r
+{6193, 1505, 5185},\r
+{6305, 1761, 5313},\r
+{6081, 1569, 5425},\r
+{6177, 1537, 5297},\r
+{6209, 1473, 5441},\r
+{6257, 1569, 5441},\r
+{6177, 1409, 5297},\r
+{6241, 1473, 5185},\r
+{6177, 1601, 4913},\r
+{6177, 1553, 5137},\r
+{6257, 1361, 5633},\r
+{6193, 1729, 5617},\r
+{6193, 1425, 5409},\r
+{6241, 1569, 5329},\r
+{6193, 1665, 5217},\r
+{6289, 1489, 5201},\r
+{6257, 1521, 5297},\r
+{6225, 1553, 5297},\r
+{6113, 1713, 5249},\r
+{6209, 1713, 5281},\r
+{6225, 1697, 5329},\r
+{6209, 1745, 5217},\r
+{6241, 1697, 5233},\r
+{6193, 1697, 5233},\r
+{6193, 1809, 5297},\r
+{6273, 1825, 5217},\r
+{6241, 1841, 5233},\r
+{6241, 1697, 5265},\r
+{6225, 1905, 5233},\r
+{6209, 1793, 5265},\r
+{6193, 1873, 5233},\r
+{6257, 1873, 5265},\r
+{6209, 1825, 5249},\r
+{6257, 1809, 5233},\r
+{6209, 1793, 5185},\r
+{6241, 1825, 5217},\r
+{6193, 1857, 5297},\r
+{6225, 1729, 5329},\r
+{6097, 1633, 5361},\r
+{6161, 1841, 5377},\r
+{6129, 1841, 5377},\r
+{6129, 1841, 5345},\r
+{6113, 1713, 5393},\r
+{6129, 1681, 5393},\r
+{6113, 1697, 5425},\r
+{6129, 1649, 5409},\r
+{6081, 1601, 5457},\r
+{6113, 1713, 5425},\r
+{6097, 1713, 5505},\r
+{6113, 1601, 5441},\r
+{6081, 1649, 5409},\r
+{6081, 1617, 5521},\r
+{6017, 1649, 5473},\r
+{6065, 1601, 5441},\r
+{6081, 1585, 5441},\r
+{6113, 1713, 5473},\r
+{6097, 1793, 5441},\r
+{6081, 1713, 5425},\r
+{6081, 1745, 5457},\r
+{6097, 1665, 5441},\r
+{6113, 1697, 5441},\r
+{6097, 1729, 5425},\r
+{6081, 1713, 5441},\r
+{6097, 1697, 5425},\r
+{6113, 1697, 5425},\r
+{6113, 1745, 5409},\r
+{6081, 1745, 5473},\r
+{6049, 1713, 5377},\r
+{6097, 1681, 5409},\r
+{6081, 1873, 5409},\r
+{6097, 1809, 5377},\r
+{6145, 1777, 5489},\r
+{6193, 1761, 5281},\r
+{6113, 1489, 5281},\r
+{6209, 1521, 5393},\r
+{6129, 1793, 5265},\r
+{6145, 1937, 5377},\r
+{6225, 1905, 5361},\r
+{6145, 1713, 5473},\r
+{6145, 1473, 5489},\r
+{5873, 1793, 5473},\r
+{5985, 1729, 5553},\r
+{6017, 1473, 5457},\r
+{6033, 1697, 5665},\r
+{6033, 1873, 5953},\r
+{6065, 1713, 5425},\r
+{5985, 1425, 5489},\r
+{5889, 1329, 5537},\r
+{5953, 1233, 5489},\r
+{6033, 1233, 5601},\r
+{5729, 849, 5761},\r
+{5681, 705, 5969},\r
+{5761, 833, 6161},\r
+{5729, 689, 6017},\r
+{5841, 705, 5953},\r
+{5713, 305, 5953},\r
+{5537, 481, 6001},\r
+{5665, 545, 6145},\r
+{5601, 465, 6081},\r
+{5601, 417, 6049},\r
+{5681, 449, 6081},\r
+{5633, 305, 6209},\r
+{5617, 529, 6049},\r
+{5633, 513, 6001},\r
+{5745, 481, 5969},\r
+{5697, 561, 5937},\r
+{5745, 641, 5985},\r
+{5921, 929, 5793},\r
+{5857, 737, 5681},\r
+{5985, 913, 5681},\r
+{6001, 961, 5633},\r
+{6097, 1473, 5393},\r
+{6033, 1217, 5489},\r
+{6145, 1233, 5649},\r
+{6289, 1457, 5361},\r
+{6273, 1441, 5249},\r
+{6273, 1265, 5265},\r
+{6145, 1665, 5377},\r
+{6241, 1633, 5409},\r
+{6161, 1617, 5377},\r
+{6177, 1729, 5297},\r
+{6177, 1665, 5409},\r
+{6129, 1553, 5361},\r
+{6161, 1569, 5345},\r
+{6193, 1745, 5377},\r
+{6273, 1361, 5393},\r
+{6177, 1505, 5489},\r
+{5905, 1073, 5553},\r
+{5953, 1441, 5681},\r
+{5873, 1249, 5777},\r
+{5745, 1233, 5777},\r
+{5921, 849, 5921},\r
+{5825, 913, 5873},\r
+{5777, 801, 5873},\r
+{5745, 1185, 5841},\r
+{5793, 1089, 5873},\r
+{5761, 945, 5921},\r
+{5793, 1041, 5841},\r
+{5889, 1281, 5681},\r
+{5793, 1153, 5777},\r
+{5649, 1425, 5713},\r
+{5809, 1553, 5809},\r
+{5441, 1745, 5841},\r
+{5537, 1841, 5729},\r
+{6945, 641, 5521},\r
+{6097, 2113, 4945},\r
+{5953, 2705, 5329},\r
+{6193, 2449, 5585},\r
+{5841, 1953, 5249},\r
+{6321, 1793, 5329},\r
+{6369, 1633, 5425},\r
+{6177, 1745, 5185},\r
+{6305, 1457, 4833},\r
+{6353, 769, 5201},\r
+{6529, 817, 5265},\r
+{6305, 641, 5473},\r
+{6289, 497, 5313},\r
+{6241, 337, 5361},\r
+{6321, 145, 5409},\r
+{6257, -63, 5441},\r
+{6177, 273, 5489},\r
+{6129, 193, 5585},\r
+{6241, -79, 5633},\r
+{6017, 65, 5665},\r
+{6257, 49, 5617},\r
+{5985, -255, 5873},\r
+{6049, -111, 5537},\r
+{6273, -15, 5585},\r
+{6113, 17, 5585},\r
+{6033, -255, 5649},\r
+{6017, 17, 5569},\r
+{6225, -287, 5553},\r
+{6321, -127, 5489},\r
+{6081, 97, 5601},\r
+{6193, 209, 5201},\r
+{6385, 241, 5217},\r
+{6273, 321, 5233},\r
+{6769, 449, 5697},\r
+{6433, 257, 5249},\r
+{6545, 689, 5089},\r
+{6305, 1313, 5281},\r
+{6177, 721, 5505},\r
+{6193, 1825, 5649},\r
+{6129, 961, 4705},\r
+{6641, 1121, 4961},\r
+{6513, 801, 4945},\r
+{6673, 641, 5345},\r
+{6241, -159, 5185},\r
+{6353, 657, 4977},\r
+{6305, 1377, 5361},\r
+{6433, 561, 5265},\r
+{6129, 1745, 5265},\r
+{6561, 465, 5329},\r
+{6417, 1089, 5505},\r
+{6193, 785, 5745},\r
+{6065, 1233, 5729},\r
+{5793, 1777, 5521},\r
+{6001, 993, 5937},\r
+{5905, 769, 5697},\r
+{6033, 1105, 5489},\r
+{6049, 1377, 5537},\r
+{5873, 1153, 5649},\r
+{5937, 1281, 5665},\r
+{6097, 2001, 5409},\r
+{6081, 2065, 5217},\r
+{6177, 1953, 5217},\r
+{6129, 2081, 5297},\r
+{6385, 1873, 5313},\r
+{5745, 1761, 5457},\r
+{6081, 2385, 5361},\r
+{6273, 1537, 5041},\r
+{6433, 1857, 4737},\r
+{6529, 1905, 4881},\r
+{6801, 1857, 4929},\r
+{6401, 1649, 5201},\r
+{6017, 1713, 4865},\r
+{6497, 1793, 5217},\r
+{5985, 1377, 4977},\r
+{6177, 1521, 5425},\r
+{6161, 1697, 5457},\r
+{5985, 1169, 5345},\r
+{6033, 1713, 5473},\r
+{6193, 1473, 5649},\r
+{5873, 1761, 5873},\r
+{6289, 1761, 5665},\r
+{5873, 1505, 5649},\r
+{5985, 1441, 5473},\r
+{6081, 1057, 5713},\r
+{6097, 1057, 5585},\r
+{6049, 1057, 5553},\r
+{5873, 1377, 5505},\r
+{6049, 1313, 5521},\r
+{6161, 1521, 5489},\r
+{6097, 1841, 5617},\r
+{6273, 2209, 5329},\r
+{6273, 2081, 5233},\r
+{6161, 1537, 5473},\r
+{6049, 2225, 4817},\r
+{6385, 2753, 4721},\r
+{6513, 2593, 4465},\r
+{6641, 2545, 4625},\r
+{6561, 2337, 4785},\r
+{6449, 2209, 4705},\r
+{6113, 1633, 4993},\r
+{6257, 2273, 5057},\r
+{6193, 1953, 5153},\r
+{6081, 1969, 5393},\r
+{5969, 1729, 5601},\r
+{5905, 1489, 5617},\r
+{6001, 1681, 5569},\r
+{5953, 1233, 5457},\r
+{5905, 1601, 5649},\r
+{6049, 1473, 5889},\r
+{5825, 1025, 6001},\r
+{6033, 1185, 5649},\r
+{6113, 1409, 5361},\r
+{6145, 1329, 5505},\r
+{6097, 1569, 5377},\r
+{6257, 1489, 5361},\r
+{6353, 1777, 5121},\r
+{6385, 2225, 4881},\r
+{6305, 2769, 5041},\r
+{6001, 2145, 4785},\r
+{6513, 1713, 5281},\r
+{6481, 641, 4769},\r
+{6657, 1297, 5137},\r
+{6609, 1425, 5025},\r
+{6529, 1185, 5201},\r
+{6369, 1233, 5057},\r
+{6465, 1441, 5041},\r
+{6401, 1473, 5137},\r
+{6417, 1473, 5025},\r
+{6337, 1633, 5073},\r
+{6305, 1521, 5313},\r
+{6273, 1313, 5425},\r
+{6129, 1089, 5601},\r
+{6273, 1185, 5329},\r
+{6225, 481, 5185},\r
+{6033, 193, 5153},\r
+{6161, 929, 5377},\r
+{6145, 385, 5553},\r
+{6065, -95, 5953},\r
+{5809, 33, 5969},\r
+{5857, 81, 5617},\r
+{6097, -15, 5601},\r
+{6001, 113, 5569},\r
+{6193, 465, 5633},\r
+{6065, 337, 5633},\r
+{6161, 513, 5649},\r
+{6257, 145, 5393},\r
+{6145, 497, 5505},\r
+{6305, 817, 5233},\r
+{6449, 769, 5281},\r
+{6385, 801, 5537},\r
+{6241, 1057, 5313},\r
+{6273, 977, 5121},\r
+{6529, 1137, 4897},\r
+{6609, 1329, 4849},\r
+{6801, 1649, 4897},\r
+{6561, 1713, 4961},\r
+{6545, 1537, 4817},\r
+{6545, 1457, 5153},\r
+{6401, 1553, 5057},\r
+{6513, 1169, 5137},\r
+{6513, 833, 5217},\r
+{6529, 1393, 4913},\r
+{6049, 1697, 5041},\r
+{5969, 2929, 5729},\r
+{6049, 2481, 6001},\r
+{5985, 2289, 5521},\r
+{5937, 1553, 5681},\r
+{5985, 1937, 5649},\r
+{6081, 1953, 5521},\r
+{6065, 1857, 5441},\r
+{5953, 1457, 5489},\r
+{5937, 1393, 5521},\r
+{5937, 1841, 5489},\r
+{6081, 1953, 5377},\r
+{5969, 1809, 5265},\r
+{6129, 2289, 5217},\r
+{6097, 1953, 5377},\r
+{6081, 2433, 5185},\r
+{6097, 2689, 5025},\r
+{6065, 2977, 5025},\r
+{6161, 2625, 5041},\r
+{6177, 2689, 5041},\r
+{6193, 2785, 5025},\r
+{5985, 2913, 4001},\r
+{7281, 2417, 4865},\r
+{6481, 3697, 5569},\r
+{6161, 2993, 4289},\r
+{6289, 2465, 4769},\r
+{6001, 3041, 5105},\r
+{6017, 2369, 5649},\r
+{6033, 2753, 5297},\r
+{5921, 2321, 5393},\r
+{5857, 2033, 5345},\r
+{5809, 1905, 5377},\r
+{5841, 1953, 5489},\r
+{5889, 2225, 5729},\r
+{5825, 1985, 5729},\r
+{6033, 1793, 5633},\r
+{6049, 1553, 5521},\r
+{5521, 1505, 5313},\r
+{6545, 705, 5585},\r
+{5553, 1905, 5713},\r
+{6049, 1633, 5633},\r
+{6369, 1073, 5121},\r
+{6193, 1313, 4961},\r
+{6273, 1873, 5201},\r
+{6481, 1681, 5841},\r
+{6113, 945, 5729},\r
+{6369, 1217, 4833},\r
+{6049, 1409, 5553},\r
+{6017, 1, 5745},\r
+{6209, 257, 5457},\r
+{6049, 929, 5681},\r
+{6001, 465, 5777},\r
+{5937, 257, 5921},\r
+{6001, 433, 5793},\r
+{6033, 433, 5601},\r
+{5937, 481, 5473},\r
+{6017, 529, 5585},\r
+{6049, 305, 5777},\r
+{6081, 97, 5649},\r
+{6065, 209, 5729},\r
+{5937, -15, 5649},\r
+{5857, 145, 5921},\r
+{5905, -143, 6065},\r
+{5681, -79, 6161},\r
+{5921, -239, 5649},\r
+{5761, -111, 5665},\r
+{5889, 113, 5697},\r
+{5841, -31, 5713},\r
+{5761, -399, 5809},\r
+{5489, -911, 5633},\r
+{5521, -767, 5585},\r
+{6433, 449, 5729},\r
+{6145, 33, 5793},\r
+{6385, 273, 5505},\r
+{6401, 961, 5057},\r
+{6385, 1505, 5185},\r
+{6273, 1377, 5409},\r
+{5985, 1841, 5201},\r
+{5857, 1825, 5489},\r
+{5889, 2209, 5777},\r
+{6177, 1601, 5473},\r
+{6113, 1969, 5601},\r
+{6033, 1953, 5473},\r
+{6193, 1857, 5601},\r
+{6225, 1697, 5617},\r
+{5985, 2353, 5601},\r
+{6481, 2161, 6273},\r
+{5713, 1585, 4849},\r
+{5921, 1377, 4849},\r
+{5825, 1009, 6209},\r
+{5089, 529, 5537},\r
+{5409, 129, 6113},\r
+{5761, 177, 5697},\r
+{6193, 289, 5249},\r
+{6193, 449, 5665},\r
+{6049, 657, 5425},\r
+{5905, 1329, 5153},\r
+{6145, 1409, 5265},\r
+{5329, 1137, 5857},\r
+{6001, 817, 5793},\r
+{6097, 769, 5697},\r
+{6513, 1393, 5297},\r
+{6433, 1729, 5265},\r
+{6321, 1537, 5169},\r
+{6305, 1329, 5249},\r
+{6097, 1185, 5265},\r
+{6161, 833, 5537},\r
+{5825, 641, 5537},\r
+{5889, 513, 5809},\r
+{6049, 401, 5969},\r
+{5697, 177, 6049},\r
+{5681, -63, 6081},\r
+{5601, -191, 6113},\r
+{5505, -863, 6289},\r
+{5329, -559, 6161},\r
+{5489, -911, 6001},\r
+{5441, -735, 6209},\r
+{5521, -959, 6225},\r
+{5841, -303, 5745},\r
+{5825, -367, 5921},\r
+{5825, -159, 5761},\r
+{6001, -47, 5681},\r
+{5969, 49, 5697},\r
+{6257, 529, 5345},\r
+{6241, 449, 5601},\r
+{5969, 769, 5617},\r
+{6145, 497, 5649},\r
+{5953, 513, 5537},\r
+{6097, 625, 5521},\r
+{6145, 993, 5313},\r
+{5857, 289, 5745},\r
+{6001, 737, 5697},\r
+{6065, 353, 5825},\r
+{5873, 641, 5905},\r
+{6193, 1137, 5569},\r
+{6145, 929, 5633},\r
+{6129, 1153, 5505},\r
+{6081, 913, 5921},\r
+{5873, 833, 5777},\r
+{5937, 193, 5809},\r
+{5953, 689, 5921},\r
+{5857, 145, 5809},\r
+{5873, 289, 5665},\r
+{5889, 241, 5633},\r
+{5937, 433, 5793},\r
+{6001, 225, 5841},\r
+{5921, 417, 5697},\r
+{6033, 1041, 5633},\r
+{6049, 1057, 5409},\r
+{5809, 1233, 5841},\r
+{5985, 1441, 5633},\r
+{6001, 1313, 5697},\r
+{6049, 1137, 5777},\r
+{6385, 1473, 5537},\r
+{6465, 1697, 4977},\r
+{6465, 1505, 4865},\r
+{6513, 1649, 5073},\r
+{6209, 1633, 4945},\r
+{6705, 1601, 5073},\r
+{6369, 1633, 5137},\r
+{6625, 1393, 5345},\r
+{6113, 1633, 4993},\r
+{6193, 1217, 5105},\r
+{6097, 1297, 5649},\r
+{5905, 1057, 5841},\r
+{5649, 897, 5937},\r
+{5553, 417, 6209},\r
+{5729, 945, 5825},\r
+{5921, 721, 5553},\r
+{5761, 593, 5297},\r
+{5345, 721, 5905},\r
+{5665, 641, 6113},\r
+{5697, 625, 5953},\r
+{5937, 705, 6209},\r
+{5745, 1121, 6177},\r
+{5953, 1105, 5329},\r
+{5889, 1393, 5233},\r
+{5745, 1217, 5937},\r
+{5857, 1441, 6033},\r
+{5889, 1585, 6065},\r
+{6833, 1921, 4721},\r
+{6801, 1969, 4417},\r
+{6737, 1905, 4561},\r
+{6657, 1921, 4785},\r
+{6305, 1953, 5089},\r
+{6065, 1937, 5281},\r
+{6177, 1985, 5377},\r
+{5985, 1905, 5553},\r
+{6049, 1601, 5713},\r
+{6001, 1313, 5713},\r
+{5793, 689, 5697},\r
+{5601, 561, 5937},\r
+{5505, 657, 6225},\r
+{5457, 433, 6449},\r
+{5521, 609, 6305},\r
+{5457, 353, 6193},\r
+{5361, -79, 6385},\r
+{5553, -223, 6017},\r
+{5521, -143, 6049},\r
+{5489, -15, 5905},\r
+{5505, 401, 6193},\r
+{5809, 689, 5793},\r
+{5857, 273, 5681},\r
+{5697, 817, 5841},\r
+{6177, 1137, 5441},\r
+{6065, 1089, 5633},\r
+{5969, 1313, 5745},\r
+{6161, 1697, 5521},\r
+{6241, 1761, 5329},\r
+{6385, 1729, 5233},\r
+{6353, 1617, 5137},\r
+{6289, 1441, 5281},\r
+{6145, 1601, 5425},\r
+{6177, 1553, 5425},\r
+{6065, 1393, 5553},\r
+{6161, 1873, 5393},\r
+{5889, 705, 5649},\r
+{5953, 881, 5777},\r
+{5745, 609, 5873},\r
+{5681, 1089, 6033},\r
+{5697, 721, 6033},\r
+{5505, 433, 6273},\r
+{5649, 769, 6033},\r
+{5809, 385, 5969},\r
+{5809, 305, 5665},\r
+{6049, 209, 5553},\r
+{5697, 337, 5985},\r
+{5809, 577, 5953},\r
+{5745, 721, 5921},\r
+{5697, 689, 5873},\r
+{5713, 961, 5665},\r
+{6049, 1105, 5649},\r
+{6145, 881, 5713},\r
+{6289, 961, 4961},\r
+{6465, 1425, 4689},\r
+{6625, 1969, 4817},\r
+{6241, 1425, 5265},\r
+{6257, 1425, 5313},\r
+{6001, 1793, 5377},\r
+{6113, 1697, 5585},\r
+{6097, 1905, 5393},\r
+{6145, 1249, 5537},\r
+{6177, 1601, 5489},\r
+{6049, 1073, 5553},\r
+{5889, 1521, 5681},\r
+{5857, 1169, 5873},\r
+{6001, 897, 5601},\r
+{6129, 1041, 5505},\r
+{6193, 881, 5377},\r
+{6289, 353, 5313},\r
+{5393, 1281, 6017},\r
+{5377, 1793, 5345},\r
+{5585, 1601, 6433},\r
+{6385, -463, 5361},\r
+{6449, 705, 5153},\r
+{6449, 577, 5425},\r
+{5969, 1329, 5505},\r
+{6529, -351, 5473},\r
+{6625, -79, 4689},\r
+{6657, 65, 4737},\r
+{6257, 721, 5249},\r
+{6129, 577, 5473},\r
+{6353, 161, 5441},\r
+{6465, 289, 5217},\r
+{6481, 465, 5105},\r
+{6465, 993, 4913},\r
+{6625, 673, 4865},\r
+{6465, 97, 5217},\r
+{6529, -463, 5601},\r
+{6513, 465, 5297},\r
+{6689, 17, 4721},\r
+{6401, -95, 4993},\r
+{6241, -319, 5729},\r
+{6193, -543, 5457},\r
+{6177, -495, 5361},\r
+{6273, -543, 5441},\r
+{6097, -879, 5201},\r
+{5393, -1551, 5457},\r
+{6113, -1183, 5361},\r
+{6225, -847, 5889},\r
+{6033, -879, 5809},\r
+{6289, -783, 5457},\r
+{6529, -239, 4865},\r
+{6545, 145, 5137},\r
+{6113, 593, 5249},\r
+{6609, 737, 5665},\r
+{5953, 209, 5569},\r
+{6241, 833, 5553},\r
+{6241, 769, 5489},\r
+{6353, 497, 5201},\r
+{5905, 1617, 4849},\r
+{6801, 865, 5553},\r
+{6145, -399, 5569},\r
+{6193, 545, 5649},\r
+{6113, 177, 5377},\r
+{6369, 481, 5409},\r
+{6241, 113, 5393},\r
+{5921, 161, 5633},\r
+{5729, 289, 6033},\r
+{5873, 449, 5969},\r
+{6001, 433, 6001},\r
+{5873, 417, 5761},\r
+{5985, -143, 5617},\r
+{6145, 209, 5489},\r
+{6097, 593, 5633},\r
+{5953, 577, 5713},\r
+{6017, 497, 5665},\r
+{6145, 769, 5665},\r
+{6289, 737, 5553},\r
+{6289, 785, 5409},\r
+{6337, 561, 5313},\r
+{6321, 881, 5121},\r
+{6337, 1457, 4561},\r
+{6273, 1313, 5057},\r
+{6321, 657, 4961},\r
+{6657, 1457, 4737},\r
+{6497, 1041, 4721},\r
+{6049, 1569, 6017},\r
+{5937, 945, 6017},\r
+{6161, 1441, 5601},\r
+{5985, 753, 5457},\r
+{6017, 737, 5537},\r
+{5905, 1137, 5745},\r
+{5761, -143, 4977},\r
+{5809, -127, 4097},\r
+{6145, 81, 5649},\r
+{5825, -191, 7201},\r
+{6017, -127, 6049},\r
+{6161, -383, 5633},\r
+{6337, 353, 5425},\r
+{6161, 225, 5665},\r
+{5937, 353, 5521},\r
+{6257, 465, 5137},\r
+{6417, 1041, 4785},\r
+{5873, 1937, 6305},\r
+{5905, 1297, 6593},\r
+{5713, 961, 6065},\r
+{5889, 1521, 5345},\r
+{5889, 2193, 5409},\r
+{5777, 1489, 6193},\r
+{6033, 1473, 5777},\r
+{5857, 1409, 5473},\r
+{6081, 1361, 5217},\r
+{6225, 1569, 4913},\r
+{5905, 1681, 5841},\r
+{5825, 1729, 5985},\r
+{5889, 1617, 5841},\r
+{6033, 1697, 5329},\r
+{6209, 977, 5425},\r
+{5857, 1521, 5921},\r
+{5841, 1761, 5697},\r
+{6097, 1665, 5553},\r
+{6097, 1457, 5473},\r
+{6033, 1393, 5473},\r
+{5937, 1857, 5649},\r
+{5905, 2001, 5649},\r
+{5809, 1873, 5633},\r
+{5825, 2017, 5761},\r
+{5985, 2081, 5713},\r
+{6049, 1825, 5185},\r
+{5953, 2145, 5217},\r
+{5937, 2305, 5489},\r
+{6033, 2433, 5873},\r
+{6177, 2161, 5441},\r
+{6001, 2113, 5073},\r
+{6177, 1889, 5185},\r
+{6097, 2017, 5441},\r
+{6033, 2033, 5537},\r
+{6033, 1633, 5553},\r
+{5921, 1521, 5761},\r
+{5889, 1633, 5729},\r
+{5873, 1825, 5553},\r
+{5937, 1601, 5361},\r
+{5937, 1745, 5569},\r
+{5937, 1601, 5761},\r
+{5809, 1329, 5649},\r
+{6049, 1313, 5441},\r
+{6001, 1569, 5441},\r
+{5969, 1329, 5633},\r
+{5921, 1521, 5697},\r
+{5873, 1841, 5489},\r
+{5665, 2161, 5233},\r
+{6177, 2193, 5217},\r
+{6113, 2321, 5521},\r
+{5985, 1857, 5393},\r
+{5841, 2753, 5217},\r
+{6097, 2513, 5441},\r
+{6049, 2497, 5297},\r
+{6081, 2129, 5153},\r
+{6065, 2433, 5201},\r
+{6129, 2449, 5297},\r
+{6033, 2113, 5361},\r
+{6049, 2209, 5249},\r
+{5953, 1921, 5425},\r
+{5889, 1921, 5633},\r
+{5745, 1617, 5745},\r
+{5649, 1889, 5889},\r
+{5649, 1809, 5777},\r
+{5729, 1217, 5857},\r
+{5633, 1521, 5953},\r
+{5585, 1489, 5969},\r
+{5713, 1425, 5793},\r
+{5697, 1393, 5729},\r
+{5889, 1905, 5713},\r
+{5809, 1969, 5665},\r
+{5777, 2065, 5569},\r
+{6033, 2081, 5169},\r
+{5905, 3217, 5393},\r
+{5681, 2865, 5457},\r
+{6033, 2977, 5345},\r
+{6033, 2881, 4865},\r
+{6017, 3121, 5041},\r
+{5921, 3089, 5121},\r
+{6017, 2689, 5217},\r
+{6113, 2673, 5201},\r
+{5937, 2913, 4961},\r
+{6001, 2449, 5185},\r
+{5921, 2401, 5377},\r
+{5953, 2353, 5409},\r
+{5777, 2577, 5521},\r
+{5585, 2129, 5873},\r
+{5553, 2081, 5889},\r
+{5601, 2177, 5729},\r
+{5729, 1825, 5697},\r
+{5745, 1569, 5713},\r
+{5761, 1345, 5889},\r
+{5617, 1953, 5777},\r
+{5649, 2065, 5729},\r
+{5713, 2065, 5649},\r
+{5633, 2209, 5537},\r
+{5745, 1921, 5857},\r
+{5809, 2849, 5745},\r
+{5793, 2577, 5521},\r
+{6017, 2689, 5041},\r
+{6049, 2929, 5025},\r
+{6001, 2369, 5409},\r
+{6065, 2593, 5025},\r
+{6065, 2289, 5345},\r
+{6033, 2705, 5185},\r
+{5953, 2673, 5249},\r
+{5889, 2289, 5393},\r
+{5921, 2417, 5521},\r
+{5809, 2193, 5665},\r
+{5889, 2161, 5521},\r
+{5889, 2145, 5441},\r
+{5969, 1873, 5505},\r
+{5969, 1713, 5537},\r
+{5649, 1713, 5777},\r
+{5713, 1521, 5793},\r
+{5793, 1489, 5857},\r
+{5729, 1345, 5841},\r
+{5841, 1681, 5857},\r
+{5777, 2097, 5617},\r
+{5729, 2193, 5537},\r
+{5905, 2353, 5777},\r
+{5697, 2273, 5697},\r
+{5745, 2321, 5569},\r
+{6129, 2945, 4241},\r
+{6033, 3089, 4129},\r
+{6657, 1537, 5345},\r
+{6529, 2641, 5969},\r
+{5809, 3153, 5137},\r
+{6145, 2337, 5281},\r
+{6385, 1553, 5025},\r
+{6305, 1041, 5121},\r
+{6177, 545, 5521},\r
+{5873, 609, 5777},\r
+{5697, 657, 6145},\r
+{5553, 273, 5713},\r
+{5217, -447, 6545},\r
+{5393, 273, 6129},\r
+{5873, 257, 5713},\r
+{5985, 385, 5905},\r
+{5841, 369, 5953},\r
+{5889, 529, 5905},\r
+{5681, 385, 5985},\r
+{5921, 913, 5793},\r
+{6033, 961, 5937},\r
+{5969, 801, 5649},\r
+{6001, 1297, 5873},\r
+{6017, 1409, 5937},\r
+{6001, 1121, 5809},\r
+{5953, 817, 5697},\r
+{6289, 1057, 5217},\r
+{6017, 1409, 5329},\r
+{6385, 929, 5297},\r
+{6049, -895, 5729},\r
+{5953, -479, 5569},\r
+{6529, 273, 5713},\r
+{6273, 17, 5185},\r
+{5889, -63, 4353},\r
+{5713, -207, 5537},\r
+{6257, 17, 5009},\r
+{5505, -527, 7665},\r
+{5073, -911, 6673},\r
+{5777, -303, 5825},\r
+{6065, 17, 5569},\r
+{5905, 401, 6081},\r
+{6193, 1281, 5761},\r
+{6049, 321, 5233},\r
+{5953, 1505, 5569},\r
+{5745, 1345, 5537},\r
+{6193, 769, 5937},\r
+{6193, 1233, 5569},\r
+{6129, 1457, 5457},\r
+{6337, 1681, 5457},\r
+{5777, 529, 5009},\r
+{5825, 2161, 5953},\r
+{5841, 2865, 6417},\r
+{6609, 2657, 5665},\r
+{6017, 2913, 4353},\r
+{6081, 3281, 4401},\r
+{5873, 3713, 5025},\r
+{5969, 1105, 5905},\r
+{5345, 1089, 6721},\r
+{5137, 977, 6129},\r
+{5441, 961, 6433},\r
+{5649, 257, 5585},\r
+{5905, -111, 5489},\r
+{6001, 1969, 6001},\r
+{5873, 1633, 5681},\r
+{6145, 1377, 5121},\r
+{6513, 1841, 4337},\r
+{6305, 3121, 5169},\r
+{6465, 2529, 4977},\r
+{6465, 2625, 4801},\r
+{6769, 2305, 4593},\r
+{6657, 1521, 4945},\r
+{6241, 1601, 4817},\r
+{6065, 1073, 5665},\r
+{5937, 1265, 5617},\r
+{6033, 1169, 5729},\r
+{5969, 1185, 5777},\r
+{5841, 929, 6049},\r
+{5585, 1169, 6177},\r
+{5809, 801, 5985},\r
+{5585, 337, 5953},\r
+{5441, -495, 6193},\r
+{5233, -223, 6209},\r
+{5329, -463, 6321},\r
+{5297, -351, 6113},\r
+{5569, -367, 6049},\r
+{5697, 113, 6097},\r
+{5889, 273, 5857},\r
+{6097, 849, 5569},\r
+{6097, 673, 5649},\r
+{6097, 1377, 5473},\r
+{6113, 993, 5521},\r
+{6065, 753, 5633},\r
+{5921, 993, 5841},\r
+{5825, 1137, 5921},\r
+{6129, 945, 5617},\r
+{6161, 1233, 5425},\r
+{6001, 1233, 5553},\r
+{5873, 881, 5841},\r
+{5825, 1297, 5825},\r
+{5649, 1329, 5985},\r
+{5649, 1761, 5937},\r
+{5569, 1233, 6049},\r
+{5489, 689, 6081},\r
+{5761, 945, 6017},\r
+{5793, 753, 5809},\r
+{5649, 561, 5857},\r
+{5761, 513, 5937},\r
+{5665, 817, 5953},\r
+{5889, 929, 5937},\r
+{5841, 1217, 5681},\r
+{5761, 977, 5761},\r
+{5745, 1393, 5809},\r
+{5825, 1217, 5809},\r
+{6097, 2081, 5521},\r
+{6097, 1681, 5457},\r
+{6001, 1585, 5537},\r
+{6177, 1793, 5345},\r
+{6241, 1841, 5297},\r
+{6257, 1601, 5329},\r
+{6289, 1345, 5409},\r
+{6017, 1121, 5505},\r
+{5873, 1009, 5633},\r
+{5857, 1025, 5665},\r
+{5489, 753, 6305},\r
+{5521, 273, 6113},\r
+{5633, 673, 6113},\r
+{5681, 769, 5985},\r
+{5729, 465, 6017},\r
+{5873, 545, 5857},\r
+{5777, 257, 5889},\r
+{5889, 833, 5857},\r
+{6065, 449, 5921},\r
+{5761, 577, 5953},\r
+{5809, 1105, 5729},\r
+{5633, 1393, 5937},\r
+{5889, 1601, 5649},\r
+{5953, 1649, 5441},\r
+{5985, 705, 5585},\r
+{5873, 1009, 5457},\r
+{6401, 1713, 5281},\r
+{6225, 2081, 5361},\r
+{6177, 2337, 5409},\r
+{6065, 2001, 5521},\r
+{6033, 1985, 5457},\r
+{5937, 1457, 5585},\r
+{5841, 1201, 5665},\r
+{5649, 1521, 5745},\r
+{5665, 1393, 5937},\r
+{5745, 1633, 5905},\r
+{5761, 865, 5761},\r
+{5953, 721, 5729},\r
+{5681, 545, 5857},\r
+{5521, 721, 6129},\r
+{5569, 529, 6225},\r
+{5617, 817, 5953},\r
+{5649, 1233, 5985},\r
+{5473, 945, 5905},\r
+{5825, 945, 5777},\r
+{5969, 1569, 5745},\r
+{6161, 2353, 5185},\r
+{6161, 2721, 4977},\r
+{6321, 2577, 5057},\r
+{6033, 2433, 5249},\r
+{6225, 2865, 4929},\r
+{6225, 2465, 5105},\r
+{6289, 2273, 5185},\r
+{6081, 2417, 5265},\r
+{6209, 2257, 5121},\r
+{6129, 2225, 5233},\r
+{5921, 1521, 5697},\r
+{5921, 1681, 5761},\r
+{5889, 1505, 5553},\r
+{5681, 1329, 6049},\r
+{5745, 1281, 6017},\r
+{5793, 1425, 5745},\r
+{5761, 1201, 5761},\r
+{5809, 961, 5825},\r
+{5905, 721, 5793},\r
+{5857, 1009, 5665},\r
+{5841, 593, 5889},\r
+{5889, 1681, 5809},\r
+{5921, 1377, 5665},\r
+{6033, 1441, 5361},\r
+{6017, 1601, 5425},\r
+{5825, 2225, 5633},\r
+{6241, 2321, 4865},\r
+{6465, 2273, 4929},\r
+{6257, 2529, 5057},\r
+{6193, 2673, 5009},\r
+{6225, 2625, 4833},\r
+{6289, 2129, 5217},\r
+{6097, 2209, 5297},\r
+{6113, 2065, 5345},\r
+{5905, 2353, 5393},\r
+{5969, 2177, 5505},\r
+{5857, 1697, 5633},\r
+{5697, 1729, 5809},\r
+{5633, 1793, 5841},\r
+{5601, 1569, 5953},\r
+{5665, 1681, 5969},\r
+{5681, 961, 6113},\r
+{5665, 1105, 6001},\r
+{5953, 1377, 5601},\r
+{5921, 577, 5825},\r
+{5713, 865, 5921},\r
+{6017, 1393, 5585},\r
+{6033, 1473, 5457},\r
+{6065, 1409, 5345},\r
+{6225, 1425, 5297},\r
+{6241, 1873, 5201},\r
+{6321, 1841, 5105},\r
+{5921, 2257, 4737},\r
+{5761, 2705, 5601},\r
+{5969, 2497, 5169},\r
+{6177, 2081, 5217},\r
+{6193, 2129, 5265},\r
+{6033, 2417, 5489},\r
+{5969, 1937, 5425},\r
+{6225, 1697, 5457},\r
+{6609, 977, 5185},\r
+{6305, -415, 5361},\r
+{6417, 913, 5313},\r
+{6209, -31, 5393},\r
+{6193, -511, 5569},\r
+{6337, -511, 5249},\r
+{6289, -207, 5073},\r
+{5729, -927, 6177},\r
+{5729, -991, 5985},\r
+{6017, -687, 5681},\r
+{6145, -367, 5377},\r
+{6273, -207, 5409},\r
+{6033, -575, 5633},\r
+{6193, -543, 5553},\r
+{6305, -271, 5521},\r
+{6273, -255, 5441},\r
+{6353, -335, 5681},\r
+{6321, 497, 5089},\r
+{6193, 705, 5425},\r
+{6369, 209, 5553},\r
+{6417, 337, 5265},\r
+{6577, 225, 5201},\r
+{6497, 1, 4689},\r
+{6497, -95, 5649},\r
+{6465, -735, 5345},\r
+{6849, 273, 5105},\r
+{6657, 97, 5153},\r
+{6385, 433, 5057},\r
+{6161, -63, 5681},\r
+{5393, 209, 4881},\r
+{5313, -591, 6641},\r
+{3681, -639, 5713},\r
+{5585, -2383, 7441},\r
+{5409, -447, 6241},\r
+{5313, -927, 6321},\r
+{5265, -399, 6369},\r
+{5601, -367, 6177},\r
+{5729, -287, 6113},\r
+{5809, -223, 5825},\r
+{5937, 561, 5457},\r
+{5793, 561, 5521},\r
+{6257, -383, 6001},\r
+{5793, 865, 5825},\r
+{6113, 881, 5857},\r
+{5969, 1265, 5377},\r
+{6017, 593, 5809},\r
+{5969, 593, 5745},\r
+{6049, 641, 5889},\r
+{5921, 1089, 5473},\r
+{5809, 609, 5569},\r
+{5745, 353, 5585},\r
+{5745, 369, 6257},\r
+{5713, -95, 6225},\r
+{5857, 385, 6129},\r
+{5281, 673, 5793},\r
+{5633, -559, 6401},\r
+{4961, -511, 6097},\r
+{5073, -783, 6145},\r
+{5185, -415, 6913},\r
+{4961, 241, 6401},\r
+{5281, 913, 6273},\r
+{5761, 657, 5569},\r
+{6081, 401, 5201},\r
+{5777, 2481, 5729},\r
+{6385, 753, 5537},\r
+{6145, 1569, 5265},\r
+{6465, 2049, 4929},\r
+{6161, 2017, 5169},\r
+{6417, 1953, 4961},\r
+{6241, 1553, 5297},\r
+{6097, 1617, 5617},\r
+{5937, 1953, 5345},\r
+{6193, 1649, 5425},\r
+{6177, 929, 5169},\r
+{6017, 945, 5441},\r
+{5985, 977, 5809},\r
+{5505, 609, 6385},\r
+{5265, 545, 6497},\r
+{5185, 385, 6753},\r
+{5665, 737, 5985},\r
+{5633, 225, 5617},\r
+{5761, 625, 5665},\r
+{5889, 1297, 5873},\r
+{6001, 1665, 5697},\r
+{6113, 1249, 5409},\r
+{6129, 1825, 4961},\r
+{6353, 2305, 5025},\r
+{6401, 2593, 5025},\r
+{6305, 2673, 4881},\r
+{6081, 2929, 4865},\r
+{6209, 2385, 5297},\r
+{6193, 2881, 5633},\r
+{6465, 2769, 6145},\r
+{5969, 4161, 6209},\r
+{6961, 1489, 2113},\r
+{6289, 2673, 5569},\r
+{6177, 1729, 5345},\r
+{6049, 1729, 5393},\r
+{6145, 1761, 5585},\r
+{6081, 785, 5649},\r
+{6113, 577, 5889},\r
+{5761, 177, 5617},\r
+{5329, 65, 5681},\r
+{5297, 1, 6305},\r
+{5825, -831, 5505},\r
+{6049, -623, 5201},\r
+{5649, 113, 5761},\r
+{5553, 321, 5713},\r
+{5665, 449, 6065},\r
+{5857, 1073, 6081},\r
+{6641, 673, 4961},\r
+{6545, 1073, 5345},\r
+{6177, 977, 5393},\r
+{6129, 1297, 5457},\r
+{6129, 817, 5649},\r
+{6081, 961, 5409},\r
+{5921, 1137, 5745},\r
+{5793, 993, 5921},\r
+{5873, 1073, 6001},\r
+{5873, 801, 5969},\r
+{6145, 1169, 5569},\r
+{6225, 1313, 5409},\r
+{6257, 897, 5457},\r
+{5617, -687, 5841},\r
+{5425, -191, 6225},\r
+{5489, -287, 6353},\r
+{5393, -703, 6241},\r
+{5569, -191, 5953},\r
+{5841, -751, 5617},\r
+{5185, -2287, 5969},\r
+{1905, -2751, 6785},\r
+{2049, -1903, 6993},\r
+{3505, -639, 7633},\r
+{4641, -1295, 7649},\r
+{4049, -2447, 7313},\r
+{4337, -1791, 7617},\r
+{6001, -319, 5953},\r
+{5857, -47, 5873},\r
+{5393, -863, 5153},\r
+{6001, -223, 5121},\r
+{5905, 577, 6161},\r
+{5825, -463, 5713},\r
+{5809, -15, 5633},\r
+{5761, -591, 5537},\r
+{5633, -207, 5841},\r
+{5649, -367, 6177},\r
+{6065, 225, 5569},\r
+{6113, 17, 5393},\r
+{6145, -287, 5473},\r
+{5713, 929, 5697},\r
+{4785, -319, 5921},\r
+{4465, -1951, 6753},\r
+{4705, -3103, 6465},\r
+{4465, -655, 7633},\r
+{4449, -927, 7297},\r
+{5009, -751, 6833},\r
+{5249, -1103, 5777},\r
+{5473, -1679, 5633},\r
+{5825, -543, 5953},\r
+{5777, 289, 6097},\r
+{5649, 625, 6129},\r
+{5985, 257, 5697},\r
+{6161, 385, 5313},\r
+{6161, 865, 5537},\r
+{6065, 1505, 5825},\r
+{6321, 257, 6177},\r
+{6209, 529, 5137},\r
+{6273, 513, 5009},\r
+{5969, 401, 5921},\r
+{5713, -95, 6321},\r
+{6801, 1729, 4705},\r
+{6241, 529, 5185},\r
+{6209, 257, 5729},\r
+{6145, 609, 5489},\r
+{6049, -335, 6113},\r
+{5921, -735, 5745},\r
+{6081, 657, 5921},\r
+{6321, -15, 5505},\r
+{6241, -735, 5105},\r
+{6097, 385, 5489},\r
+{6145, 1025, 5553},\r
+{6049, 1681, 5537},\r
+{5937, 353, 5729},\r
+{5745, 1585, 5841},\r
+{5841, 1825, 5857},\r
+{6017, 1409, 5553},\r
+{6769, 1313, 5329},\r
+{6097, 1889, 5633},\r
+{6225, 2129, 5313},\r
+{6177, 1361, 5233},\r
+{5777, 2433, 5313},\r
+{6129, 1729, 5857},\r
+{5825, 881, 5713},\r
+{5713, 625, 5713},\r
+{5601, 1265, 5889},\r
+{5665, 1105, 6145},\r
+{5585, 1009, 5985},\r
+{5681, 689, 6001},\r
+{5649, 1233, 6065},\r
+{5585, 273, 5905},\r
+{5425, 209, 5585},\r
+{6129, 225, 5537},\r
+{6513, 2369, 5921},\r
+{6737, 1025, 5681},\r
+{6065, 753, 5073},\r
+{6289, 1089, 4865},\r
+{6241, 1649, 5409},\r
+{6305, 641, 5377},\r
+{6209, 769, 5249},\r
+{6257, 1681, 5521},\r
+{6353, 1425, 5345},\r
+{6321, 1137, 5089},\r
+{6289, 881, 5105},\r
+{6737, 769, 5265},\r
+{6449, 1025, 5153},\r
+{6289, 401, 5153},\r
+{6449, 385, 5361},\r
+{6497, 481, 5217},\r
+{6577, 353, 5105},\r
+{6385, 257, 5361},\r
+{6289, 273, 5361},\r
+{6257, -143, 5441},\r
+{5825, -159, 6385},\r
+{4881, -303, 5505},\r
+{5425, -751, 7169},\r
+{5681, 273, 6961},\r
+{5585, 1, 5921},\r
+{6017, 65, 6017},\r
+{6145, 337, 5457},\r
+{6305, 1137, 5025},\r
+{6545, 1441, 4641},\r
+{5457, 305, 5025},\r
+{6209, -671, 6689},\r
+{6161, 849, 5825},\r
+{6081, 625, 5169},\r
+{5985, 65, 5457},\r
+{5569, 529, 6017},\r
+{5265, 321, 5953},\r
+{5441, 577, 6433},\r
+{5857, 289, 6017},\r
+{5697, 145, 5873},\r
+{5745, 1105, 5313},\r
+{6097, 1153, 5489},\r
+{5601, 481, 5921},\r
+{5409, 49, 6193},\r
+{4769, 241, 5921},\r
+{4273, 177, 6833},\r
+{5377, -47, 7265},\r
+{5521, -15, 6481},\r
+{5729, -703, 5889},\r
+{5905, -31, 5761},\r
+{5889, 577, 5585},\r
+{5905, 1297, 5137},\r
+{5777, 1537, 6305},\r
+{5441, 449, 6625},\r
+{5473, -319, 6465},\r
+{6193, 369, 5617},\r
+{6273, 881, 5393},\r
+{6321, 849, 5249},\r
+{6065, 737, 5329},\r
+{6177, 1025, 5649},\r
+{6113, 1617, 5617},\r
+{6065, 1217, 5329},\r
+{5489, -175, 6049},\r
+{5329, -303, 6193},\r
+{5521, -207, 6033},\r
+{5249, 161, 6161},\r
+{5169, -31, 6449},\r
+{4737, -207, 6241},\r
+{3729, -1407, 7473},\r
+{4369, -2463, 7729},\r
+{4305, -1775, 7345},\r
+{4353, -927, 6881},\r
+{4737, -1407, 6753},\r
+{4993, -863, 6001},\r
+{5409, -687, 5761},\r
+{6081, -367, 5905},\r
+{5585, 321, 5857},\r
+{5681, -671, 6225},\r
+{5569, 209, 5937},\r
+{5457, 49, 6321},\r
+{5281, -415, 6497},\r
+{5297, -255, 6545},\r
+{5425, -271, 6209},\r
+{5857, 417, 6225},\r
+{5809, 593, 5937},\r
+{5841, 497, 5697},\r
+{5809, 497, 5457},\r
+{5953, 481, 5601},\r
+{3889, 801, 5921},\r
+{5169, -1583, 6929},\r
+{3889, -1455, 7249},\r
+{3985, -1807, 7249},\r
+{3009, -2479, 7825},\r
+{2897, -1279, 8353},\r
+{2881, -1055, 7969},\r
+{3105, -1487, 7441},\r
+{3217, -1679, 7345},\r
+{3745, -1407, 7761},\r
+{6561, -1135, 2257},\r
+{6993, -3679, 1905},\r
+{5217, -1023, 6945},\r
+{5137, 305, 7137},\r
+{5857, -783, 5553},\r
+{5649, -1103, 6305},\r
+{5633, 337, 6561},\r
+{5745, -1407, 5617},\r
+{5873, -367, 5569},\r
+{6369, -831, 4913},\r
+{5521, -2015, 5217},\r
+{4833, -2847, 5409},\r
+{4097, -2559, 6817},\r
+{3985, -2479, 7025},\r
+{3185, -2911, 6673},\r
+{2817, -2991, 6817},\r
+{1153, -3359, 8033},\r
+{993, -2863, 8273},\r
+{1441, -3311, 7473},\r
+{1425, -3263, 7617},\r
+{2129, -2959, 7409},\r
+{3361, -2879, 6721},\r
+{3825, -2575, 6641},\r
+{4513, -2463, 5921},\r
+{4689, -1967, 6321},\r
+{4737, -2111, 6209},\r
+{5345, -239, 6385},\r
+{5633, -239, 5665},\r
+{4737, -1215, 5361},\r
+{4657, -911, 6305},\r
+{3633, -1695, 7025},\r
+{4625, -1263, 7345},\r
+{4593, -1823, 6865},\r
+{4689, -1711, 6001},\r
+{4641, -2159, 5793},\r
+{4465, -2095, 5953},\r
+{3905, -2191, 6785},\r
+{3841, -1519, 6817},\r
+{3457, -2031, 6833},\r
+{2833, -2735, 7345},\r
+{2641, -1535, 8193},\r
+{3057, -1583, 7873},\r
+{3249, -1871, 7537},\r
+{3345, -1487, 7473},\r
+{4321, -735, 6945},\r
+{4417, -1471, 6609},\r
+{4401, -2175, 6273},\r
+{5793, -1391, 5489},\r
+{5457, -975, 6033},\r
+{5537, -767, 6417},\r
+{5857, -591, 5985},\r
+{5729, -383, 6033},\r
+{5553, -799, 5921},\r
+{5553, -15, 6273},\r
+{5505, 369, 5761},\r
+{6033, -143, 5345},\r
+{5985, -879, 4481},\r
+{5857, -367, 5585},\r
+{5905, -399, 5985},\r
+{5873, 1, 5857},\r
+{5953, -223, 5985},\r
+{5825, 657, 5857},\r
+{5665, -207, 6193},\r
+{5361, -399, 6209},\r
+{5345, -623, 6257},\r
+{5121, -1263, 6273},\r
+{5553, -991, 6129},\r
+{5985, -767, 5601},\r
+{5841, -175, 5889},\r
+{6177, 449, 5729},\r
+{6433, 97, 5121},\r
+{6337, 481, 5409},\r
+{6641, 1649, 5057},\r
+{6481, 337, 5265},\r
+{6289, 817, 5297},\r
+{6673, 369, 4881},\r
+{6561, 513, 4961},\r
+{7025, 1121, 4209},\r
+{6129, -3407, 3809},\r
+{6641, -767, 8721},\r
+{5169, -1807, 7265},\r
+{2689, -2703, 6801},\r
+{1649, -735, 8769},\r
+{2625, -3599, 4865},\r
+{4945, -5679, 4913},\r
+{5457, -3967, 5233},\r
+{5489, -6543, 3473},\r
+{3105, -5199, 4049},\r
+{3169, -6127, 5345},\r
+{3521, -5727, 4833},\r
+{3841, -5087, 5105},\r
+{3889, -5663, 5169},\r
+{3793, -5695, 5089},\r
+{4161, -4959, 4625},\r
+{3825, -4015, 4609},\r
+{4529, -4527, 5665},\r
+{4769, -4879, 6209},\r
+{4529, -4191, 4817},\r
+{4545, -4095, 5409},\r
+{4657, -4111, 5233},\r
+{4849, -4255, 5601},\r
+{4913, -4431, 5585},\r
+{4833, -4287, 5345},\r
+{4897, -4879, 5793},\r
+{4673, -3903, 5649},\r
+{5521, -4511, 5537},\r
+{5201, -4943, 5217},\r
+{5601, -5439, 5953},\r
+{2977, -3487, 3777},\r
+{2609, -3775, 4929},\r
+{641, -1983, 6865},\r
+{-207, -3631, 3857},\r
+{-719, -543, 481},\r
+{13217, -4719, 12625},\r
+{4305, 1057, 11297},\r
+{6593, -655, 4145},\r
+{7249, 1937, 5025},\r
+{6513, 737, 4961},\r
+{6305, 1521, 4417},\r
+{6193, 689, 5585},\r
+{6289, 1057, 5121},\r
+{6193, 1489, 5393},\r
+{6273, 2081, 4977},\r
+{6257, 1265, 4849},\r
+{6433, 1201, 5041},\r
+{6529, 945, 5201},\r
+{6673, 1505, 4897},\r
+{6801, 881, 5233},\r
+{6753, 1121, 5073},\r
+{6561, 529, 4897},\r
+{6161, 145, 5441},\r
+{6209, 65, 5473},\r
+{6257, -175, 5313},\r
+{6225, -31, 5313},\r
+{6241, -623, 5569},\r
+{6353, -399, 5505},\r
+{6481, -703, 5169},\r
+{6545, -111, 4945},\r
+{6529, 353, 5057},\r
+{6401, 17, 5409},\r
+{6609, 353, 5169},\r
+{6545, 273, 5041},\r
+{6593, 593, 4945},\r
+{6641, 993, 4817},\r
+{6689, 481, 5073},\r
+{6689, 721, 5041},\r
+{6737, 625, 4929},\r
+{6545, 673, 4865},\r
+{6801, 625, 4849},\r
+{6833, 529, 4673},\r
+{6545, 241, 5073},\r
+{6481, 161, 5217},\r
+{6449, 65, 5313},\r
+{6369, 209, 5185},\r
+{6481, 209, 5153},\r
+{6497, 81, 5297},\r
+{6641, 321, 5201},\r
+{6689, 513, 4897},\r
+{6657, 753, 4881},\r
+{6737, 753, 5009},\r
+{6753, 849, 4977},\r
+{6513, 1025, 5025},\r
+{6449, 1281, 5185},\r
+{6385, 1137, 5249},\r
+{6465, 1441, 5025},\r
+{6385, 1265, 5009},\r
+{6625, 625, 5201},\r
+{6801, 929, 5009},\r
+{6625, 1009, 5057},\r
+{6593, 577, 4929},\r
+{6369, 369, 5425},\r
+{6273, -15, 5569},\r
+{6241, -111, 5441},\r
+{6305, 225, 5217},\r
+{6305, 81, 5249},\r
+{6193, -255, 5473},\r
+{6513, -399, 5265},\r
+{6145, -351, 5345},\r
+{6353, 225, 5409},\r
+{6417, 257, 5281},\r
+{6561, 241, 5169},\r
+{6369, 353, 5185},\r
+{6433, 481, 5345},\r
+{6513, 801, 5009},\r
+{6513, 721, 5105},\r
+{6449, 641, 5201},\r
+{6513, 801, 5025},\r
+{6673, 1041, 4865},\r
+{6737, 225, 5089},\r
+{6497, 33, 5089},\r
+{6497, 417, 5281},\r
+{6337, 113, 5249},\r
+{6385, -15, 5329},\r
+{6353, 33, 5105},\r
+{6321, -191, 5281},\r
+{6225, -511, 5537},\r
+{6401, -287, 5281},\r
+{5953, 177, 5425},\r
+{7201, 273, 4849},\r
+{6305, -447, 5473},\r
+{6545, 817, 5553},\r
+{6113, 1009, 5297},\r
+{6705, 833, 5329},\r
+{6561, 1761, 4881},\r
+{6657, 1793, 4913},\r
+{6417, 1281, 4993},\r
+{6641, 1281, 4945},\r
+{6929, 1409, 4785},\r
+{6817, 1457, 4673},\r
+{6561, 1649, 4577},\r
+{6465, 865, 5473},\r
+{6161, 1329, 5425},\r
+{6081, 1153, 5793},\r
+{6241, 833, 6241},\r
+{5697, 1329, 6065},\r
+{5745, 2593, 5169},\r
+{6353, 1969, 4721},\r
+{6289, 1409, 4929},\r
+{5969, 1841, 4817},\r
+{6385, 2433, 4913},\r
+{6305, 1857, 5505},\r
+{6305, 1793, 5217},\r
+{6401, 2257, 4705},\r
+{6449, 2321, 5089},\r
+{6321, 2273, 5249},\r
+{6561, 2209, 5249},\r
+{6401, 2161, 5729},\r
+{6161, 1601, 4945},\r
+{6273, 1921, 4641},\r
+{6257, 1585, 4241},\r
+{6097, 1409, 5217},\r
+{5953, 1425, 4993},\r
+{5905, 1505, 5889},\r
+{5905, 1697, 6305},\r
+{5745, 1761, 5745},\r
+{6273, 1329, 5297},\r
+{6529, 945, 5105},\r
+{5985, 1921, 5313},\r
+{6049, 2065, 5553},\r
+{6001, 1697, 5905},\r
+{6033, 1457, 5569},\r
+{6193, 1697, 5377},\r
+{6305, 2001, 5137},\r
+{6065, 1617, 5617},\r
+{6113, 1921, 5441},\r
+{6225, 1665, 5361},\r
+{6177, 1649, 5281},\r
+{6001, 1841, 5409},\r
+{6225, 1905, 5409},\r
+{6257, 1521, 5553},\r
+{6257, 1121, 5249},\r
+{6193, 1041, 5441},\r
+{6065, 1649, 5585},\r
+{6065, 1777, 5313},\r
+{6225, 1441, 5217},\r
+{6257, 1489, 5329},\r
+{6225, 1489, 5361},\r
+{6081, 2209, 5265},\r
+{6161, 2033, 5265},\r
+{6385, 2017, 5265},\r
+{6385, 1937, 4977},\r
+{6497, 2305, 4929},\r
+{6305, 1921, 5249},\r
+{6273, 1953, 5137},\r
+{6305, 1857, 5185},\r
+{6241, 1985, 5073},\r
+{6273, 1857, 5217},\r
+{6161, 1521, 5361},\r
+{5921, 1857, 5617},\r
+{6001, 1809, 5553},\r
+{6065, 1457, 5361},\r
+{6145, 1681, 5281},\r
+{5969, 1185, 5553},\r
+{5985, 1297, 5825},\r
+{6049, 1633, 5457},\r
+{6225, 1681, 5169},\r
+{6097, 1521, 5313},\r
+{5937, 1985, 5377},\r
+{5985, 2081, 5777},\r
+{6065, 1841, 5457},\r
+{6161, 2193, 5249},\r
+{6209, 2321, 5137},\r
+{6257, 2337, 5009},\r
+{6129, 2033, 5249},\r
+{6337, 2433, 5313},\r
+{6289, 2577, 5249},\r
+{6289, 2033, 5073},\r
+{6257, 1649, 5089},\r
+{5921, 2385, 5457},\r
+{5793, 1633, 5953},\r
+{6129, 1393, 5393},\r
+{6273, 1585, 5425},\r
+{5873, 1969, 5617},\r
+{6017, 1569, 5489},\r
+{6161, 1825, 5441},\r
+{6033, 1537, 5585},\r
+{5969, 1857, 5441},\r
+{5761, 2177, 5617},\r
+{6033, 2113, 5521},\r
+{5985, 2017, 5281},\r
+{6193, 2257, 5185},\r
+{6225, 2401, 5217},\r
+{6065, 2033, 5457},\r
+{6129, 2001, 5441},\r
+{6305, 2497, 5121},\r
+{6241, 2305, 5057},\r
+{6209, 1441, 5153},\r
+{5905, 1889, 5505},\r
+{5729, 1697, 5889},\r
+{6065, 1585, 5505},\r
+{5905, 1617, 5633},\r
+{5937, 1937, 5617},\r
+{5905, 1889, 5569},\r
+{6129, 1569, 5505},\r
+{6193, 1361, 5345},\r
+{6193, 1873, 5249},\r
+{6145, 2129, 5137},\r
+{6337, 2129, 5249},\r
+{6065, 1761, 5633},\r
+{6081, 2081, 5265},\r
+{5921, 2113, 5441},\r
+{5793, 2305, 5585},\r
+{6081, 2113, 5265},\r
+{6369, 2673, 6081},\r
+{6081, 2449, 4961},\r
+{6129, 1313, 5297},\r
+{5761, 1441, 5665},\r
+{6465, 1265, 5681},\r
+{6001, 625, 5377},\r
+{6097, 1089, 5537},\r
+{6065, 945, 5441},\r
+{6289, 129, 5361},\r
+{6481, 257, 5553},\r
+{6273, 577, 5217},\r
+{6289, 1505, 5281},\r
+{6273, 801, 5489},\r
+{6049, 977, 5553},\r
+{6161, 1297, 5409},\r
+{6449, 1553, 5201},\r
+{6353, 1393, 5425},\r
+{6433, 1521, 5313},\r
+{6385, 849, 5137},\r
+{6641, 1537, 4961},\r
+{6481, 993, 5073},\r
+{6289, 1009, 5249},\r
+{6097, 945, 5521},\r
+{6273, 545, 5329},\r
+{6033, 641, 5393},\r
+{6001, 801, 5697},\r
+{5809, 449, 6017},\r
+{6385, 465, 4849},\r
+{6513, 1041, 4737},\r
+{6625, 2129, 4785},\r
+{6721, 1473, 4881},\r
+{6625, 1265, 4833},\r
+{6545, 1873, 4753},\r
+{6801, 2145, 4593},\r
+{6625, 1697, 4929},\r
+{6449, 1489, 4801},\r
+{6481, 1393, 5329},\r
+{6673, 1265, 4961},\r
+{6641, 993, 4961},\r
+{6417, 1505, 4993},\r
+{6081, 785, 5393},\r
+{6017, 977, 5617},\r
+{6033, 769, 5633},\r
+{6401, 1057, 5409},\r
+{6257, 705, 5489},\r
+{6369, 689, 5361},\r
+{6385, 993, 5201},\r
+{6353, 1825, 4817},\r
+{6385, 1921, 4945},\r
+{6433, 1585, 5201},\r
+{6449, 1809, 4721},\r
+{6705, 2065, 4641},\r
+{6593, 2289, 4881},\r
+{6385, 1985, 4833},\r
+{6369, 1777, 5057},\r
+{6449, 1489, 5185},\r
+{6337, 1889, 5089},\r
+{6321, 1281, 5521},\r
+{5713, 1345, 5745},\r
+{6225, 1105, 5649},\r
+{6097, 1361, 5281},\r
+{6001, 1441, 5601},\r
+{5985, 2081, 5537},\r
+{6129, 1505, 5377},\r
+{5905, 1937, 5201},\r
+{5873, 993, 5633},\r
+{5905, 2161, 5457},\r
+{6417, 2305, 5169},\r
+{6529, 2177, 4465},\r
+{6641, 2641, 4161},\r
+{6353, 2673, 4897},\r
+{6305, 2849, 4929},\r
+{6401, 2593, 4929},\r
+{6353, 2193, 5153},\r
+{6513, 1521, 5489},\r
+{6353, 2049, 5313},\r
+{6129, 2161, 4833},\r
+{6001, 1425, 5201},\r
+{6273, 1201, 5185},\r
+{6289, 1361, 5345},\r
+{5873, 1233, 5681},\r
+{5889, 1153, 5873},\r
+{5857, 1361, 5665},\r
+{6881, 1873, 4801},\r
+{6593, 1825, 4993},\r
+{6273, 1585, 5105},\r
+{6497, 1713, 5137},\r
+{6273, 2161, 4945},\r
+{6513, 2001, 4961},\r
+{6369, 2049, 5057},\r
+{6257, 1985, 5153},\r
+{6289, 2017, 5137},\r
+{6417, 2177, 4993},\r
+{6369, 1489, 5153},\r
+{6257, 1457, 5265},\r
+{6193, 1681, 5233},\r
+{6145, 1649, 5457},\r
+{6001, 1585, 5393},\r
+{6129, 993, 5457},\r
+{6017, 1601, 5329},\r
+{5953, 1889, 5489},\r
+{6305, 1201, 5377},\r
+{6561, 1153, 5105},\r
+{6481, 1921, 4993},\r
+{6017, 2081, 5345},\r
+{6001, 1521, 5937},\r
+{5649, 2017, 6561},\r
+{5633, 2145, 5969},\r
+{6129, 2401, 4961},\r
+{6561, 1745, 4721},\r
+{5985, 1825, 5681},\r
+{6113, 2289, 5521},\r
+{6385, 1873, 5361},\r
+{6177, 1809, 5249},\r
+{6081, 1889, 5281},\r
+{6081, 1617, 5345},\r
+{6129, 1377, 5569},\r
+{6129, 1217, 5441},\r
+{5985, 1265, 5489},\r
+{6065, 1793, 5489},\r
+{6273, 1329, 5409},\r
+{6465, 1521, 5249},\r
+{6337, 1601, 5169},\r
+{6225, 1745, 5121},\r
+{6177, 1665, 5553},\r
+{5889, 2065, 5569},\r
+{6081, 1921, 5409},\r
+{6193, 2241, 5025},\r
+{6241, 2097, 5185},\r
+{5937, 2257, 5361},\r
+{6369, 1601, 5409},\r
+{6129, 2017, 5041},\r
+{6417, 1329, 5169},\r
+{5969, 1233, 5393},\r
+{5985, 1617, 6049},\r
+{6273, 1345, 5265},\r
+{6369, 1137, 5105},\r
+{5969, 1553, 5489},\r
+{6257, 1265, 5553},\r
+{5985, 1249, 5905},\r
+{6065, 1697, 5185},\r
+{6305, 2033, 4897},\r
+{6481, 1825, 5121},\r
+{6321, 1697, 5377},\r
+{6353, 1713, 5041},\r
+{6065, 2593, 5137},\r
+{6241, 1985, 5425},\r
+{6481, 2529, 4721},\r
+{6577, 1937, 4881},\r
+{6465, 1569, 5153},\r
+{6273, 1729, 5329},\r
+{6081, 2033, 5281},\r
+{6305, 1681, 5281},\r
+{6161, 1377, 5073},\r
+{5937, 1585, 5169},\r
+{5825, 2369, 6225},\r
+{6225, 1473, 5169},\r
+{6433, 1889, 4833},\r
+{6353, 1745, 4849},\r
+{6321, 2321, 4737},\r
+{6129, 2449, 5153},\r
+{6257, 2177, 4929},\r
+{6241, 2417, 4769},\r
+{6273, 2417, 5249},\r
+{6305, 2257, 5313},\r
+{6353, 1921, 5009},\r
+{6225, 2241, 5137},\r
+{6145, 1969, 5265},\r
+{6161, 2129, 5105},\r
+{6369, 2001, 5137},\r
+{6337, 1681, 5009},\r
+{6145, 1905, 5169},\r
+{6177, 2209, 5249},\r
+{6129, 1697, 5489},\r
+{6241, 1921, 5009},\r
+{6545, 1793, 4769},\r
+{6321, 2241, 5313},\r
+{6161, 2081, 5505},\r
+{6209, 2241, 5153},\r
+{6289, 2209, 4865},\r
+{6209, 2545, 5041},\r
+{6289, 2113, 5329},\r
+{6257, 2305, 5185},\r
+{6465, 2225, 5041},\r
+{6273, 1873, 5137},\r
+{6145, 1681, 5185},\r
+{6081, 1937, 5537},\r
+{6113, 1697, 5377},\r
+{6097, 1521, 5249},\r
+{6097, 1713, 5345},\r
+{5953, 1889, 5537},\r
+{6337, 1489, 5329},\r
+{6049, 1601, 5457},\r
+{6289, 1761, 5265},\r
+{6193, 2081, 5089},\r
+{6289, 2177, 5041},\r
+{6177, 2001, 5121},\r
+{6289, 1953, 5057},\r
+{6257, 2241, 5073},\r
+{6225, 2225, 5137},\r
+{6161, 2129, 5233},\r
+{6353, 1857, 4993},\r
+{6257, 1745, 5057},\r
+{6705, 1265, 6097},\r
+{5425, 2721, 5409},\r
+{6577, 1441, 4993},\r
+{6033, 1745, 5329},\r
+{6129, 1905, 5585},\r
+{5969, 1473, 5649},\r
+{6177, 1473, 5633},\r
+{6241, 865, 5201},\r
+{6321, 1121, 5153},\r
+{6609, 1345, 4865},\r
+{6353, 1057, 5297},\r
+{6305, 785, 5457},\r
+{6401, 1169, 5281},\r
+{6465, 1281, 4961},\r
+{6529, 1169, 4737},\r
+{6769, 1729, 4593},\r
+{7169, 1121, 4865},\r
+{6721, 1217, 4737},\r
+{6737, 897, 4865},\r
+{6497, 417, 5233},\r
+{6529, 609, 5025},\r
+{6625, 289, 5009},\r
+{6513, 369, 4977},\r
+{6129, 209, 5217},\r
+{6273, 177, 5377},\r
+{6481, 49, 5185},\r
+{6401, 353, 4993},\r
+{6833, 1057, 4833},\r
+{6593, 1953, 4625},\r
+{6289, 801, 4849},\r
+{6737, 897, 5473},\r
+{6257, 1665, 4833},\r
+{6577, 1921, 4881},\r
+{6465, 913, 5457},\r
+{6737, 689, 5121},\r
+{6513, 897, 4945},\r
+{6305, 1489, 5121},\r
+{6241, 1393, 5585},\r
+{6241, 513, 5569},\r
+{6241, 801, 5377},\r
+{6241, 1393, 5553},\r
+{6097, 977, 5553},\r
+{6177, 449, 5585},\r
+{6385, 1089, 5329},\r
+{6449, 1793, 4705},\r
+{6369, 2257, 4945},\r
+{6849, 1457, 5489},\r
+{6465, 1697, 4689},\r
+{6801, 2001, 4769},\r
+{6529, 2113, 4849},\r
+{6593, 1713, 4913},\r
+{6385, 1265, 5105},\r
+{6481, 1329, 5585},\r
+{5905, 1409, 5361},\r
+{6321, 1633, 5313},\r
+{6209, 689, 5473},\r
+{6113, 401, 5713},\r
+{6049, 1265, 5473},\r
+{5969, 1409, 5553},\r
+{6033, 1601, 5633},\r
+{6289, 1409, 5105},\r
+{6417, 1569, 4865},\r
+{6385, 1793, 5073},\r
+{6225, 2177, 5185},\r
+{6257, 1665, 5281},\r
+{6529, 1921, 4801},\r
+{6369, 2241, 5009},\r
+{6449, 1953, 5249},\r
+{6321, 2273, 5009},\r
+{6305, 2257, 4945},\r
+{6321, 1585, 5201},\r
+{6273, 1393, 5153},\r
+{6097, 1649, 5361},\r
+{6049, 1793, 5489},\r
+{6161, 1057, 5489},\r
+{6033, 1057, 5569},\r
+{5905, 1313, 5745},\r
+{6145, 1281, 5553},\r
+{6257, 1073, 5329},\r
+{6257, 2017, 5169},\r
+{6081, 2097, 5393},\r
+{6129, 1665, 5729},\r
+{6145, 1665, 5537},\r
+{6241, 2177, 5009},\r
+{6305, 2129, 5025},\r
+{6097, 2273, 5281},\r
+{6129, 2609, 5249},\r
+{6513, 1521, 5137},\r
+{6433, 1937, 4881},\r
+{6305, 1297, 5169},\r
+{6097, 1473, 5329},\r
+{5985, 1473, 5809},\r
+{6113, 1553, 5185},\r
+{6257, 1265, 5041},\r
+{6033, 1713, 5345},\r
+{6065, 1569, 5553},\r
+{6433, 1345, 5217},\r
+{6209, 2161, 4993},\r
+{6257, 2657, 4945},\r
+{6129, 2609, 5153},\r
+{5969, 2625, 5329},\r
+{6033, 2529, 4961},\r
+{6081, 3169, 4945},\r
+{6369, 2657, 4961},\r
+{6465, 2497, 4833},\r
+{6289, 1665, 5153},\r
+{6081, 1473, 5329},\r
+{5905, 2081, 5425},\r
+{5857, 1889, 5729},\r
+{6033, 1825, 5537},\r
+{6161, 1729, 5233},\r
+{6065, 1745, 5617},\r
+{6049, 1553, 5809},\r
+{6273, 2017, 5009},\r
+{6401, 1585, 5041},\r
+{6129, 1969, 5105},\r
+{6081, 2161, 5729},\r
+{6209, 2385, 5185},\r
+{6353, 1857, 4993},\r
+{6241, 2225, 4881},\r
+{6065, 2033, 5425},\r
+{6097, 2401, 5489},\r
+{6193, 1937, 5265},\r
+{6193, 1185, 5281},\r
+{5953, 2017, 5233},\r
+{6065, 1633, 5537},\r
+{6065, 1873, 5473},\r
+{6081, 1569, 5473},\r
+{6177, 1649, 5473},\r
+{6177, 1569, 5457},\r
+{6209, 1265, 5457},\r
+{6225, 1201, 5345},\r
+{6193, 1921, 5041},\r
+{6273, 2161, 5601},\r
+{6353, 1857, 5297},\r
+{6433, 1425, 4993},\r
+{6321, 1873, 4849},\r
+{6161, 2657, 5201},\r
+{6273, 2033, 5505},\r
+{6241, 1825, 5569},\r
+{6193, 913, 5025},\r
+{6097, 673, 4977},\r
+{6545, 1761, 5729},\r
+{6065, -111, 5601},\r
+{5969, 881, 5473},\r
+{6161, 1409, 5121},\r
+{5889, 737, 5585},\r
+{6097, 1713, 5057},\r
+{6561, 1377, 4449},\r
+{6673, 1697, 5313},\r
+{6433, 2689, 5345},\r
+{6401, 2049, 4737},\r
+{6081, 1777, 5153},\r
+{5969, 1793, 5969},\r
+{6081, 1553, 5745},\r
+{6081, 2049, 5201},\r
+{6257, 1313, 5201},\r
+{6433, 1297, 4801},\r
+{6337, 1009, 5249},\r
+{6081, 1121, 5601},\r
+{5713, 289, 6017},\r
+{5793, 417, 6113},\r
+{5729, 737, 6209},\r
+{6385, 913, 5345},\r
+{6049, 1121, 5457},\r
+{6177, 1553, 5153},\r
+{6321, 1713, 5217},\r
+{6113, 1921, 5665},\r
+{6177, 1489, 5185},\r
+{6225, 1825, 4993},\r
+{6241, 2097, 5265},\r
+{6369, 2241, 5201},\r
+{6369, 2289, 5009},\r
+{6385, 1761, 5409},\r
+{6289, 2049, 4977},\r
+{6129, 1553, 4657},\r
+{5905, 609, 5697},\r
+{5713, 785, 5905},\r
+{6193, 1073, 5553},\r
+{5761, 1233, 5873},\r
+{6129, 737, 5697},\r
+{6321, 1297, 5089},\r
+{6561, 1297, 4865},\r
+{6337, 1825, 5649},\r
+{6161, 1793, 5489},\r
+{6177, 1585, 5217},\r
+{6113, 1729, 5217},\r
+{6353, 2465, 5041},\r
+{6353, 2513, 4929},\r
+{6193, 1729, 5345},\r
+{6161, 1633, 5217},\r
+{6097, 1473, 5345},\r
+{6081, 2129, 5377},\r
+{6145, 2001, 5281},\r
+{5825, 1473, 5457},\r
+{6241, 1393, 5265},\r
+{6241, 1937, 5073},\r
+{6225, 1425, 5585},\r
+{6273, 1873, 5281},\r
+{6369, 1761, 5025},\r
+{6289, 1793, 5281},\r
+{5937, 1809, 5537},\r
+{5905, 2433, 5617},\r
+{6209, 2001, 5297},\r
+{6097, 1953, 5425},\r
+{6017, 2305, 5441},\r
+{6257, 2385, 5297},\r
+{5921, 1713, 5505},\r
+{6081, 1937, 5505},\r
+{6001, 2193, 5457},\r
+{5745, 2177, 5777},\r
+{5505, 993, 5393},\r
+{5089, 2737, 6161},\r
+{6737, 1953, 5041},\r
+{6753, 465, 5457},\r
+{6209, 961, 4657},\r
+{6849, 1057, 4817},\r
+{6641, 2289, 4801},\r
+{6593, 1617, 4785},\r
+{6401, 673, 5585},\r
+{6641, 1841, 4769},\r
+{6593, 1585, 4625},\r
+{6625, 1249, 4929},\r
+{6561, 1329, 5169},\r
+{6609, 1233, 4609},\r
+{6609, 1393, 4785},\r
+{6657, 833, 4913},\r
+{6241, 721, 5505},\r
+{6561, 593, 5473},\r
+{6561, 625, 4961},\r
+{6241, 897, 5313},\r
+{6481, 513, 5537},\r
+{6353, 369, 5313},\r
+{6257, 497, 5153},\r
+{6529, 1297, 4849},\r
+{6673, 1153, 5041},\r
+{6465, 801, 5393},\r
+{6609, 1057, 4961},\r
+{6641, 1473, 4977},\r
+{6241, 2113, 4657},\r
+{6257, 1873, 4977},\r
+{6689, 1121, 5185},\r
+{6673, 1249, 4769},\r
+{6641, 1393, 4849},\r
+{6497, 849, 5137},\r
+{6401, 977, 5505},\r
+{6289, 1249, 5457},\r
+{6305, 1185, 5249},\r
+{6081, 1633, 5457},\r
+{6161, 1361, 5569},\r
+{6353, 1633, 5009},\r
+{6545, 1601, 4961},\r
+{6337, 2081, 4865},\r
+{6401, 1601, 5169},\r
+{6385, 1569, 5185},\r
+{6577, 2737, 4769},\r
+{6321, 2001, 5009},\r
+{6321, 2529, 4897},\r
+{6337, 2161, 5121},\r
+{6305, 1937, 5233},\r
+{6193, 1409, 5393},\r
+{5665, 1777, 5585},\r
+{5889, 1457, 5857},\r
+{6097, 1505, 5489},\r
+{6065, 1585, 5425},\r
+{5953, 1697, 5473},\r
+{5921, 1361, 5777},\r
+{6049, 1569, 5377},\r
+{6369, 2049, 4929},\r
+{6561, 1985, 4977},\r
+{6001, 2481, 5185},\r
+{6145, 2065, 5217},\r
+{6273, 2161, 4881},\r
+{6177, 2305, 5137},\r
+{6177, 2465, 5409},\r
+{6193, 2433, 5345},\r
+{6337, 1985, 5057},\r
+{6065, 1745, 5265},\r
+{5873, 1665, 5649},\r
+{5649, 2049, 5905},\r
+{6209, 1761, 5233},\r
+{6145, 1297, 5249},\r
+{5921, 1601, 5617},\r
+{6081, 1873, 5729},\r
+{6257, 1825, 5137},\r
+{6385, 1857, 4801},\r
+{6033, 2545, 5537},\r
+{6257, 2465, 5377},\r
+{6289, 2033, 5137},\r
+{6465, 1905, 4833},\r
+{6593, 2353, 4737},\r
+{6289, 2289, 4961},\r
+{6353, 2273, 4785},\r
+{6417, 1537, 5137},\r
+{6257, 1617, 5137},\r
+{6209, 1345, 5393},\r
+{6001, 1697, 5249},\r
+{6241, 1505, 5377},\r
+{6001, 1281, 5425},\r
+{6017, 1137, 5537},\r
+{5793, 1377, 5921},\r
+{5777, 1185, 6001},\r
+{6257, 1409, 5169},\r
+{6273, 1793, 5201},\r
+{5889, 1873, 5521},\r
+{5809, 2161, 5425},\r
+{5921, 2065, 5409},\r
+{6097, 1841, 4993},\r
+{6305, 1761, 5473},\r
+{6209, 1857, 5649},\r
+{6449, 1393, 5217},\r
+{6209, 1121, 5361},\r
+{6273, 1041, 5361},\r
+{6065, 1633, 5345},\r
+{6321, 1297, 5777},\r
+{6353, 705, 5521},\r
+{6081, 865, 5297},\r
+{6017, 1009, 5649},\r
+{6081, 1025, 5569},\r
+{6289, 545, 5537},\r
+{6209, 1105, 5153},\r
+{6449, 1217, 5233},\r
+{6273, 1521, 5233},\r
+{6465, 1105, 5233},\r
+{6497, 1137, 4945},\r
+{6401, 1457, 5041},\r
+{6529, 1713, 5329},\r
+{6353, 1137, 5409},\r
+{6561, 1553, 5041},\r
+{6481, 1377, 5009},\r
+{6481, 1297, 5073},\r
+{6449, 721, 5345},\r
+{6305, 881, 5393},\r
+{6065, 369, 5649},\r
+{5761, 529, 5825},\r
+{5777, 721, 6129},\r
+{5585, 1217, 6081},\r
+{6449, 961, 5361},\r
+{6337, 993, 5137},\r
+{6305, 1329, 5201},\r
+{6209, 2113, 5057},\r
+{6353, 1793, 5361},\r
+{6721, 1297, 5393},\r
+{6497, 1841, 4817},\r
+{6177, 2193, 5073},\r
+{6225, 2017, 5377},\r
+{6145, 2049, 5473},\r
+{6497, 1505, 5105},\r
+{6001, 2225, 4817},\r
+{6273, 1649, 5217},\r
+{5969, 1921, 5569},\r
+{6161, 1521, 5457},\r
+{6193, 1249, 5393},\r
+{6033, 1169, 5649},\r
+{5921, 1537, 5665},\r
+{6129, 1409, 5585},\r
+{6113, 1633, 5297},\r
+{6273, 1457, 5121},\r
+{6289, 2049, 5281},\r
+{6145, 1969, 5569},\r
+{6161, 1761, 5249},\r
+{6273, 1761, 5009},\r
+{6465, 2273, 5025},\r
+{6433, 2081, 4961},\r
+{6449, 1793, 5153},\r
+{6449, 1905, 5201},\r
+{6481, 1905, 5009},\r
+{6385, 1761, 4817},\r
+{6401, 1473, 4977},\r
+{6081, 1713, 5217},\r
+{6113, 1505, 5217},\r
+{6145, 1489, 5201},\r
+{6129, 1457, 5425},\r
+{6113, 1761, 5585},\r
+{6321, 1521, 5169},\r
+{6561, 1537, 5025},\r
+{6417, 1777, 4945},\r
+{6193, 2289, 5153},\r
+{6273, 1761, 5345},\r
+{6001, 2017, 5185},\r
+{6465, 2305, 4977},\r
+{6321, 2401, 4865},\r
+{6433, 1777, 5185},\r
+{6353, 1633, 5281},\r
+{6497, 2289, 5425},\r
+{6337, 1473, 5217},\r
+{6337, 1649, 5041},\r
+{6161, 2097, 5441},\r
+{6017, 1905, 5425},\r
+{6209, 1569, 5249},\r
+{6193, 1425, 5217},\r
+{5937, 1713, 5313},\r
+{5889, 1953, 5777},\r
+{6113, 1457, 5985},\r
+{6433, 1697, 5137},\r
+{6337, 2241, 5137},\r
+{6097, 2289, 5089},\r
+{6161, 1633, 5521},\r
+{6257, 1889, 5185},\r
+{6353, 2161, 4929},\r
+{6305, 1969, 5249},\r
+{6305, 2033, 5281},\r
+{6353, 2225, 5137},\r
+{6401, 1841, 5041},\r
+{6401, 1569, 5169},\r
+{6097, 1889, 5377},\r
+{6001, 1697, 5361},\r
+{6033, 1713, 5217},\r
+{6113, 1425, 5505},\r
+{6017, 1649, 5649},\r
+{6177, 1441, 5409},\r
+{6481, 1425, 5153},\r
+{6385, 1761, 4961},\r
+{6081, 1953, 5217},\r
+{5777, 2097, 5553},\r
+{6609, 961, 5761},\r
+{6353, 2017, 4769},\r
+{6449, 2225, 5057},\r
+{6385, 1505, 5537},\r
+{6081, 1969, 5281},\r
+{6161, 497, 5553},\r
+{6449, 1121, 5329},\r
+{6177, 897, 5313},\r
+{6129, 753, 4929},\r
+{6273, -79, 5425},\r
+{6129, 305, 5505},\r
+{6033, -127, 5633},\r
+{6049, -223, 5777},\r
+{6289, 273, 5617},\r
+{6305, 113, 5377},\r
+{6433, 657, 5121},\r
+{6353, 209, 5361},\r
+{6209, 65, 5793},\r
+{6241, 593, 5345},\r
+{6561, 753, 5153},\r
+{6433, 673, 5233},\r
+{6705, 737, 5329},\r
+{6465, -335, 5345},\r
+{6161, 257, 4945},\r
+{6369, 145, 5073},\r
+{6225, 337, 5793},\r
+{5969, -463, 5697},\r
+{6065, 49, 5505},\r
+{6657, -847, 6177},\r
+{5777, 497, 5233},\r
+{6401, 545, 5649},\r
+{6449, 1057, 5137},\r
+{6561, 993, 5073},\r
+{6481, 1537, 4817},\r
+{6881, 1137, 4993},\r
+{6321, 1537, 5121},\r
+{6433, 1729, 4929},\r
+{6561, 1297, 5457},\r
+{6449, 1217, 5265},\r
+{6177, 1921, 5121},\r
+{6305, 1633, 5201},\r
+{6017, 1217, 5185},\r
+{6353, 785, 5441},\r
+{6321, 737, 5489},\r
+{6129, 977, 5201},\r
+{6193, 1329, 5137},\r
+{6257, 801, 5825},\r
+{6177, 1169, 5377},\r
+{6801, 1361, 4753},\r
+{6769, 1777, 4657},\r
+{6257, 2305, 4625},\r
+{6417, 1889, 4545},\r
+{6641, 1937, 4865},\r
+{6545, 2193, 5105},\r
+{6433, 2065, 5185},\r
+{6769, 1937, 5105},\r
+{6577, 1761, 5393},\r
+{6241, 2337, 5105},\r
+{6257, 1825, 5201},\r
+{6017, 1681, 5153},\r
+{5921, 1009, 5425},\r
+{5985, 1121, 5457},\r
+{5825, 1185, 5489},\r
+{6113, 1105, 5777},\r
+{6193, 1457, 5537},\r
+{6337, 1697, 4625},\r
+{6321, 1985, 4721},\r
+{6657, 2465, 5585},\r
+{6433, 2241, 4833},\r
+{6561, 2577, 4401},\r
+{6481, 2577, 4545},\r
+{6289, 2673, 4897},\r
+{6401, 2193, 5169},\r
+{6385, 2257, 5169},\r
+{6145, 2241, 4881},\r
+{5905, 1889, 5409},\r
+{5905, 1329, 5601},\r
+{6257, 1537, 5345},\r
+{6081, 1281, 5217},\r
+{6065, 1361, 5265},\r
+{5841, 1345, 5489},\r
+{5681, 1409, 5761},\r
+{6353, 1601, 5121},\r
+{6449, 1761, 5265},\r
+{6353, 1985, 5233},\r
+{6273, 2129, 5297},\r
+{6273, 1985, 5233},\r
+{6161, 1969, 4961},\r
+{6129, 2209, 5201},\r
+{6129, 2161, 5249},\r
+{6097, 2241, 5233},\r
+{6129, 2465, 5217},\r
+{6193, 1905, 5361},\r
+{6097, 1697, 5249},\r
+{6017, 1585, 5521},\r
+{5697, 1697, 5761},\r
+{5729, 1793, 5969},\r
+{5761, 1729, 5521},\r
+{5857, 1521, 6097},\r
+{5873, 2017, 6033},\r
+{5985, 1809, 5537},\r
+{6081, 1985, 5313},\r
+{6049, 2241, 5617},\r
+{5937, 3393, 6065},\r
+{6241, 3681, 4721},\r
+{6481, 3569, 4673},\r
+{6577, 3521, 4433},\r
+{6145, 2881, 3889},\r
+{6257, 2817, 5201},\r
+{6337, 2769, 5777},\r
+{6289, 2577, 5777},\r
+{6177, 1985, 5793},\r
+{5969, 2529, 4321},\r
+{5921, 1649, 4865},\r
+{6033, 1825, 5089},\r
+{6033, 1537, 5681},\r
+{6161, 929, 5841},\r
+{6001, 1041, 4945},\r
+{6385, 1201, 5153},\r
+{5889, 1441, 5393},\r
+{6113, 1633, 5297},\r
+{6129, 1457, 5313},\r
+{6001, 2145, 5537},\r
+{6161, 1809, 6065},\r
+{6161, 1745, 5105},\r
+{6481, 1969, 5073},\r
+{6481, 2113, 5073},\r
+{6209, 1953, 5393},\r
+{6113, 1889, 5601},\r
+{6273, 2033, 5073},\r
+{6177, 1681, 5201},\r
+{6033, 1649, 5489},\r
+{6001, 2145, 5297},\r
+{5809, 1505, 5329},\r
+{5713, 1249, 5873},\r
+{5921, 1249, 5905},\r
+{5745, 1057, 6049},\r
+{5873, 1377, 5729},\r
+{6289, 1089, 5265},\r
+{5953, 1713, 5377},\r
+{5793, 1425, 5953},\r
+{5985, 1169, 5681},\r
+{6049, 1185, 5489},\r
+{6305, 1713, 4945},\r
+{6225, 1905, 5681},\r
+{6161, 1457, 5665},\r
+{6177, 1233, 5409},\r
+{6369, 1153, 5169},\r
+{6097, 1345, 5345},\r
+{6017, 1073, 5921},\r
+{5841, 1201, 5729},\r
+{6081, 1105, 5377},\r
+{5969, 1217, 5729},\r
+{5809, 1185, 5921},\r
+{5857, 929, 5697},\r
+{6065, 2097, 5249},\r
+{6033, 2033, 5281},\r
+{6001, 2449, 5441},\r
+{6193, 1681, 5441},\r
+{6177, 1937, 5201},\r
+{6049, 1969, 5393},\r
+{6033, 1713, 5729},\r
+{6001, 2209, 5361},\r
+{6161, 1649, 5345},\r
+{6097, 1361, 5505},\r
+{5729, 1361, 5745},\r
+{5793, 1857, 5777},\r
+{6033, 1217, 5745},\r
+{5889, 1233, 5553},\r
+{5969, 1169, 5553},\r
+{6017, 1185, 5617},\r
+{5985, 1265, 5681},\r
+{6001, 1233, 5569},\r
+{6033, 1137, 5473},\r
+{5985, 2033, 5313},\r
+{5969, 1537, 5569},\r
+{6145, 1473, 5233},\r
+{6209, 1713, 5201},\r
+{6033, 1985, 5537},\r
+{6097, 1777, 5649},\r
+{6209, 1489, 5457},\r
+{6033, 1217, 5489},\r
+{6065, 1569, 5505},\r
+{6081, 1713, 5457},\r
+{6209, 1425, 5441},\r
+{6209, 945, 5393},\r
+{6145, 1169, 5489},\r
+{5937, 1569, 5569},\r
+{6145, 1441, 5569},\r
+{6225, 1569, 5265},\r
+{6353, 1441, 5025},\r
+{6209, 1937, 5521},\r
+{6177, 1873, 5569},\r
+{6145, 1953, 5137},\r
+{6337, 2145, 4897},\r
+{6337, 2081, 5137},\r
+{6225, 1857, 5345},\r
+{6321, 2017, 5281},\r
+{6209, 1633, 5249},\r
+{6113, 1745, 5377},\r
+{6177, 1809, 5297},\r
+{5905, 1169, 5617},\r
+{5825, 1505, 5665},\r
+{6001, 1601, 5617},\r
+{6033, 1969, 5505},\r
+{6113, 1153, 5585},\r
+{6257, 1793, 5041},\r
+{6225, 1617, 5137},\r
+{5937, 2689, 5121},\r
+{5521, 1345, 6049},\r
+{6609, 1329, 5889},\r
+{6577, 1729, 5457},\r
+{5617, 2225, 5537},\r
+{6753, 1521, 5489},\r
+{6433, 1073, 5569},\r
+{6497, 1617, 4961},\r
+{6097, 1329, 4785},\r
+{6049, 481, 5857},\r
+{6017, -79, 5521},\r
+{6161, 689, 5313},\r
+{6401, 81, 5393},\r
+{6241, 65, 5617},\r
+{6417, 353, 5441},\r
+{6321, 305, 5169},\r
+{6433, 577, 5057},\r
+{6241, 593, 5361},\r
+{6225, 465, 5569},\r
+{6241, 497, 5377},\r
+{6129, 497, 5553},\r
+{6177, 241, 5617},\r
+{6353, 1185, 5489},\r
+{6545, 209, 5537},\r
+{6289, -255, 5313},\r
+{6241, -191, 5409},\r
+{5889, -79, 6145},\r
+{6385, -143, 5441},\r
+{6273, 161, 5441},\r
+{6209, 257, 5393},\r
+{5873, -271, 6049},\r
+{6353, -367, 5585},\r
+{6385, 33, 5633},\r
+{6513, 1329, 4961},\r
+{6465, 1105, 4993},\r
+{6545, 993, 5105},\r
+{6369, 737, 5233},\r
+{6513, 1889, 5233},\r
+{6209, 1505, 5297},\r
+{6529, 817, 5377},\r
+{6625, 1009, 5441},\r
+{6433, 1105, 4881},\r
+{6273, 1569, 4689},\r
+{6817, 1761, 5137},\r
+{5905, 849, 5489},\r
+{6241, 1505, 5233},\r
+{6081, 1921, 5345},\r
+{6257, 1089, 5857},\r
+{5969, 401, 5617},\r
+{5921, 1249, 5361},\r
+{6209, 2145, 5041},\r
+{6337, 1825, 5521},\r
+{6177, 1489, 5665},\r
+{6113, 1425, 5313},\r
+{6289, 2289, 4817},\r
+{6177, 1233, 5521},\r
+{6081, 1921, 5425},\r
+{6417, 913, 5665},\r
+{6145, 1073, 5345},\r
+{6049, 1313, 5329},\r
+{5697, 1089, 6209},\r
+{5777, 1073, 5969},\r
+{5825, 849, 5697},\r
+{5985, 1345, 5649},\r
+{5729, 1505, 5729},\r
+{5905, 1185, 5841},\r
+{5937, 1185, 5585},\r
+{5809, 1297, 5505},\r
+{5681, 1761, 5745},\r
+{5969, 1569, 5777},\r
+{5937, 1393, 5649},\r
+{6225, 1729, 5281},\r
+{6241, 1697, 5281},\r
+{5953, 1505, 5633},\r
+{6049, 1905, 5585},\r
+{6273, 1409, 5345},\r
+{6257, 1073, 5473},\r
+{5905, 609, 5505},\r
+{5729, 497, 5665},\r
+{5665, 561, 6145},\r
+{5713, 257, 5793},\r
+{5409, 113, 6145},\r
+{5345, 913, 6401},\r
+{5825, 753, 5921},\r
+{6225, 961, 5585},\r
+{6241, 481, 5361},\r
+{5569, 593, 6065},\r
+{6049, 225, 6273},\r
+{5713, 673, 6321},\r
+{5825, 721, 5793},\r
+{5969, 977, 5441},\r
+{5889, 881, 5841},\r
+{5857, 849, 6017},\r
+{5985, 497, 5809},\r
+{5729, 865, 5873},\r
+{5841, 1089, 5745},\r
+{5649, 657, 6241},\r
+{5617, 401, 6081},\r
+{5569, 497, 6033},\r
+{5617, 481, 5905},\r
+{5537, 513, 6337},\r
+{5745, 449, 5969},\r
+{5873, 641, 5713},\r
+{6001, 785, 5473},\r
+{6001, 1265, 5601},\r
+{5969, 1041, 5809},\r
+{5969, 753, 5601},\r
+{5921, 1297, 5505},\r
+{5841, 1441, 5713},\r
+{5937, 1409, 5905},\r
+{5873, 1297, 5857},\r
+{6065, 1361, 5537},\r
+{6081, 1041, 5473},\r
+{5777, 1121, 5825},\r
+{5809, 865, 6161},\r
+{5681, 865, 5953},\r
+{5761, 529, 5873},\r
+{5681, 1041, 6337},\r
+{5665, 705, 6241},\r
+{5745, 657, 5969},\r
+{6001, 929, 5457},\r
+{6001, 1153, 5457},\r
+{6033, 1521, 5569},\r
+{5985, 817, 5713},\r
+{6017, 1329, 5377},\r
+{6161, 1809, 5361},\r
+{6049, 1633, 5569},\r
+{6001, 1345, 5601},\r
+{5953, 1313, 5633},\r
+{6049, 1473, 5569},\r
+{6001, 1105, 5569},\r
+{5617, 833, 5793},\r
+{5889, 961, 5905},\r
+{5953, 881, 5633},\r
+{5889, 673, 5617},\r
+{5793, 753, 5809},\r
+{5809, 1073, 5969},\r
+{6177, 1137, 5425},\r
+{6209, 1009, 5361},\r
+{6049, 1025, 5473},\r
+{6081, 1297, 5617},\r
+{5889, 977, 5809},\r
+{6033, 1281, 5505},\r
+{5953, 1505, 5489},\r
+{6097, 1793, 5793},\r
+{6001, 1457, 5825},\r
+{6049, 1521, 5537},\r
+{5985, 1281, 5473},\r
+{5745, 1009, 5841},\r
+{5521, 945, 6417},\r
+{6049, 1441, 5633},\r
+{5921, 1185, 5425},\r
+{5809, 1265, 5633},\r
+{5633, 1329, 6337},\r
+{5697, 1265, 5985},\r
+{6097, 1105, 5537},\r
+{6081, 1441, 5233},\r
+{5921, 2161, 5425},\r
+{6049, 1537, 5857},\r
+{6033, 1521, 5601},\r
+{6113, 1537, 5217},\r
+{6097, 1985, 5233},\r
+{6049, 1809, 5585},\r
+{6257, 1425, 5425},\r
+{6033, 1377, 5377},\r
+{6225, 1553, 5297},\r
+{5921, 1057, 5649},\r
+{5681, 1393, 6097},\r
+{5825, 913, 5713},\r
+{5985, 1025, 5489},\r
+{5761, 625, 5889},\r
+{5617, 849, 6305},\r
+{5857, 593, 6161},\r
+{5937, 977, 5457},\r
+{5985, 1489, 5393},\r
+{6065, 1425, 5553},\r
+{5937, 1217, 5985},\r
+{5969, 977, 5665},\r
+{6081, 1665, 5329},\r
+{6113, 1537, 5489},\r
+{5841, 1537, 5921},\r
+{6129, 1537, 5617},\r
+{5985, 657, 5681},\r
+{5825, 657, 5745},\r
+{5665, 1089, 5857},\r
+{5889, 1137, 6001},\r
+{5713, 657, 6033},\r
+{5793, 929, 5809},\r
+{5681, 769, 5921},\r
+{5697, 1025, 6273},\r
+{5809, 1601, 5665},\r
+{6129, 913, 5457},\r
+{5921, 657, 5489},\r
+{5713, 1921, 5585},\r
+{5825, 1489, 5889},\r
+{5825, 1249, 5585},\r
+{5841, 1361, 5521},\r
+{5921, 1521, 5921},\r
+{5825, 1905, 5825},\r
+{5953, 769, 5713},\r
+{6049, 1217, 5489},\r
+{5857, 881, 5553},\r
+{5921, 1393, 5713},\r
+{5793, 1153, 6049},\r
+{5905, 881, 5601},\r
+{5825, 737, 5761},\r
+{5681, 1105, 6065},\r
+{5649, 833, 6273},\r
+{5729, 961, 6033},\r
+{5953, 753, 5521},\r
+{5985, 1057, 5553},\r
+{5729, 2177, 5569},\r
+{6305, 433, 6561},\r
+{6273, 1345, 5137},\r
+{6257, 1361, 5345},\r
+{5905, 1249, 5505},\r
+{6209, 1009, 5393},\r
+{6033, 1361, 5265},\r
+{6401, 369, 5697},\r
+{6769, 1217, 4529},\r
+{6801, 1089, 4561},\r
+{6433, 865, 4481},\r
+{6449, 369, 5265},\r
+{6257, 81, 5457},\r
+{6321, 497, 5377},\r
+{6305, 81, 5521},\r
+{6545, 177, 5153},\r
+{6577, 97, 5025},\r
+{6609, 513, 4817},\r
+{6721, 865, 4929},\r
+{6609, 705, 5121},\r
+{6353, 241, 5345},\r
+{6241, 465, 5345},\r
+{6369, 1217, 5249},\r
+{6321, 945, 5265},\r
+{6593, 497, 5281},\r
+{6529, 737, 5089},\r
+{6897, 369, 5201},\r
+{6417, 1121, 4561},\r
+{6833, 161, 4833},\r
+{6337, -79, 5425},\r
+{6545, 49, 5137},\r
+{6369, 305, 5137},\r
+{6369, 1, 5681},\r
+{5857, 897, 5345},\r
+{6225, 657, 5809},\r
+{6385, 1041, 5233},\r
+{6689, 1137, 5281},\r
+{6497, 1569, 4881},\r
+{6337, 2225, 4497},\r
+{6081, 1377, 5089},\r
+{6609, 1633, 4721},\r
+{6465, 2017, 4641},\r
+{6593, 2065, 5073},\r
+{6481, 1313, 5217},\r
+{6465, 1265, 5585},\r
+{6465, 1505, 5313},\r
+{6353, 1905, 5489},\r
+{6385, 1729, 5777},\r
+{6257, 2145, 5921},\r
+{5409, 1489, 4737},\r
+{5121, -463, 6465},\r
+{5505, 801, 6209},\r
+{5265, 1137, 6385},\r
+{5729, 577, 5969},\r
+{5873, 321, 5777},\r
+{5761, 1553, 5569},\r
+{5857, 1697, 5793},\r
+{5889, 1073, 6385},\r
+{5841, 1409, 5969},\r
+{6049, 1249, 5441},\r
+{6209, 929, 5201},\r
+{6017, 545, 5729},\r
+{6001, 1441, 5937},\r
+{6209, 1073, 5681},\r
+{6161, 1153, 5585},\r
+{5889, 881, 5489},\r
+{5729, 833, 5825},\r
+{5777, 673, 6193},\r
+{5585, 817, 5953},\r
+{5425, 369, 6193},\r
+{5585, 481, 6193},\r
+{5793, 737, 5969},\r
+{6209, 1105, 5345},\r
+{6209, 1185, 5249},\r
+{6113, 1745, 5457},\r
+{5873, 1889, 5889},\r
+{5825, 1313, 5985},\r
+{5777, 1329, 5729},\r
+{5841, 1425, 5617},\r
+{5777, 2225, 5713},\r
+{5905, 2385, 5793},\r
+{5937, 1345, 5777},\r
+{5729, 1409, 5681},\r
+{5745, 1233, 5761},\r
+{5537, 1441, 5921},\r
+{5473, 1537, 6017},\r
+{5553, 929, 5921},\r
+{5585, 849, 6017},\r
+{5585, 1057, 6017},\r
+{5473, 673, 6401},\r
+{5537, 881, 5985},\r
+{6145, 1121, 5569},\r
+{5953, 1793, 5521},\r
+{6001, 1537, 5809},\r
+{5889, 1457, 5777},\r
+{6017, 1377, 5617},\r
+{5905, 1905, 5489},\r
+{5953, 1793, 5601},\r
+{6049, 1489, 5569},\r
+{5969, 1569, 5809},\r
+{5905, 1137, 5633},\r
+{5713, 1313, 5809},\r
+{5569, 1649, 6081},\r
+{5793, 929, 5985},\r
+{5681, 769, 5857},\r
+{5681, 961, 5793},\r
+{5729, 1345, 6001},\r
+{5617, 561, 6225},\r
+{5601, 849, 6049},\r
+{5921, 1233, 5569},\r
+{5857, 1649, 5569},\r
+{6017, 1713, 5601},\r
+{5889, 769, 5889},\r
+{5777, 1121, 5729},\r
+{5937, 1761, 5553},\r
+{5889, 1473, 5633},\r
+{5857, 1361, 5985},\r
+{6033, 1617, 5713},\r
+{6257, 1601, 5521},\r
+{6225, 1185, 5249},\r
+{6161, 1105, 5153},\r
+{6017, 849, 5297},\r
+{5633, 1169, 5937},\r
+{6113, 1393, 5473},\r
+{6257, 401, 5441},\r
+{5937, 657, 5697},\r
+{5985, 993, 5777},\r
+{5969, 1441, 5601},\r
+{6241, 1073, 5473},\r
+{5857, 1729, 5489},\r
+{6017, 1633, 5649},\r
+{6065, 1681, 5681},\r
+{6113, 1457, 5281},\r
+{6193, 1745, 5153},\r
+{6209, 1825, 5409},\r
+{6113, 1729, 5585},\r
+{5937, 1697, 5665},\r
+{6033, 1105, 5841},\r
+{6033, 2001, 5537},\r
+{6145, 1665, 5249},\r
+{6209, 865, 5297},\r
+{6017, 1377, 5601},\r
+{5793, 769, 5889},\r
+{5697, 1025, 5889},\r
+{5601, 897, 6081},\r
+{5617, 1249, 6049},\r
+{6097, 833, 5697},\r
+{6193, 1105, 5409},\r
+{6001, 1313, 5553},\r
+{6033, 1617, 5521},\r
+{5985, 1745, 5617},\r
+{6001, 1409, 5761},\r
+{6033, 1537, 5441},\r
+{6129, 1729, 5313},\r
+{6017, 1665, 5313},\r
+{5905, 1617, 5953},\r
+{5825, 1457, 5937},\r
+{6097, 1585, 5553},\r
+{5969, 1153, 5665},\r
+{5857, 1441, 5633},\r
+{5889, 1169, 5761},\r
+{5889, 1217, 5873},\r
+{5889, 881, 5793},\r
+{5633, 1089, 5985},\r
+{5649, 961, 6033},\r
+{5617, 993, 6049},\r
+{5681, 849, 6065},\r
+{5745, 1057, 5937},\r
+{5921, 1185, 5745},\r
+{5825, 945, 5729},\r
+{5841, 1249, 5665},\r
+{5889, 1441, 5681},\r
+{5905, 1329, 5809},\r
+{5857, 1249, 5697},\r
+{5937, 1489, 5665},\r
+{5809, 1681, 5937},\r
+{5889, 1873, 5665},\r
+{5921, 1505, 5697},\r
+{6065, 1489, 5361},\r
+{6049, 1265, 5409},\r
+{6017, 1489, 5489},\r
+{5937, 1201, 5617},\r
+{5745, 1265, 5937},\r
+{5777, 1281, 5873},\r
+{5937, 1265, 5649},\r
+{5745, 945, 5969},\r
+{5777, 929, 5905},\r
+{5761, 945, 5905},\r
+{5777, 961, 5793},\r
+{5921, 561, 5777},\r
+{5857, 865, 5761},\r
+{5969, 1201, 5569},\r
+{5681, 1633, 5777},\r
+{5681, 1089, 6129},\r
+{5537, 1377, 6001},\r
+{5825, 1617, 5777},\r
+{5697, 1601, 5841},\r
+{5745, 1441, 5953},\r
+{5729, 1313, 5985},\r
+{5921, 1377, 5681},\r
+{5841, 1521, 5729},\r
+{5793, 929, 5969},\r
+{5585, 1601, 5937},\r
+{5761, 1281, 5921},\r
+{5697, 945, 5873},\r
+{5697, 881, 5921},\r
+{5713, 1073, 5841},\r
+{5585, 993, 5841},\r
+{5489, 961, 5985},\r
+{5889, 785, 6321},\r
+{5745, 1057, 6145},\r
+{6529, 1441, 5249},\r
+{6321, 561, 4401},\r
+{6497, 913, 5089},\r
+{6161, 513, 5553},\r
+{6449, 353, 5233},\r
+{6401, 417, 5121},\r
+{6273, 561, 5217},\r
+{6577, 273, 5249},\r
+{6465, -335, 5025},\r
+{6417, 97, 5041},\r
+{6497, -319, 5185},\r
+{6209, -559, 5345},\r
+{6001, -719, 5697},\r
+{5937, -1039, 6241},\r
+{5905, -895, 5745},\r
+{5985, -687, 5425},\r
+{5985, -1103, 5601},\r
+{6193, -911, 5393},\r
+{6257, -943, 5313},\r
+{6433, -351, 5233},\r
+{6129, 65, 4865},\r
+{6369, 49, 5937},\r
+{6305, -543, 5537},\r
+{6577, -383, 5345},\r
+{6785, 737, 5185},\r
+{6673, 289, 4593},\r
+{5969, 1313, 4817},\r
+{7969, 145, 4897},\r
+{6497, 1393, 5057},\r
+{6593, -591, 5169},\r
+{5921, -159, 5201},\r
+{6113, -367, 5761},\r
+{6129, 33, 5649},\r
+{6577, -447, 5361},\r
+{6177, 769, 5073},\r
+{6241, 209, 5761},\r
+{6209, -79, 6321},\r
+{6305, 209, 5713},\r
+{6577, 881, 4945},\r
+{6497, 1489, 4785},\r
+{6321, 657, 5313},\r
+{6241, 625, 5601},\r
+{6529, 929, 5377},\r
+{6449, 1489, 4977},\r
+{6193, 1585, 4961},\r
+{6273, 625, 5825},\r
+{6257, 1457, 5345},\r
+{6529, 785, 5249},\r
+{6289, 913, 4929},\r
+{6081, 385, 4897},\r
+{5809, -223, 6113},\r
+{5889, -271, 6049},\r
+{5761, -463, 5905},\r
+{5905, 33, 5793},\r
+{5921, 17, 5729},\r
+{5873, -111, 6049},\r
+{6081, -175, 5777},\r
+{6065, 65, 5697},\r
+{6193, 769, 5169},\r
+{6305, 865, 5121},\r
+{6337, 337, 5505},\r
+{6177, 417, 5697},\r
+{6241, 881, 5297},\r
+{6065, 1009, 5297},\r
+{6017, 545, 5745},\r
+{6193, 257, 5649},\r
+{6433, 641, 5361},\r
+{6401, 705, 5265},\r
+{6161, -399, 5473},\r
+{6033, 289, 5745},\r
+{6113, 257, 5553},\r
+{6161, -175, 5601},\r
+{6193, -335, 5569},\r
+{6113, 81, 5361},\r
+{6113, 465, 5393},\r
+{6001, 641, 5313},\r
+{6161, 2049, 6881},\r
+{6257, 1105, 5473},\r
+{6129, 1761, 5313},\r
+{6353, 2529, 5249},\r
+{6353, 2737, 5377},\r
+{6545, 2257, 4897},\r
+{6497, 2497, 5281},\r
+{6353, 2977, 4929},\r
+{6353, 2129, 3681},\r
+{6449, 2593, 4081},\r
+{6001, 1505, 5937},\r
+{6353, 1425, 5169},\r
+{6049, 1665, 5457},\r
+{5953, 1409, 5489},\r
+{6017, 977, 5617},\r
+{5617, 753, 5793},\r
+{5761, 897, 5713},\r
+{5825, 577, 5841},\r
+{5937, 753, 5649},\r
+{5793, 353, 5425},\r
+{6001, 225, 6049},\r
+{6353, 417, 5169},\r
+{6353, 577, 5521},\r
+{5921, 913, 5377},\r
+{6017, 1153, 5025},\r
+{6193, 1537, 6129},\r
+{5937, 1393, 5921},\r
+{5969, 1265, 5553},\r
+{6081, 1505, 5505},\r
+{6097, 1729, 5329},\r
+{6129, 1921, 5729},\r
+{5937, 1617, 5521},\r
+{6113, 1665, 5297},\r
+{6241, 1505, 5297},\r
+{6273, 1857, 5249},\r
+{5921, 1185, 5729},\r
+{5889, 1073, 5905},\r
+{6145, 1025, 5569},\r
+{6049, 961, 5457},\r
+{5889, 1089, 5665},\r
+{5745, 1057, 5921},\r
+{5889, 289, 5969},\r
+{6049, 929, 5585},\r
+{6129, 1105, 5425},\r
+{6049, 977, 5569},\r
+{5873, 1361, 5697},\r
+{6161, 1393, 5569},\r
+{6033, 1457, 5473},\r
+{6241, 1649, 5233},\r
+{6209, 2001, 5185},\r
+{6161, 1681, 5345},\r
+{6097, 1697, 5473},\r
+{6161, 1777, 5297},\r
+{6273, 1681, 5297},\r
+{6225, 1793, 5313},\r
+{6017, 1553, 5441},\r
+{5921, 1201, 5745},\r
+{5889, 1425, 5697},\r
+{6033, 1073, 5633},\r
+{5905, 1089, 5489},\r
+{5921, 897, 5681},\r
+{5745, 977, 6049},\r
+{5937, 1265, 5681},\r
+{6097, 865, 5473},\r
+{6081, 1217, 5441},\r
+{5873, 1281, 5713},\r
+{5889, 1697, 5729},\r
+{6129, 1585, 5553},\r
+{6097, 1489, 5425},\r
+{6097, 1457, 5409},\r
+{6049, 1633, 5473},\r
+{6033, 1697, 5569},\r
+{6129, 1505, 5441},\r
+{6129, 1537, 5473},\r
+{6177, 1761, 5345},\r
+{6193, 1585, 5361},\r
+{6145, 1393, 5441},\r
+{5841, 1473, 5697},\r
+{6065, 1233, 5585},\r
+{6129, 1073, 5425},\r
+{6001, 1073, 5553},\r
+{5969, 1185, 5649},\r
+{6049, 1089, 5697},\r
+{6129, 817, 5569},\r
+{6033, 1201, 5409},\r
+{6049, 993, 5553},\r
+{5969, 1361, 5553},\r
+{6017, 1313, 5633},\r
+{6225, 1409, 5313},\r
+{6209, 1217, 5297},\r
+{6193, 1457, 5329},\r
+{6193, 1633, 5345},\r
+{6033, 1505, 5665},\r
+{6129, 1537, 5441},\r
+{6145, 1553, 5409},\r
+{6161, 1473, 5457},\r
+{6161, 1281, 5553},\r
+{5969, 1361, 5617},\r
+{5985, 1281, 5617},\r
+{6033, 1249, 5553},\r
+{6001, 1041, 5585},\r
+{5969, 1137, 5681},\r
+{5889, 1089, 5825},\r
+{5921, 1185, 5761},\r
+{6113, 993, 5649},\r
+{6129, 1153, 5441},\r
+{6049, 1121, 5601},\r
+{6017, 1137, 5601},\r
+{6081, 1265, 5457},\r
+{6081, 1265, 5521},\r
+{6081, 1233, 5601},\r
+{5937, 1425, 5633},\r
+{6049, 1361, 5601},\r
+{6017, 1345, 5665},\r
+{5969, 1265, 5665},\r
+{6113, 1697, 5473},\r
+{6177, 1617, 5425},\r
+{6129, 1025, 5521},\r
+{5921, 1121, 5713},\r
+{5841, 1089, 5825},\r
+{6033, 1185, 5649},\r
+{5985, 1105, 5601},\r
+{5905, 1089, 5729},\r
+{5857, 737, 5873},\r
+{5857, 897, 5921},\r
+{5809, 849, 5809},\r
+{6129, 1073, 5505},\r
+{6001, 673, 5569},\r
+{6113, 1073, 5569},\r
+{6097, 1281, 5569},\r
+{6097, 1441, 5457},\r
+{6113, 1233, 5329},\r
+{5409, 1953, 5489},\r
+{6065, 1281, 5969},\r
+{5905, 1969, 5569},\r
+{6449, 1313, 4977},\r
+{6529, 1329, 4401},\r
+{6657, 945, 5041},\r
+{6273, 1121, 5473},\r
+{6369, 417, 5169},\r
+{6321, 385, 5345},\r
+{6289, 705, 5185},\r
+{6433, 417, 5329},\r
+{6161, 225, 5505},\r
+{6257, 417, 5121},\r
+{6657, 177, 4881},\r
+{6337, 241, 5393},\r
+{6369, 657, 5457},\r
+{6609, 849, 5089},\r
+{6577, 433, 5169},\r
+{6465, 913, 5169},\r
+{6641, 865, 4849},\r
+{6545, 1201, 4897},\r
+{6401, 945, 5265},\r
+{6449, 801, 5233},\r
+{6689, 929, 5025},\r
+{6625, 1041, 4945},\r
+{6577, 897, 4929},\r
+{6385, 417, 5201},\r
+{6289, 289, 5601},\r
+{6145, 241, 5521},\r
+{6193, 609, 5361},\r
+{6209, 353, 5537},\r
+{6385, 401, 5585},\r
+{6673, 609, 5265},\r
+{6273, 465, 5217},\r
+{6545, 513, 5105},\r
+{6369, 1185, 4977},\r
+{6465, 913, 5121},\r
+{6433, 753, 5249},\r
+{6305, 1137, 5265},\r
+{6321, 1313, 5249},\r
+{6289, 1313, 5441},\r
+{6321, 1057, 5393},\r
+{6257, 993, 5345},\r
+{6321, 1217, 5169},\r
+{6401, 817, 5201},\r
+{6465, 577, 5313},\r
+{6257, 481, 5537},\r
+{6401, 769, 5441},\r
+{6305, 513, 5249},\r
+{6001, 929, 5441},\r
+{5969, 849, 5825},\r
+{5953, 785, 6177},\r
+{6097, 609, 5777},\r
+{6097, 1281, 5425},\r
+{6081, 1489, 5617},\r
+{6145, 1345, 5553},\r
+{6289, 1185, 5073},\r
+{6225, 1313, 5169},\r
+{6433, 1409, 4961},\r
+{6113, 1521, 5537},\r
+{6225, 1265, 5681},\r
+{6161, 705, 5665},\r
+{6353, 1041, 5585},\r
+{5953, 1377, 5521},\r
+{6097, 1265, 5473},\r
+{6081, 1265, 5489},\r
+{5681, 881, 6193},\r
+{5857, 1521, 5953},\r
+{6209, 1457, 4977},\r
+{5969, 1537, 5617},\r
+{5889, 1313, 5793},\r
+{6049, 1553, 5937},\r
+{6065, 1425, 5745},\r
+{6001, 1681, 5521},\r
+{5537, 1937, 5777},\r
+{5889, 1937, 6273},\r
+{6289, 1329, 5489},\r
+{6257, 1201, 5057},\r
+{6241, 1425, 4721},\r
+{6209, 1937, 4929},\r
+{6049, 913, 5601},\r
+{5969, 1201, 5905},\r
+{6097, 1313, 5681},\r
+{6097, 1201, 5681},\r
+{5937, 1169, 5825},\r
+{5857, 1281, 5857},\r
+{6097, 1073, 5601},\r
+{6001, 1009, 5521},\r
+{5985, 1137, 5713},\r
+{6033, 1137, 5601},\r
+{5857, 1217, 5665},\r
+{5905, 1009, 5889},\r
+{5969, 1265, 5745},\r
+{5985, 1313, 5553},\r
+{6209, 1649, 5313},\r
+{6049, 1377, 5633},\r
+{6305, 1505, 5313},\r
+{6385, 1457, 5105},\r
+{6289, 1601, 5089},\r
+{6353, 1729, 5265},\r
+{6225, 1713, 5457},\r
+{6289, 1505, 5425},\r
+{6289, 1617, 5313},\r
+{6273, 1665, 5233},\r
+{6081, 1409, 5441},\r
+{6145, 1553, 5361},\r
+{5985, 977, 5665},\r
+{5953, 1169, 5809},\r
+{5825, 865, 5889},\r
+{5905, 1073, 5921},\r
+{5809, 945, 5921},\r
+{5777, 673, 5857},\r
+{5873, 897, 5745},\r
+{5921, 545, 5745},\r
+{5953, 865, 5761},\r
+{5985, 1041, 5713},\r
+{5921, 1025, 5873},\r
+{5969, 1025, 5745},\r
+{5969, 849, 5633},\r
+{5953, 1105, 5569},\r
+{5969, 1457, 5665},\r
+{5985, 1393, 5633},\r
+{6033, 1137, 5713},\r
+{6097, 961, 5697},\r
+{6209, 1025, 5329},\r
+{6113, 641, 5553},\r
+{6049, 1089, 5649},\r
+{6001, 753, 5729},\r
+{5953, 817, 5729},\r
+{5969, 721, 5777},\r
+{5825, 1073, 5809},\r
+{5841, 897, 5905},\r
+{5873, 1009, 5809},\r
+{6001, 801, 5713},\r
+{5937, 865, 5713},\r
+{5969, 1185, 5633},\r
+{5921, 1281, 5665},\r
+{5969, 1521, 5601},\r
+{6033, 1457, 5681},\r
+{6001, 1473, 5537},\r
+{6033, 1569, 5441},\r
+{5969, 1617, 5537},\r
+{5969, 1809, 5681},\r
+{6017, 1585, 5665},\r
+{6177, 1729, 5409},\r
+{6145, 1649, 5281},\r
+{6017, 1841, 5473},\r
+{5857, 1585, 5569},\r
+{5761, 1297, 5809},\r
+{5905, 1585, 5761},\r
+{5969, 1201, 5729},\r
+{5825, 1409, 5601},\r
+{5681, 1313, 5953},\r
+{5729, 1473, 6097},\r
+{5857, 1025, 5969},\r
+{5953, 1185, 5585},\r
+{5969, 1377, 5537},\r
+{5985, 1633, 5633},\r
+{5921, 1457, 5745},\r
+{5889, 1601, 5729},\r
+{5873, 1409, 5617},\r
+{5905, 1777, 5649},\r
+{5777, 1969, 5681},\r
+{5905, 1889, 5649},\r
+{6017, 1873, 5553},\r
+{5985, 1761, 5617},\r
+{6033, 1553, 5537},\r
+{5937, 1521, 5569},\r
+{5841, 1313, 5681},\r
+{5841, 1585, 5729},\r
+{5921, 1265, 5761},\r
+{5937, 1569, 5329},\r
+{5953, 1025, 5809},\r
+{5873, 1553, 5905},\r
+{5921, 945, 5953},\r
+{5841, 1249, 5713},\r
+{5729, 1889, 5521},\r
+{5857, 2337, 5569},\r
+{6193, 2129, 5393},\r
+{5825, 2497, 5473},\r
+{6113, 1985, 5361},\r
+{5921, 2097, 5473},\r
+{5953, 2209, 5537},\r
+{6193, 1953, 5361},\r
+{6065, 2113, 5377},\r
+{6001, 1953, 5441},\r
+{5905, 1857, 5553},\r
+{5793, 1873, 5665},\r
+{5761, 1345, 5729},\r
+{5777, 865, 5473},\r
+{5729, 1073, 5649},\r
+{5553, 1569, 6065},\r
+{5665, 1169, 6177},\r
+{5873, 1473, 5425},\r
+{5985, 1729, 5169},\r
+{6033, 1809, 5281},\r
+{5617, 1745, 6097},\r
+{5793, 1841, 5441},\r
+{5777, 2081, 5185},\r
+{5793, 1905, 5809},\r
+{5457, 1841, 5905},\r
+{5617, 1569, 6129},\r
+{5809, 1633, 5921},\r
+{5889, 1889, 5729},\r
+{5873, 1553, 5537},\r
+{5793, 1217, 5457},\r
+{5713, 1265, 6241},\r
+{5777, 1201, 5857},\r
+{5745, 1153, 5761},\r
+{5841, 1041, 5873},\r
+{6049, 1025, 5665},\r
+{6257, 945, 5665},\r
+{6065, 849, 5281},\r
+{6321, 1089, 5185},\r
+{6369, 1505, 5169},\r
+{6401, 977, 5425},\r
+{6097, 913, 5681},\r
+{6289, 1105, 5345},\r
+{6449, 1441, 5201},\r
+{6305, 1137, 5121},\r
+{6465, 1329, 5073},\r
+{6369, 897, 5393},\r
+{6497, 1073, 5249},\r
+{6433, 1121, 4929},\r
+{6241, 1121, 5281},\r
+{6193, 641, 5569},\r
+{6177, 433, 5553},\r
+{6113, 513, 5393},\r
+{6161, 705, 5457},\r
+{6273, 289, 5649},\r
+{6193, 337, 5665},\r
+{6401, 577, 5329},\r
+{6561, 385, 5217},\r
+{6305, 1121, 4929},\r
+{6065, 2193, 5425},\r
+{6769, -47, 5345},\r
+{6449, 1889, 5041},\r
+{6417, 1409, 5345},\r
+{6177, 1521, 5281},\r
+{6001, 1873, 5393},\r
+{6417, 1249, 5057},\r
+{6225, 945, 4929},\r
+{6241, 1041, 4945},\r
+{5969, 1601, 5329},\r
+{5665, 1889, 6081},\r
+{5649, 2417, 6609},\r
+{5745, 1361, 5585},\r
+{5985, 1441, 5473},\r
+{5953, 2289, 5537},\r
+{5985, 1393, 5377},\r
+{5921, 2081, 5441},\r
+{5905, 2241, 5601},\r
+{5985, 1921, 5489},\r
+{6097, 1969, 5249},\r
+{6081, 2161, 5169},\r
+{6097, 2065, 5329},\r
+{6097, 2241, 5585},\r
+{6097, 2241, 5393},\r
+{6065, 1809, 5409},\r
+{5969, 1633, 5377},\r
+{5937, 1745, 5537},\r
+{5953, 1985, 5601},\r
+{5921, 1793, 5553},\r
+{5889, 1729, 5569},\r
+{5793, 1809, 5937},\r
+{5841, 1793, 5873},\r
+{6129, 1665, 5505},\r
+{6241, 1361, 5361},\r
+{6049, 2081, 5105},\r
+{5937, 2273, 5249},\r
+{6033, 2161, 5633},\r
+{5921, 2017, 5905},\r
+{5889, 2033, 5713},\r
+{6001, 2097, 5217},\r
+{5825, 2337, 5553},\r
+{5953, 2129, 5633},\r
+{6017, 2065, 5409},\r
+{6017, 1777, 5457},\r
+{6065, 2273, 5297},\r
+{5889, 1873, 5537},\r
+{5809, 1825, 5713},\r
+{5745, 1425, 5841},\r
+{5777, 1777, 5745},\r
+{5889, 1265, 5585},\r
+{5809, 1681, 5777},\r
+{5873, 1553, 5777},\r
+{6033, 1505, 5665},\r
+{6065, 1393, 5489},\r
+{5953, 2017, 5329},\r
+{6129, 1553, 5553},\r
+{6065, 1185, 5521},\r
+{6049, 1297, 5489},\r
+{6017, 1585, 5377},\r
+{6033, 1889, 5329},\r
+{5953, 1921, 5537},\r
+{6113, 1681, 5473},\r
+{6177, 1825, 5297},\r
+{6113, 1697, 5329},\r
+{5985, 1505, 5425},\r
+{5937, 1457, 5649},\r
+{5857, 1425, 5921},\r
+{5825, 1185, 5681},\r
+{5809, 1377, 5745},\r
+{5713, 1393, 5873},\r
+{5745, 1217, 6049},\r
+{5825, 1281, 5777},\r
+{5937, 1169, 5649},\r
+{5905, 1185, 5585},\r
+{5873, 1345, 5665},\r
+{5857, 1377, 5713},\r
+{5873, 1633, 5873},\r
+{5889, 1473, 5745},\r
+{5841, 1249, 5601},\r
+{5873, 1729, 5617},\r
+{5793, 1761, 5633},\r
+{5777, 1441, 5969},\r
+{5873, 1681, 5713},\r
+{5985, 1665, 5505},\r
+{5969, 1601, 5617},\r
+{5873, 1537, 5617},\r
+{5857, 1297, 5841},\r
+{5761, 1313, 5969},\r
+{6017, 1377, 5409},\r
+{5953, 1265, 5473},\r
+{5889, 1329, 5537},\r
+{5873, 1265, 5809},\r
+{5953, 1169, 5697},\r
+{6049, 1249, 5489},\r
+{6113, 1361, 5441},\r
+{6065, 1601, 5441},\r
+{5873, 1585, 5553},\r
+{5809, 1617, 5761},\r
+{5841, 1857, 5665},\r
+{5873, 1793, 5489},\r
+{5969, 1809, 5505},\r
+{5857, 1873, 5633},\r
+{5969, 2225, 5409},\r
+{6017, 1617, 5537},\r
+{6049, 1697, 5521},\r
+{5953, 1505, 5553},\r
+{5905, 1761, 5489},\r
+{6001, 1601, 5825},\r
+{5905, 1393, 5553},\r
+{5921, 1441, 5505},\r
+{5777, 1265, 5633},\r
+{5681, 1681, 5889},\r
+{5985, 1521, 5617},\r
+{6065, 1169, 5441},\r
+{5969, 1425, 5473},\r
+{5841, 1521, 5649},\r
+{5777, 1857, 5809},\r
+{5793, 1745, 5953},\r
+{5825, 1745, 5553},\r
+{5841, 1841, 5553},\r
+{5889, 2017, 5569},\r
+{5793, 1873, 5681},\r
+{5937, 1889, 5729},\r
+{5921, 1985, 5505},\r
+{6017, 1921, 5441},\r
+{5905, 1649, 5681},\r
+{5905, 1585, 5697},\r
+{5937, 1761, 5569},\r
+{6097, 1409, 5265},\r
+{6017, 1377, 5441},\r
+{5905, 1377, 5649},\r
+{5793, 1665, 5921},\r
+{6001, 1521, 5649},\r
+{6065, 1473, 5361},\r
+{6033, 1313, 5521},\r
+{5873, 1777, 5697},\r
+{5841, 1649, 5857},\r
+{5761, 1569, 6001},\r
+{5841, 1793, 5409},\r
+{5777, 1729, 5537},\r
+{5809, 1713, 5713},\r
+{5713, 1905, 5777},\r
+{5761, 1681, 5969},\r
+{5889, 1937, 5569},\r
+{5857, 1713, 5553},\r
+{5777, 1521, 5761},\r
+{5745, 1457, 5857},\r
+{5745, 1777, 5745},\r
+{5825, 1393, 5777},\r
+{5825, 1377, 5777},\r
+{5825, 1345, 5761},\r
+{5745, 1681, 5841},\r
+{5697, 1361, 5841},\r
+{5761, 1377, 5905},\r
+{5937, 1409, 5633},\r
+{5873, 1617, 5601},\r
+{5745, 1857, 5521},\r
+{5793, 1793, 5601},\r
+{5793, 1969, 5889},\r
+{5857, 2049, 5489},\r
+{5889, 2161, 5377},\r
+{5873, 2385, 5409},\r
+{5873, 2193, 5585},\r
+{5793, 2001, 5681},\r
+{5985, 2401, 5297},\r
+{6001, 2289, 5377},\r
+{5873, 2289, 5409},\r
+{5857, 1729, 5617},\r
+{5825, 2017, 5601},\r
+{5889, 1761, 5569},\r
+{5841, 1713, 5521},\r
+{5793, 1601, 5601},\r
+{5825, 1873, 5793},\r
+{5841, 1521, 5857},\r
+{5921, 1441, 5633},\r
+{5905, 1793, 5601},\r
+{5809, 1745, 5713},\r
+{5809, 1793, 5713},\r
+{5905, 1761, 5745},\r
+{5921, 1745, 5473},\r
+{5713, 1745, 5425},\r
+{5793, 2129, 5585},\r
+{6689, 897, 6161},\r
+{6065, 2913, 5681},\r
+{6097, 1521, 5537},\r
+{6097, 1761, 5457},\r
+{6273, 1153, 5441},\r
+{6273, 1521, 5361},\r
+{6257, 1889, 5137},\r
+{6033, 1329, 5009},\r
+{6033, 209, 5729},\r
+{6113, 177, 5713},\r
+{5953, 609, 5761},\r
+{6129, 481, 5713},\r
+{5937, 481, 5665},\r
+{6129, 449, 5409},\r
+{6177, 369, 5457},\r
+{6177, 609, 5489},\r
+{6225, 305, 5569},\r
+{6097, 401, 5537},\r
+{6145, 305, 5649},\r
+{6081, 625, 5457},\r
+{6113, 705, 5457},\r
+{6081, 561, 5473},\r
+{6273, 609, 5633},\r
+{6433, 481, 5281},\r
+{6385, 529, 5217},\r
+{5873, 593, 5569},\r
+{6657, -1983, 5969},\r
+{5873, 1185, 5345},\r
+{6289, -607, 5681},\r
+{5489, 1441, 5313},\r
+{6033, -63, 5921},\r
+{6081, 1009, 5745},\r
+{5889, 1041, 6129},\r
+{6241, 817, 5345},\r
+{6145, 689, 5313},\r
+{6209, 1121, 5377},\r
+{6321, 1121, 5665},\r
+{6321, 1505, 5297},\r
+{6321, 1537, 5185},\r
+{6161, 2001, 4721},\r
+{6513, 2097, 5041},\r
+{6513, 1777, 5313},\r
+{6289, 1793, 5361},\r
+{5921, 2241, 4977},\r
+{6369, 2865, 4865},\r
+{5953, 3041, 5185},\r
+{6273, 3457, 4753},\r
+{6097, 3841, 4641},\r
+{6241, 3521, 4577},\r
+{6145, 2705, 4753},\r
+{6113, 2305, 4481},\r
+{5729, 2353, 4609},\r
+{5777, 3169, 7057},\r
+{6065, 2049, 4977},\r
+{6049, 1953, 5073},\r
+{5857, 2673, 5393},\r
+{5873, 2625, 5633},\r
+{5953, 2289, 5633},\r
+{5761, 2657, 5377},\r
+{5841, 2577, 5217},\r
+{5841, 2529, 5377},\r
+{5857, 2433, 5585},\r
+{5857, 2849, 5585},\r
+{5937, 2385, 5329},\r
+{5905, 2449, 5201},\r
+{6001, 2337, 5329},\r
+{5841, 2273, 5473},\r
+{5793, 2273, 5505},\r
+{5761, 2209, 5649},\r
+{5809, 2209, 5633},\r
+{5745, 2033, 5649},\r
+{5745, 2177, 5745},\r
+{5633, 2177, 5793},\r
+{5921, 2049, 5569},\r
+{5937, 1681, 5489},\r
+{5873, 1905, 5553},\r
+{5761, 2401, 5553},\r
+{5697, 2545, 5633},\r
+{5697, 2481, 5665},\r
+{5809, 2305, 5697},\r
+{5873, 2417, 5313},\r
+{5809, 2593, 5377},\r
+{5745, 2449, 5553},\r
+{5793, 2465, 5713},\r
+{5905, 2689, 5313},\r
+{5969, 2065, 5457},\r
+{5841, 2081, 5489},\r
+{5761, 1921, 5569},\r
+{5713, 2289, 5569},\r
+{5665, 2401, 5825},\r
+{5745, 1857, 5585},\r
+{5857, 1713, 5521},\r
+{5761, 1969, 5601},\r
+{5857, 2065, 5761},\r
+{5761, 1969, 5713},\r
+{6033, 1361, 5521},\r
+{5873, 2209, 5505},\r
+{5761, 2289, 5345},\r
+{5713, 2497, 5249},\r
+{5905, 2801, 5649},\r
+{6001, 2529, 5057},\r
+{6001, 2625, 5041},\r
+{6033, 2817, 5185},\r
+{5873, 2913, 5297},\r
+{5857, 2561, 5505},\r
+{5825, 2337, 5585},\r
+{5857, 2065, 5361},\r
+{5905, 2193, 5377},\r
+{5873, 1985, 5665},\r
+{5793, 1969, 5585},\r
+{5905, 1889, 5617},\r
+{5729, 1905, 5745},\r
+{5857, 1633, 5697},\r
+{5777, 1889, 5681},\r
+{5969, 2129, 5441},\r
+{6113, 1617, 5617},\r
+{6065, 1649, 5569},\r
+{5809, 2161, 5377},\r
+{5889, 2369, 5441},\r
+{5905, 1825, 5745},\r
+{6001, 2529, 5377},\r
+{6033, 2321, 5089},\r
+{6065, 2129, 5313},\r
+{5985, 2209, 5441},\r
+{6001, 2273, 5553},\r
+{6033, 1889, 5601},\r
+{5937, 1617, 5361},\r
+{5905, 1841, 5409},\r
+{5953, 1777, 5601},\r
+{6001, 1793, 5761},\r
+{5873, 1457, 5633},\r
+{5857, 1857, 5457},\r
+{5905, 1393, 5761},\r
+{5889, 1345, 5697},\r
+{5985, 1313, 5489},\r
+{6017, 1521, 5409},\r
+{5889, 2577, 5217},\r
+{5937, 2673, 5457},\r
+{5921, 2913, 5393},\r
+{5889, 2737, 5265},\r
+{6001, 2433, 5025},\r
+{6017, 2625, 5121},\r
+{5953, 2721, 5265},\r
+{6033, 2881, 5297},\r
+{6049, 2593, 5217},\r
+{6065, 2529, 5217},\r
+{5985, 2513, 5121},\r
+{5825, 2593, 5489},\r
+{5889, 2289, 5633},\r
+{5873, 2081, 5505},\r
+{5761, 1985, 5553},\r
+{5841, 2129, 5553},\r
+{5857, 2209, 5729},\r
+{5969, 1953, 5281},\r
+{5953, 2129, 5265},\r
+{5985, 2177, 5441},\r
+{5937, 2497, 5473},\r
+{6017, 2337, 5265},\r
+{6001, 2289, 5137},\r
+{5889, 2625, 5281},\r
+{5889, 2561, 5441},\r
+{5921, 2369, 5585},\r
+{6177, 2465, 5201},\r
+{5953, 2497, 5249},\r
+{5953, 2273, 5345},\r
+{6001, 2193, 5393},\r
+{5793, 2113, 5521},\r
+{5873, 1921, 5697},\r
+{5777, 1729, 5697},\r
+{5793, 2113, 5745},\r
+{5921, 1777, 5841},\r
+{5873, 2033, 5665},\r
+{5985, 1793, 5521},\r
+{5953, 1745, 5553},\r
+{5889, 2273, 5377},\r
+{5889, 2465, 5457},\r
+{6049, 2225, 5521},\r
+{5889, 2033, 5473},\r
+{5873, 2273, 5393},\r
+{5857, 2577, 5585},\r
+{5953, 2433, 5697},\r
+{6017, 2417, 5425},\r
+{6033, 2289, 5169},\r
+{5921, 2065, 5329},\r
+{5889, 1953, 5729},\r
+{5857, 2113, 5617},\r
+{6033, 1793, 5345},\r
+{5921, 2097, 5201},\r
+{5873, 1681, 5729},\r
+{5825, 2113, 5697},\r
+{5953, 1921, 5489},\r
+{5985, 1761, 5425},\r
+{6081, 1665, 5393},\r
+{6001, 2289, 5569},\r
+{6049, 2401, 5537},\r
+{6017, 2273, 5457},\r
+{5921, 1809, 5297},\r
+{5937, 2225, 5329},\r
+{5985, 2433, 5585},\r
+{5953, 2049, 5425},\r
+{6033, 2193, 5297},\r
+{5969, 2113, 5393},\r
+{5857, 1809, 5505},\r
+{5921, 1969, 5537},\r
+{5937, 2353, 5265},\r
+{5985, 2033, 5393},\r
+{5841, 2257, 5409},\r
+{5777, 2049, 5649},\r
+{5809, 1873, 5857},\r
+{5921, 1793, 5393},\r
+{5713, 2785, 5745},\r
+{6017, 1777, 5649},\r
+{5857, 2785, 5313},\r
+{6065, 2049, 5937},\r
+{6033, 2113, 5281},\r
+{6001, 1985, 5153},\r
+{5905, 2417, 5505},\r
+{5713, 2305, 5713},\r
+{5905, 2641, 5921},\r
+{6497, 1777, 4417},\r
+{6497, 673, 4625},\r
+{6721, 1057, 4785},\r
+};\r
+static const uint32_t duration_HRD[] = \r
+{\r
+41,\r
+39,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+40,\r
+40,\r
+80,\r
+40,\r
+40,\r
+};\r
+static const uint32_t frame_HRD[] =\r
+{      \r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+151,\r
+152,\r
+153,\r
+154,\r
+155,\r
+156,\r
+157,\r
+158,\r
+159,\r
+160,\r
+161,\r
+162,\r
+163,\r
+164,\r
+165,\r
+166,\r
+167,\r
+168,\r
+169,\r
+170,\r
+171,\r
+172,\r
+173,\r
+174,\r
+175,\r
+176,\r
+177,\r
+178,\r
+179,\r
+180,\r
+181,\r
+182,\r
+183,\r
+184,\r
+185,\r
+186,\r
+187,\r
+188,\r
+189,\r
+190,\r
+191,\r
+192,\r
+193,\r
+194,\r
+195,\r
+196,\r
+197,\r
+198,\r
+199,\r
+200,\r
+201,\r
+202,\r
+203,\r
+204,\r
+205,\r
+206,\r
+207,\r
+208,\r
+209,\r
+210,\r
+211,\r
+212,\r
+213,\r
+214,\r
+215,\r
+216,\r
+217,\r
+218,\r
+219,\r
+220,\r
+221,\r
+222,\r
+223,\r
+224,\r
+225,\r
+226,\r
+227,\r
+228,\r
+229,\r
+230,\r
+231,\r
+232,\r
+233,\r
+234,\r
+235,\r
+236,\r
+237,\r
+238,\r
+239,\r
+240,\r
+241,\r
+242,\r
+243,\r
+244,\r
+245,\r
+246,\r
+247,\r
+248,\r
+249,\r
+250,\r
+251,\r
+252,\r
+253,\r
+254,\r
+255,\r
+0,\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,\r
+60,\r
+61,\r
+62,\r
+63,\r
+64,\r
+65,\r
+66,\r
+67,\r
+68,\r
+69,\r
+70,\r
+71,\r
+72,\r
+73,\r
+74,\r
+75,\r
+76,\r
+77,\r
+78,\r
+79,\r
+80,\r
+81,\r
+82,\r
+83,\r
+84,\r
+85,\r
+86,\r
+87,\r
+88,\r
+89,\r
+90,\r
+91,\r
+92,\r
+93,\r
+94,\r
+95,\r
+96,\r
+97,\r
+98,\r
+99,\r
+100,\r
+101,\r
+102,\r
+103,\r
+104,\r
+105,\r
+106,\r
+107,\r
+108,\r
+109,\r
+110,\r
+111,\r
+112,\r
+113,\r
+114,\r
+115,\r
+116,\r
+117,\r
+118,\r
+119,\r
+120,\r
+121,\r
+122,\r
+123,\r
+124,\r
+125,\r
+126,\r
+127,\r
+128,\r
+129,\r
+130,\r
+131,\r
+132,\r
+133,\r
+134,\r
+135,\r
+136,\r
+137,\r
+138,\r
+139,\r
+140,\r
+141,\r
+142,\r
+143,\r
+144,\r
+145,\r
+146,\r
+147,\r
+148,\r
+149,\r
+150,\r
+};\r
+\r
+static const uint8_t touch_HRD[] = \r
+{\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+1,\r
+};\r
+\r
+static const int32_t Expo_time[][NF_PPG_PER_CHANNEL*NF_PPG_CHANNEL] = \r
+{\r
+{0, 256, 40},\r
+{0, 240, 40},\r
+{0, 224, 40},\r
+{0, 208, 40},\r
+{0, 208, 40},\r
+{0, 192, 40},\r
+{0, 184, 40},\r
+{0, 176, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+{0, 168, 40},\r
+};\r
+\r
+\r
+\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxialg.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxialg.h
new file mode 100644 (file)
index 0000000..ac2b98c
--- /dev/null
@@ -0,0 +1,698 @@
+#ifndef PXIALG_H__\r
+#define PXIALG_H__\r
+#include "stdint.h"\r
+#include "pxivar.h"\r
+\r
+#define FW                             1\r
+\r
+#define FW_DEBUG  0\r
+#if ( FW == 0 )\r
+#undef FW_DEBUG\r
+#define FW_DEBUG  0\r
+#endif\r
+\r
+//#define STRIIV\r
+\r
+#if FW == 1\r
+#define PXIALG_API\r
+#else\r
+#ifdef PXIALG_EXPORTS\r
+#define PXIALG_API             __declspec(dllexport)\r
+#else\r
+#define PXIALG_API             __declspec(dllimport)\r
+#endif\r
+#endif\r
+/*\r
+typedef struct {\r
+       uint8_t                                         frame_count;\r
+       uint32_t                                        time;\r
+       uint8_t                                         touch_flag;\r
+       uint32_t                                        nf_ppg_channel;\r
+       uint32_t                                        nf_ppg_per_channel;\r
+       int32_t                                         *ppg_data;\r
+       uint32_t                                        nf_mems;\r
+       int16_t                                         *mems_data;\r
+} pah8series_data_t;\r
+\r
+typedef enum {\r
+       FLAG_DATA_READY                         = 0,\r
+       FLAG_DATA_NOT_READY,\r
+       FLAG_DATA_LOSS,\r
+       FLAG_NO_TOUCH,\r
+       FLAG_DATA_ERROR,\r
+       FLAG_POOR_SIGNAL,\r
+       FLAG_FIFO_ERROR,\r
+       FLAG_TIMMING_ERROR,\r
+       FLAG_MEMS_ERROR,\r
+       FLAG_HR_UPDATE                          = 16,\r
+       FLAG_SG_UPDATE,\r
+} PXI_STATUS_FLAG;\r
+\r
+typedef enum {\r
+       _quick_report_rms_gs_th         = 0,\r
+       _hr_speed_mode,\r
+       _support_cal_motion_idx_enhancement_enh,\r
+       _rsv1,\r
+       _set_switch_mems_fft_max_energy_th,\r
+       _set_switch_mems_large_energy_num_th,\r
+       _set_switch_mn_fft_energy_lo_thr,\r
+       _set_switch_mn_fft_energy_hi_thr,\r
+\r
+       _ppg_large_energy_num_th,\r
+       _max_hr_idx_th,\r
+       _min_hr_idx_th,\r
+       _ppg_fft_total_peak_num_th,\r
+       _mems_large_energy_num_th,\r
+       _mems_fft_max_energy_th,\r
+       _support_signal_grade_motion_detection_enh,\r
+       _support_signal_grade_check_signal_lelvel_enh,\r
+       _support_signal_grade_large_energy_num_enh,\r
+       _rsv2,\r
+       _rsv3,\r
+       _set_reg_shake_count_th0,\r
+} PXI_PARAM_SET;\r
+\r
+typedef enum {\r
+       _rms_gs                                         = 0,\r
+       _signal_level,\r
+       _cal_motion_idx,\r
+       _is_prediction_hr,\r
+       _get_switch_mems_fft_max_energy_th,\r
+       _get_switch_mems_large_energy_num_th,\r
+       _get_switch_mn_fft_energy_lo_thr,\r
+       _get_switch_mn_fft_energy_hi_thr,\r
+\r
+       _hr_sample_count,\r
+       _ppg_large_energy_num,\r
+       _signal_grade_motion_frm,\r
+       _ppg_fft_max_energy_idx,\r
+       _ppg_fft_total_peak_num,\r
+       _mems_large_energy_num,\r
+       _mems_fft_max_energy,\r
+       _grade,\r
+       _signal_grade_hr_to_low_frm,\r
+       _flag_signal_grade_ready_go,\r
+       _motion_flag,\r
+       _get_reg_shake_count_th0,\r
+} PXI_PARAM_GET;\r
+\r
+typedef enum {\r
+       MemsLargeEnergyNumTh            = 0,\r
+       MemsFftMaxEnergyTh,\r
+       QuickReportRmsGsTh,\r
+       SupportSigGradeMotionDetection,\r
+       PpgLargeEnergyNumTh,\r
+       SupportSigGradeLargeEnergyNumEnh,\r
+       SupportSigGradeLargeEnergyNumTh,\r
+       SigGradeThr,\r
+       SupportSigGradeCheckSigLevel,\r
+       FlagCheckNotStableFirstHR,\r
+       MaxHrDefinition,\r
+       MinHrDefinition,\r
+} PXI_PARAM2;\r
+*/\r
+\r
+#if FW == 1\r
+/**\r
+ * @brief When HRD and MEMS data are ready, call this function to do the algorithm processing\r
+ *\r
+ * @param[in] HRD_Data   Pointer to the buffer where HRD data (13 Bytes) is stored.\r
+ * @param[in] MEMS_Data  Pointer to the buffer where MEMS data (3*sizeof(float) Bytes) is stored.\r
+ *\r
+ * @return Return one of the PXI_STATUS_FLAG types.\r
+ */\r
+PXIALG_API int32_t PxiAlg_ProcessByTime(unsigned char *HRD_Data, float *MEMS_Data, float time);\r
+PXIALG_API int32_t PxiAlg_Process(unsigned char *HRD_Data, float *MEMS_Data);\r
+\r
+/**\r
+ * @brief Call this function to get Heart Rate\r
+ *\r
+ * @param[out] hr   Pointer to a float variable where heart rate is stored\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_HrGet(float *hr);\r
+\r
+\r
+PXIALG_API void PxiAlg_FlagInitialSignalNoiseGet(uint8_t *flag);\r
+/**\r
+ * @brief Call this function to feed Algorithm raw data(19 Bytes), and get Signal Grade and Heart Rate\r
+ *\r
+ * @param[in] pixart_19_byte_data   Pointer to a arrag where raw data is stored\r
+ *     Format: 13 bytes PPG + G-sensor X_L[13] + X_H[14] + Y_L[15] + Y_H[16] + Z_L[17] + Z_H[18]\r
+ * @param[out] grade   Pointer to a float variable where signal grade is stored.\r
+ * @param[out] heart_rate   Pointer to a float variable where heart rate is stored\r
+ *\r
+ * @return status bit field, combinatoin of the list below\r
+ * 1 << FLAG_DATA_READY,\r
+ * 1 << FLAG_DATA_NOT_READY,\r
+ * 1 << FLAG_DATA_LOSS,\r
+ * 1 << FLAG_NO_TOUCH,\r
+ * 1 << FLAG_DATA_ERROR,\r
+ * 1 << FLAG_POOR_SIGNAL,\r
+ * 1 << FLAG_FIFO_ERROR,\r
+ * 1 << FLAG_TIMMING_ERROR,\r
+ * 1 << FLAG_MEMS_ERROR,\r
+ * 1 << FLAG_HR_UPDATE,\r
+ * 1 << FLAG_SG_UPDATE,\r
+ */\r
+PXIALG_API uint32_t PxiAlg_HRM(uint8_t *pixart_19_byte_data, float *grade, float * heart_rate);\r
+#else\r
+/**\r
+ * @brief When HRD, MEMS, and ECG data are ready, call this function to do the algorithm processing\r
+ *\r
+ * @param[in] HRD_Data   Pointer to the buffer where HRD data (13 Bytes) is stored.\r
+ * @param[in] MEMS_Data  Pointer to the buffer where MEMS data (12 Bytes) is stored.\r
+ * @param[in] ECG_Data   Pointer to the buffer where ECG data (4 Bytes) is stored.\r
+ *\r
+ * @return Return one of the PXI_STATUS_FLAG types.\r
+ */\r
+PXIALG_API int32_t PxiAlg_Process(unsigned char *HRD_Data, float *MEMS_Data, float ECG_Data);\r
+\r
+/**\r
+ * @brief When HRD, MEMS, ECG data, and time interval are ready, call this function to do the algorithm processing\r
+ *\r
+ * @param[in] HRD_Data   Pointer to the buffer where HRD data (13 Bytes) is stored.\r
+ * @param[in] MEMS_Data  Pointer to the buffer where MEMS data (12 Bytes) is stored.\r
+ * @param[in] ECG_Data   Pointer to the buffer where ECG data (4 Bytes) is stored.\r
+ * @param[in] time              Time interval.\r
+ *\r
+ * @return Return one of the PXI_STATUS_FLAG types.\r
+ */\r
+PXIALG_API int32_t PxiAlg_ProcessByTime(unsigned char *HRD_Data, float *MEMS_Data, float ECG_Data, float time);\r
+\r
+/**\r
+ * @brief Call this function to get Heart Rate\r
+ *\r
+ * @param[out] hr   Pointer to a float variable where heart rate is stored\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_HrGet(float *hr);\r
+\r
+PXIALG_API void PxiAlg_FlagInitialSignalNoiseGet(uint8_t *flag);\r
+\r
+/**\r
+ * @brief Call this            function to get output\r
+ *\r
+ * @param[out] output  Pointer to a SHr_motion_plot variable where output information is stored\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API int32_t PxiAlg_OutputGet(void *output);\r
+\r
+/**\r
+ * @brief Call this            function to get a specific parameter\r
+ *\r
+ * @param[out] param   Pointer to the start address of the variable of parameter list\r
+ * @param[in]  offset  Offset of the parameter variable\r
+ * @param[in]  size            Type size of the parameter\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_ParamGet(uint8_t *param, int32_t offset, int32_t size);\r
+\r
+/**\r
+ * @brief Call this            function to set a specific parameter\r
+ *\r
+ * @param[in] offset   Offset of the parameter variable\r
+ * @param[in] size             Type size of the parameter\r
+ * @param[in] param            Pointer to the start address of the variable of parameter list\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_ParamSet(int32_t offset, int32_t size, uint8_t *param);\r
+#endif\r
+\r
+/**\r
+* @brief When HRD, MEMS, and Expo data are ready, call this function to do the algorithm processing\r
+*\r
+* @param[in] HRD_Data   Pointer to the buffer where HRD data (13 Bytes) is stored.\r
+* @param[in] MEMS_Data  Pointer to the buffer where MEMS data (12 Bytes) is stored.\r
+* @param[in] expo       Exposure Time.\r
+*\r
+* @return Return one of the PXI_STATUS_FLAG types.\r
+*/\r
+PXIALG_API int32_t PxiAlg_Process_Expo(unsigned char *HRD_Data, float *MEMS_Data, int expo);\r
+\r
+/**\r
+ * @brief Call this function to determine the version of the algorithm\r
+ *\r
+ *\r
+ * @return Version of the algorithm\r
+ */\r
+PXIALG_API int32_t PxiAlg_Version(void);\r
+\r
+/**\r
+ * @brief Call this funtion to get Ready_Flag\r
+ *\r
+ * @return Return Ready_Flag\r
+ */\r
+PXIALG_API unsigned char PxiAlg_GetReadyFlag(void);\r
+\r
+/**\r
+ * @brief Call this funtion to get Motion_Flag\r
+ *\r
+ * @return Return Motion_Flag\r
+ */\r
+PXIALG_API unsigned char PxiAlg_GetMotionFlag(void);\r
+\r
+\r
+/**\r
+* @brief Call this function to get force flag\r
+*\r
+* @return force_flag\r
+*/\r
+PXIALG_API unsigned char PxiAlg_GetForceFlag(void);\r
+\r
+/**\r
+ * @brief Call this funtion to get Timeout_Flag\r
+ *\r
+ * @return Return Timeout_Flag\r
+ */\r
+PXIALG_API unsigned char PxiAlg_GetTimeoutFlag(void);\r
+\r
+/**\r
+ * @brief Call this function to set PPG buffer pointer and size\r
+ *\r
+ * @param[in] ppg_buffer   Pointer to a float buffer where the PPG data would be stored\r
+ * @param[in] size   PPG buffer size\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_SetPPGBuffer(float *ppg_buffer, int32_t size);\r
+\r
+/**\r
+ * @brief Call this function to set algorithm parameters\r
+ *\r
+ * @param[in] hr_param   Pointer to a "HR_Param" sturcture where the parameters are stored.\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_SetParam(void *hr_param);\r
+\r
+/**\r
+ * @brief Call this function to set data\r
+ *\r
+ * @param[in] data   Pointer to an algorithm-dependent data\r
+ *\r
+ * @return None\r
+ */\r
+PXIALG_API void PxiAlg_SetData(void *data);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the Output Data Rate of PPG Sensor\r
+ *\r
+ * @param[in] odr                      The Output Data Rate of PPG Sensor. Only 10,20,40,160 and 200 ODR are supported.\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetODR(int32_t odr);\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the Timeout Length of PPG Sensor\r
+ *\r
+ * @param[in] t                        The Timeout Length of PPG Sensor. Unit: second.\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetTimeoutLength(int32_t t);\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the Quality Threshold of PPG Sensor\r
+ *\r
+ * @param[in] th                       The Quality Threshold of PPG Sensor. Range: 0.0 ~ 1.0\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetQualityThreshold(float th);\r
+\r
+/**\r
+* @brief Call this function to notify algorithm the HR smooth weight of PPG Sensor\r
+*\r
+* @param[in] w                 The weight. Range: 0.0 ~ 1.0\r
+*\r
+* @return 1 for success. 0 for failure.\r
+*/\r
+PXIALG_API uint8_t PxiAlg_SetHRSmoothWeight(float w);\r
+\r
+/**\r
+* @brief Call this function to notify algorithm the length of process window of PPG Sensor\r
+*\r
+* @param[in] t                 The normal time window.\r
+* @param[in] t_fast            The fast time window.\r
+*\r
+* @return 1 for success. 0 for failure.\r
+*/\r
+PXIALG_API uint8_t PxiAlg_SetProcWindow(float t, float t_fast);\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the number of PPG sample to skip\r
+ *\r
+ * @param[in] num                      The number\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetSkipSampleNum(int num);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the MEMS Scale of Motion Sensor\r
+ *\r
+ * @param[in] scale                    The MEMS Scale of Motion Sensor. 0: +-2G, 1: +-4G, 2: +-8G, and 3: +-16G\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetMemsScale(int scale);\r
+PXIALG_API uint8_t PxiAlg_SetMemsScaleBase(int scale, int th);\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the time length to force hr to update\r
+ *\r
+ * @param[in] t                        The time length\r
+ * @param[in] ub               The upper bound\r
+ * @param[in] lb               The lower bound\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetForceOutput(int t, int ub, int lb);\r
+\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm force hr to output\r
+ *\r
+ * @param[in] t                        The time length\r
+ * @param[in] ub               The upper bound\r
+ * @param[in] lb               The lower bound\r
+ * @param[in] link_flag        To link with normal output\r
+ * @param[in] w                    Smoothing weight between force and normal\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetForceOutputLink(int t, int ub, int lb, int link_flag, float w);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm normal hr to output\r
+ *\r
+ * @param[in] ub                   The upper bound\r
+ * @param[in] lb                   The lower bound\r
+ * @param[in] static_flag      First normal output at static\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetNormalOutput(int ub, int lb, int static_flag);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the time to force hr to output\r
+ *\r
+ * @param[in] t                        The duration\r
+ * @param[in] bpm              The amplitude\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetForceRipple(int t, int bpm);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the time to force hr to output\r
+ *\r
+ * @param[in] ch               The ppg channel selection\r
+ * @param[in] flag             The resample flag\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetPackage(int ch, int flag);\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the time length to force hr to update\r
+ *\r
+ * @param[in] t                        The time length\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetForceUpdateTimeLength(int t);\r
+/**\r
+ * @brief Call this function to notify algorithm the time to force hr to output\r
+ *\r
+ * @param[in] t                        The time length\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetForceOutputTime(int t);\r
+/**\r
+ * @brief Call this function to notify algorithm the bound of hr\r
+ *\r
+ * @param[in] ub                       The upper bound\r
+ * @param[in] lb                       The lower bound\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetFullHRBound(int ub, int lb);\r
+/**\r
+ * @brief Call this function to notify algorithm the bound of first hr\r
+ *\r
+ * @param[in] ub                       The upper bound\r
+ * @param[in] lb                       The lower bound\r
+ * @param[in] t                        The time length to keep this bound\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetFirstHRBound(int ub, int lb, int t);\r
+\r
+\r
+\r
+/**\r
+ * @brief Call this function to notify algorithm the MEMS Energy Threshold of Motion Sensor\r
+ *\r
+ * @param[in] lower                    The MEMS energy lower threshold\r
+ * @param[in] upper                    The MEMS energy upper threshold\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetMemsEnergyThrd(int lower, int upper);\r
+\r
+/**\r
+ * @brief Call this function to set PPG Signal Grade Threshold\r
+ *\r
+ * @param[in] threshold                The PPG Signal Grade Threshold. Its value ranges from 0 to 100.\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetSigGradeThrd(float thrd);\r
+\r
+/**\r
+ * @brief Call this function to set parameters of PPG Signal Grade\r
+ *\r
+ * @param[in] frm_thrd         The PPG Signal Grade Frame Threshold.\r
+ * @param[in] rep_count                The PPG Signal Grade Repetitive Counter.\r
+ *\r
+ * @return 1 for success. 0 for failure.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_SetSigGradeParam(int16_t frm_thrd, int16_t rep_count);\r
+\r
+/**\r
+ * @brief Call this function to enable or disable fast output mode\r
+ *\r
+ * @param[in] en               The flag of fast output mode.\r
+ */\r
+\r
+PXIALG_API void PxiAlg_EnableFastOutput(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to enable or disable motion mode\r
+ *\r
+ * @param[in] en               The flag of motion mode.\r
+ */\r
+PXIALG_API void PxiAlg_EnableMotionMode(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to enable or disable auto mode\r
+ *\r
+ * @param[in] en               The flag of auto mode.\r
+ */\r
+PXIALG_API void PxiAlg_EnableAutoMode(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to enable or disable tracking mode after fast output\r
+ *\r
+ * @param[in] en               The flag of tracking mode.\r
+ */\r
+PXIALG_API void PxiAlg_EnableTrackingAfterFastOut(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to enable or disable mems0 signal grade mode\r
+ *\r
+ * @param[in] en               1 : enable. 0 : disable.\r
+ */\r
+PXIALG_API void PxiAlg_EnableMEMS0SigGrade(uint8_t en);\r
+\r
+//PXIALG_API void PxiAlg_EnableMEMS0SigGrade(uint8_t en, uint8_t idx);\r
+//// idx = 0: PxiAlg_EnableFastOutput(uint8_t en);\r
+//// idx = 1: PxiAlg_EnableMotionMode(uint8_t en);\r
+//// idx = 2: PxiAlg_EnableAutoMode(uint8_t en);\r
+//// idx = 3: PxiAlg_EnableTrackingAfterFastOut(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to get PPG Signal Grade\r
+ *\r
+ * @param[out] grade   Pointer to a float variable where signal grade is stored.\r
+ *\r
+ * @return  Return 1 when Signal Grade is ready. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_GetSigGrade(float *grade);\r
+\r
+/**\r
+ * @brief Call this function to get the alarm flag of fast output\r
+ *\r
+ * @param[out] flag            The alarm flag of fast output\r
+ *\r
+ * @return  Return 1 when the flag is set. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_GetFastOutAlarmFlag(void);\r
+\r
+/**\r
+ * @brief Call this function to get the alarm flag of signal bad\r
+ *\r
+ * @param[out] flag            The alarm flag of fast output\r
+ *\r
+ * @return  Return 1 when the flag is set. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_GetSignalBadAlarm(void);\r
+\r
+/**\r
+ * @brief Call this function to open algorithm\r
+ */\r
+#if FW == 1\r
+PXIALG_API uint8_t PxiAlg_Open_Mem(void *mem);\r
+#else\r
+PXIALG_API void PxiAlg_Open(void);\r
+#endif\r
+\r
+/**\r
+ * @brief Call this function to close algorithm\r
+ */\r
+PXIALG_API void PxiAlg_Close(void);\r
+\r
+/**\r
+ * @brief Call this function to initialize 200Hz low-pass filter\r
+ */\r
+PXIALG_API void PxiAlg_LPF200Hz_Init(void);\r
+\r
+/**\r
+ * @brief Call this function to process 200Hz low-pass filter\r
+ */\r
+PXIALG_API float PxiAlg_LPF200Hz_Process(float data);\r
+\r
+/**\r
+ * @brief Call this function to get PPG Signal Level\r
+ *\r
+ * @param[out] grade   Pointer to a float variable where signal level is stored.\r
+ *\r
+ * @return  Return 1 when Signal Level is ready. Otherwise, return 0.\r
+ */\r
+#ifndef REDUCE_MORE_CODE_SIZE\r
+PXIALG_API uint8_t PxiAlg_Get_Signal_Level(float *level);\r
+#endif\r
+/**\r
+ * @brief Call this function to enable/disable Check_Not_Stable_First_HR\r
+ *\r
+ * @param[in] 1 : enable, 0: disable\r
+ */\r
+PXIALG_API void PxiAlg_Check_Not_Stable_First_HR(uint8_t check); \r
+\r
+/**\r
+ * @brief Call this function to set Signal_Grade_Large_Energy_Num_Th_Lo\r
+ *\r
+ * @param[in] Threshold.\r
+ *\r
+ */\r
+PXIALG_API void PxiAlg_Set_Signal_Grade_Large_Energy_Num_Th_Lo(uint8_t th) ;\r
+\r
+/**\r
+ * @brief Call this function to Set SportMode\r
+ *\r
+ * @@param[in] en      0: disable 1: enable\r
+ *\r
+ * @return  Return 1 when Set Signal Grade Large Energy Num Threshold is ready. Otherwise, return 0.\r
+ */\r
+PXIALG_API void PxiAlg_SetSportMode(uint8_t en);\r
+\r
+/**\r
+ * @brief Call this function to Set Signal Grade Large Energy Num Threshold\r
+ *\r
+ * @@param[in] th      => threshold\r
+ *\r
+ * @return  Return 1 when Set Signal Grade Large Energy Num Threshold is ready. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_Set_Signal_Grade_Large_Energy_Num_Th(uint8_t th);\r
+\r
+\r
+/**\r
+ * @brief Call this function to Set Algorithm Parameters\r
+ *\r
+ * @@param[in] index - index of parameters, param - parameter value\r
+ *\r
+ * @return  Return 1 when Set algorithm parameter suceeessfully. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_Set_Parameter(uint32_t index, float param);\r
+\r
+/**\r
+ * @brief Call this function to Get Algorithm Parameters\r
+ *\r
+ * @@param[in] index - index of parameters, *param - pointer to parameter value\r
+ *\r
+ * @return  Return 1 when Set algorithm parameter suceeessfully. Otherwise, return 0.\r
+ */\r
+PXIALG_API uint8_t PxiAlg_Get_Parameter(uint32_t index, float *param);\r
+\r
+/**\r
+* @brief Call this function to Set Algorithm Parameters (2nd Version)\r
+*\r
+* @@param[in] index - index of parameters, param - parameter value\r
+*\r
+* @return  Return 1 when Set algorithm parameter suceeessfully. Otherwise, return 0.\r
+*/\r
+PXIALG_API uint8_t PxiAlg_Set_Parameter2(uint32_t index, float param);\r
+\r
+/**\r
+* @brief Call this function to Get Algorithm Parameters (2nd Version)\r
+*\r
+* @@param[in] index - index of parameters, *param - pointer to parameter value\r
+*\r
+* @return  Return 1 when Set algorithm parameter suceeessfully. Otherwise, return 0.\r
+*/\r
+PXIALG_API uint8_t PxiAlg_Get_Parameter2(uint32_t index, float *param);\r
+\r
+\r
+\r
+PXIALG_API uint8_t PxiAlg_Set_Cal_Flag_HR_Trust_Energy_Ratio(float fValue);\r
+PXIALG_API uint8_t PxiAlg_Set_Cal_Flag_HR_Trust_Large_Energy_Num_Th(uint16_t fValue);\r
+PXIALG_API uint8_t PxiAlg_Get_Cal_Flag_HR_Trust_Energy_Ratio(float *fValue);\r
+PXIALG_API uint8_t PxiAlg_Get_Cal_Flag_HR_Trust_Large_Energy_Num_Th(uint16_t *fValue);\r
+\r
+PXIALG_API uint8_t PxiAlg_Get_Flag_HR_Trust(uint8_t *flag);\r
+\r
+#if (ANDROID_JNI==1)\r
+PXIALG_API uint8_t PxiAlg_Get_ParameterName(uint32_t index, const char **param);\r
+#endif\r
+\r
+PXIALG_API uint8_t PxiAlg_DecodeProcess(uint32_t data, int touch_flag, float time_in);\r
+PXIALG_API uint8_t  PxiAlg_Entrance_0(pah8series_data_t *pah8series_data);\r
+PXIALG_API uint8_t  PxiAlg_Entrance(pah8series_data_t *pah8series_data);\r
+PXIALG_API uint8_t  PxiAlg_EntranceD(pah8series_data_t *pah8series_data);\r
+PXIALG_API uint32_t PxiAlg_Query_Mem_Size();\r
+PXIALG_API uint8_t PxiAlg_GetHrUpdateFlag();\r
+\r
+PXIALG_API void PxiAlg_SetData_Seg(pah8series_data_t *pah8series_data);\r
+PXIALG_API uint8_t PxiAlg_Process_Seg(uint8_t *is_finished);\r
+PXIALG_API uint8_t PxiAlg_ProcessD_Seg(uint8_t *is_finished);\r
+#endif /* PXIALG_H__ */\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxivar.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/pxivar.h
new file mode 100644 (file)
index 0000000..0f1dd76
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef PXIVAR_H__\r
+#define PXIVAR_H__\r
+\r
+#include "stdint.h"\r
+\r
+#ifndef pah8series_data_t\r
+typedef struct {\r
+       uint8_t                                         frame_count;\r
+       uint32_t                                        time;\r
+       uint8_t                                         touch_flag;\r
+       uint32_t                                        nf_ppg_channel;\r
+       uint32_t                                        nf_ppg_per_channel;\r
+       int32_t                                         *ppg_data;\r
+       uint32_t                                        nf_mems;\r
+       int16_t                                         *mems_data;\r
+} pah8series_data_t;\r
+#endif\r
+\r
+typedef enum {\r
+       FLAG_DATA_READY                         = 0,\r
+       FLAG_DATA_NOT_READY,\r
+       FLAG_DATA_LOSS,\r
+       FLAG_NO_TOUCH,\r
+       FLAG_DATA_ERROR,\r
+       FLAG_POOR_SIGNAL,\r
+       FLAG_FIFO_ERROR,\r
+       FLAG_TIMMING_ERROR,\r
+       FLAG_MEMS_ERROR,\r
+       FLAG_HR_UPDATE                          = 16,\r
+       FLAG_SG_UPDATE,\r
+} PXI_STATUS_FLAG;\r
+\r
+typedef enum {\r
+       _quick_report_rms_gs_th         = 0,\r
+       _hr_speed_mode,\r
+       _support_cal_motion_idx_enhancement_enh,\r
+       _rsv1,\r
+       _set_switch_mems_fft_max_energy_th,\r
+       _set_switch_mems_large_energy_num_th,\r
+       _set_switch_mn_fft_energy_lo_thr,\r
+       _set_switch_mn_fft_energy_hi_thr,\r
+\r
+       _ppg_large_energy_num_th,\r
+       _max_hr_idx_th,\r
+       _min_hr_idx_th,\r
+       _ppg_fft_total_peak_num_th,\r
+       _mems_large_energy_num_th,\r
+       _mems_fft_max_energy_th,\r
+       _support_signal_grade_motion_detection_enh,\r
+       _support_signal_grade_check_signal_lelvel_enh,\r
+       _support_signal_grade_large_energy_num_enh,\r
+       _rsv2,\r
+       _rsv3,\r
+       _set_reg_shake_count_th0,\r
+} PXI_PARAM_SET;\r
+\r
+typedef enum {\r
+       _rms_gs                                         = 0,\r
+       _signal_level,\r
+       _cal_motion_idx,\r
+       _is_prediction_hr,\r
+       _get_switch_mems_fft_max_energy_th,\r
+       _get_switch_mems_large_energy_num_th,\r
+       _get_switch_mn_fft_energy_lo_thr,\r
+       _get_switch_mn_fft_energy_hi_thr,\r
+\r
+       _hr_sample_count,\r
+       _ppg_large_energy_num,\r
+       _signal_grade_motion_frm,\r
+       _ppg_fft_max_energy_idx,\r
+       _ppg_fft_total_peak_num,\r
+       _mems_large_energy_num,\r
+       _mems_fft_max_energy,\r
+       _grade,\r
+       _signal_grade_hr_to_low_frm,\r
+       _flag_signal_grade_ready_go,\r
+       _motion_flag,\r
+       _get_reg_shake_count_th0,\r
+} PXI_PARAM_GET;\r
+\r
+typedef enum {\r
+       MemsLargeEnergyNumTh            = 0,\r
+       MemsFftMaxEnergyTh,\r
+       QuickReportRmsGsTh,\r
+       SupportSigGradeMotionDetection,\r
+       PpgLargeEnergyNumTh,\r
+       SupportSigGradeLargeEnergyNumEnh,\r
+       SupportSigGradeLargeEnergyNumTh,\r
+       SigGradeThr,\r
+       SupportSigGradeCheckSigLevel,\r
+       FlagCheckNotStableFirstHR,\r
+       MaxHrDefinition,\r
+       MinHrDefinition,\r
+} PXI_PARAM2;\r
+\r
+#endif /* PXIVAR_H__ */\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/test_library_HRD.c b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_hr/V303009/test_library_HRD.c
new file mode 100644 (file)
index 0000000..7085701
--- /dev/null
@@ -0,0 +1,112 @@
+\r
+#include "pah8009_testpattern_HRD.h"\r
+// platform\r
+#include <stdlib.h>\r
+#include "pah800x_main.h"\r
+#include "pah800x_bsp.h"\r
+#include <math.h>  \r
+//#include "nrf_delay.h"\r
+#define array_szie(arr) (sizeof(arr) / sizeof(arr[0]))\r
+\r
+\r
+\r
+\r
+void test_library_HRD(void)\r
+{\r
+       int i               = 0;\r
+  void *hr_pBuffer = NULL;\r
+       static ppg_mems_data_t ppg_mems_data_alg;\r
+\r
+       sRaw_Data_13Bytes hr_data;\r
+                \r
+       \r
+       // static  Hr-V301009\r
+               \r
+               PxiAlg_Close();\r
+               int32_t version = PxiAlg_Version();\r
+               DEBUG_PRINT("HR_Version = %d \r\n", version);\r
+       \r
+\r
+               uint32_t Query_Mem_Size = PxiAlg_Query_Mem_Size();\r
+               DEBUG_PRINT("HR_Mem_Size = %d \r\n", Query_Mem_Size);\r
+               \r
+               hr_pBuffer = malloc(Query_Mem_Size);\r
+               \r
+   \r
+               if(!PxiAlg_Open_Mem(hr_pBuffer))\r
+                               DEBUG_PRINT("PxiAlg_Open_Mem fail \n");\r
+       \r
+                       \r
+               PxiAlg_SetQualityThreshold(0.35f); \r
+               PxiAlg_SetHRSmoothWeight(0.9f); \r
+               PxiAlg_SetProcWindow(5.0f, 5.0f); \r
+         PxiAlg_SetTimeoutLength(30.0f);\r
+               PxiAlg_SetMemsScale(1);               //MEMS 2/4/8/16G : 0/1/2/3\r
+               PxiAlg_SetSkipSampleNum(10); \r
+               PxiAlg_SetMemsScaleBase(1, 0);  //MEMS 2/4/8/16G : 0/1/2/3\r
+               PxiAlg_SetForceOutputLink(0, 150, 40, 1, 0.9f); \r
+               PxiAlg_SetNormalOutput(200, 40, 0); \r
+               PxiAlg_SetForceRipple(3, 1); \r
+    //PxiAlg_SetForceOutput(30, 120, 45);\r
+               //PxiAlg_SetForceOutputTime(10);\r
+               PxiAlg_SetPackage(0, 1);\r
+       \r
+       \r
+         \r
+//-----------------------------------------------//\r
+          \r
+               LOG_PRINT("ARRAY_SIZE = %d\n",array_szie(PAH8009_rawdata_HRD));\r
+//******************************************************************            \r
+          \r
+               float   hr         = 0.0f;\r
+               float   hr_grader  = 0.0f;\r
+         \r
+//*******************************************************************           \r
+                \r
+          //nrf_delay_ms(50);\r
+                \r
+\r
+               for( i = 0 ; i <array_szie(PAH8009_rawdata_HRD) ; i ++)\r
+               {\r
+                         \r
+                                               memset(&hr_data, 0, sizeof(hr_data));\r
+                       hr_data.loss        = 1;\r
+                       hr_data.rawData     = (uint32_t)PAH8009_rawdata_HRD[i][1] ;\r
+                                   //LOG_PRINT("rawData = %d \n ", hr_data.rawData);\r
+                       hr_data.non_zero1   = 1;\r
+                       hr_data.non_zero2   = 2;\r
+                       hr_data.non_zero3   = 3;\r
+                       hr_data.frame_count = frame_HRD[i];\r
+                                               //LOG_PRINT("frame_count = %d  ", hr_data.frame_count);\r
+                       hr_data.time        = duration_HRD[i];  \r
+                                               //LOG_PRINT("time = %d  ", hr_data.time);\r
+                       hr_data.rsv         = 0;\r
+                       hr_data.touch       = touch_HRD[i] > 0 ? 0x80 : 0x00;\r
+                                               //LOG_PRINT("touch = %d  ", hr_data.touch);\r
+                       hr_data.rsv2        = 0;\r
+\r
+                                               int exposure_time      = Expo_time[i][1];\r
+            //LOG_PRINT("exposure_time = %d  \n",exposure_time);\r
+\r
+                                               ppg_mems_data_alg.MEMS_Data[0]=PAH8009_mems_HRD[i][0];\r
+                                               ppg_mems_data_alg.MEMS_Data[1]=PAH8009_mems_HRD[i][1]; \r
+                                               ppg_mems_data_alg.MEMS_Data[2]=PAH8009_mems_HRD[i][2]; \r
+                                               \r
+                                               int32_t ret = PxiAlg_Process_Expo((uint8_t*)&hr_data, ppg_mems_data_alg.MEMS_Data, exposure_time);\r
+\r
+            //LOG_PRINT("ret_HR %d  \n",ret);\r
+\r
+                                               if(PxiAlg_GetHrUpdateFlag())\r
+                                               {\r
+                                                       PxiAlg_HrGet(&hr);\r
+                                                       PxiAlg_GetSigGrade(&hr_grader);\r
+                                               }\r
+\r
+                                               LOG_PRINT("ret  %d  , hr  %f ,  hr_grade  %f  \n", ret,  hr, hr_grader);\r
+                        \r
+               }\r
+        \r
+    PxiAlg_Close();\r
+\r
+    return;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/libv703_0_1.a b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/libv703_0_1.a
new file mode 100644 (file)
index 0000000..0cb0d3b
Binary files /dev/null and b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/libv703_0_1.a differ
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pah8009_testpattern_SPO2.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pah8009_testpattern_SPO2.h
new file mode 100644 (file)
index 0000000..d8d9d49
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef _PAH8009_TESTPATTERN_\r
+#define _PAH8009_TESTPATTERN_\r
+\r
+#include <stdint.h>\r
+#define NF_PPG_CHANNEL 2\r
+#define NF_PPG_PER_CHANNEL 81\r
+static const int32_t PAH8009_rawdata_SPO2[][NF_PPG_PER_CHANNEL*NF_PPG_CHANNEL] = \r
+{\r
+{1,44,1413227,1375343,1847643,1787527,1849059,1795619,1850643,1799035,1853773,1804053,1855985,1807487,1857211,1810045,1858155,1811489,1857549,1810013,1856203,1807653,1855885,1807985,1856225,1808433,1856443,1808915,1856873,1809501,1856415,1809469,1856153,1808027,1854979,1805393,1853881,1804191,1853475,1803313,1853703,1803495,1853817,1804027,1852163,1801415},\r
+{1,50,1849833,1797659,1848117,1794425,1846501,1792429,1846933,1794465,1848347,1797081,1847485,1795507,1845053,1791709,1845377,1792531,1845089,1792009,1844055,1790507,1844639,1792275,1845127,1792257,1844247,1791883,1845803,1795625,1848153,1799679,1848469,1799821,1847757,1799101,1847791,1798791,1847717,1799383,1847285,1799295,1846165,1798421,1846711,1799119,1846979,1800181,1847917,1802373,1850389,1806013},\r
+{1,54,1851247,1807949,1852643,1810447,1854655,1814097,1856243,1816695,1856223,1816223,1855313,1814589,1854833,1813203,1854871,1813909,1855589,1815461,1855909,1816625,1856441,1816653,1856433,1816745,1856403,1816085,1854765,1813617,1853649,1811729,1853635,1812979,1854253,1814335,1854801,1814861,1855735,1817119,1856677,1818893,1856001,1817823,1855067,1815591,1854373,1814907,1853907,1813719,1852421,1811229,1851319,1809519,1850537,1808687},\r
+{1,54,1850007,1808285,1850491,1808867,1851353,1810153,1850677,1808535,1849503,1806183,1847779,1803439,1845305,1798249,1842229,1794125,1841311,1792951,1840299,1790817,1839801,1790775,1839609,1791541,1840653,1792959,1840111,1792037,1838781,1789819,1838071,1788025,1837549,1786829,1837177,1786199,1834709,1782813,1835469,1783903,1837155,1788265,1838507,1791097,1839841,1792945,1841147,1795599,1842109,1797251,1842343,1798043,1843101,1799101},\r
+{1,52,1843105,1799891,1843259,1800647,1843283,1801331,1842971,1800695,1843171,1800911,1843061,1801429,1843091,1801291,1843385,1801803,1843243,1802025,1843955,1803115,1845053,1804645,1844847,1804419,1844275,1802959,1844563,1803241,1844051,1802191,1844389,1802653,1844789,1803795,1845123,1804267,1845465,1804429,1845769,1804835,1845421,1804775,1844911,1804409,1844629,1804201,1844617,1804613,1845049,1804889,1845049,1805099},\r
+{1,54,1845203,1805421,1844861,1805319,1845265,1805971,1845519,1806249,1845809,1806711,1845999,1807367,1846361,1807837,1846561,1808147,1847089,1809035,1847853,1810107,1848437,1811271,1848687,1811447,1848663,1811475,1848819,1811293,1848815,1811405,1847765,1810337,1847277,1809779,1847415,1809381,1846875,1808739,1846289,1808049,1846243,1807663,1846263,1807911,1845817,1807357,1845631,1807343,1845983,1807737,1846023,1807371,1845827,1807367},\r
+{1,52,1846061,1807943,1845723,1807769,1845883,1807671,1845831,1807777,1845765,1807449,1845733,1807487,1845631,1807823,1845133,1806927,1844505,1806271,1844083,1805967,1843839,1805569,1843705,1805473,1844097,1806027,1844243,1806141,1844395,1806617,1844113,1806423,1844341,1806709,1844363,1807205,1844527,1807439,1844603,1807187,1844567,1807015,1844563,1806931,1844247,1806691,1844457,1806229,1844533,1806451,1844537,1806307},\r
+{1,52,1844555,1806299,1843955,1806475,1843797,1805597,1843233,1805593,1843451,1805647,1843265,1805505,1843037,1805499,1843121,1805159,1843229,1805383,1843029,1804627,1843313,1805051,1843019,1805145,1843261,1804877,1842989,1804949,1842807,1804521,1843091,1805135,1843381,1805241,1843323,1805171,1843523,1805439,1843737,1805711,1843861,1806105,1843411,1806039,1842957,1805241,1842411,1804437,1842521,1804595,1842225,1804201},\r
+{1,54,1842265,1804225,1842225,1804141,1842091,1803731,1842001,1803837,1842331,1804307,1842349,1804483,1842811,1805057,1842709,1804691,1842997,1805397,1843061,1805025,1843003,1805237,1843179,1805291,1843309,1804907,1843287,1805309,1843237,1805263,1843353,1805513,1843121,1805413,1842015,1803891,1841531,1803513,1841903,1804169,1841713,1803343,1841855,1803643,1841597,1803495,1841721,1803983,1841979,1804191,1841961,1804663,1842237,1805463},\r
+{1,52,1842841,1805611,1843219,1805829,1843215,1806035,1843643,1806543,1843665,1807081,1844097,1807349,1844393,1807677,1844555,1808157,1844457,1808143,1845213,1809151,1844893,1808913,1844453,1808725,1844261,1808397,1844083,1808377,1844029,1807939,1843945,1807671,1843379,1807363,1843327,1806831,1843163,1806443,1842717,1806451,1842935,1806207,1842847,1806623,1843341,1806843,1843117,1806631,1842887,1806461,1843239,1806761},\r
+{1,52,1843491,1806813,1843455,1807039,1843207,1806913,1843179,1806881,1843535,1806961,1842847,1806401,1842167,1805047,1842027,1804743,1841633,1804475,1841295,1803827,1841263,1803435,1840961,1803563,1840957,1803337,1841055,1803563,1840755,1803551,1841335,1804649,1842085,1805085,1842247,1805269,1842033,1805263,1842063,1805325,1842263,1805527,1842563,1805681,1843101,1806203,1843291,1806545,1844207,1808087,1844433,1808143},\r
+{1,54,1844493,1808715,1843847,1808245,1844033,1809131,1844385,1809343,1844457,1808979,1844433,1808869,1844073,1808139,1843385,1807065,1843145,1806497,1843803,1807307,1843051,1806933,1844003,1809509,1845831,1812717,1847551,1816579,1851097,1823331,1860321,1839875,1866743,1849125,1865911,1843927,1860507,1835367,1859875,1834775,1858871,1833191,1857559,1830255,1854361,1824619,1852367,1821855,1851795,1820705,1850731,1818609,1850629,1818733},\r
+{1,52,1852007,1822665,1852347,1822961,1851195,1820025,1850279,1817891,1848753,1815595,1847853,1814407,1847935,1814333,1848401,1816057,1848725,1816107,1848753,1815591,1848549,1815471,1848717,1815887,1849229,1816815,1848961,1816479,1848807,1815707,1847681,1814379,1846801,1812689,1846111,1810819,1843763,1806849,1840543,1801615,1839751,1801757,1840755,1802973,1841277,1804533,1840179,1802529,1840005,1801457,1840333,1802113},\r
+{1,52,1839583,1800437,1838631,1799091,1838427,1799267,1839369,1800713,1839779,1801687,1840619,1804035,1841259,1804479,1841405,1804525,1841135,1804127,1841249,1804447,1840529,1804373,1840391,1804179,1839897,1803301,1839635,1802829,1839387,1802491,1839369,1802159,1839377,1802149,1839271,1801763,1839453,1802063,1839409,1802091,1839343,1802141,1839449,1802299,1839911,1802955,1840165,1803041,1840579,1803235,1840957,1803901},\r
+{1,54,1840957,1804053,1841015,1804355,1841415,1804557,1841627,1805273,1841847,1805861,1841179,1805361,1841343,1805159,1841357,1805579,1841353,1805249,1841153,1805343,1841231,1805547,1841491,1805587,1841633,1806263,1841685,1806429,1841651,1806705,1842211,1807541,1842779,1807939,1843069,1808897,1843483,1809417,1843837,1809717,1844225,1810343,1844371,1811299,1844701,1811483,1845013,1811833,1845563,1812531,1845239,1812135,1844749,1811935},\r
+{1,52,1844875,1812555,1844835,1812143,1844691,1811903,1844741,1811959,1844491,1811669,1844505,1811673,1844443,1811543,1844435,1811445,1844101,1811371,1844163,1811027,1844233,1811177,1843949,1811133,1844233,1811133,1844221,1811021,1844069,1810507,1844051,1810775,1844061,1810745,1844051,1810749,1843349,1810309,1842981,1809331,1842705,1809183,1842441,1808973,1842451,1808739,1842345,1808835,1842219,1808761,1842411,1808559},\r
+{1,54,1842157,1808645,1842139,1808919,1842389,1808895,1842463,1808749,1842335,1808767,1842407,1808839,1842527,1808295,1842543,1808405,1842563,1808735,1842229,1808049,1842567,1808585,1842535,1808383,1842411,1808495,1841747,1807763,1841427,1807067,1841277,1807089,1841295,1807213,1840813,1806619,1840951,1806783,1841151,1807095,1841019,1806927,1841053,1807181,1840885,1807043,1841227,1806959,1841073,1807035,1841063,1807181,1841215,1807417},\r
+{1,52,1841459,1807145,1841449,1807199,1841393,1807067,1841415,1806979,1841509,1807187,1841507,1807269,1841729,1807481,1840863,1806965,1840663,1806083,1840347,1805851,1840275,1805935,1840177,1805587,1839961,1805841,1840045,1805471,1839875,1805569,1840161,1805727,1840281,1805785,1840409,1805607,1840463,1806087,1840779,1806397,1840677,1806737,1841009,1806767,1841183,1807029,1841241,1807131,1841197,1807195,1841343,1807293},\r
+{1,52,1841673,1807403,1841477,1807223,1841063,1806543,1840397,1806369,1840027,1805805,1839885,1805675,1839769,1805283,1839823,1804973,1839867,1805033,1839169,1804963,1839217,1805009,1839599,1804875,1839439,1805443,1839685,1805367,1839583,1804599,1839377,1804201,1839027,1803559,1838803,1803089,1838555,1802459,1837971,1801073,1837439,1800159,1837599,1801079,1837897,1801331,1836701,1799857,1836455,1800321,1837069,1801853},\r
+{1,54,1837643,1802797,1837269,1801951,1836379,1801137,1836025,1799811,1835379,1799317,1835171,1798263,1834655,1798043,1834249,1797073,1833925,1796527,1833769,1796001,1833431,1795583,1833475,1795783,1833499,1795867,1832885,1794835,1832697,1794735,1832605,1794313,1832151,1793511,1832045,1793463,1831047,1792143,1830137,1791131,1829695,1790225,1829007,1789429,1829437,1789379,1828881,1789107,1828783,1789009,1829103,1789001,1828851,1789125},\r
+{1,52,1829207,1789139,1829051,1789453,1829331,1789623,1829469,1789449,1829407,1788433,1828309,1786533,1827885,1785401,1826885,1783253,1826359,1782583,1826343,1783151,1825813,1781565,1824831,1780531,1824051,1779917,1823559,1779967,1823461,1779837,1824221,1781705,1824447,1781357,1823893,1781117,1823901,1780941,1823883,1781123,1824131,1780957,1823839,1781045,1823811,1780333,1823719,1780059,1823785,1780587,1824243,1781293},\r
+{1,52,1824133,1781279,1824061,1781059,1823835,1780387,1823857,1779837,1823781,1780479,1823985,1780725,1823713,1780581,1822647,1779399,1822121,1779229,1822219,1779113,1821779,1778493,1822043,1779141,1822127,1779127,1822081,1779237,1822189,1779195,1822481,1779691,1822655,1779935,1823117,1780235,1823349,1780897,1823763,1780883,1823977,1781445,1823793,1780467,1823777,1780327,1823715,1780481,1823367,1779621,1823461,1779755},\r
+{1,52,1823465,1779557,1823283,1779347,1822891,1778737,1822153,1778157,1821487,1777481,1821353,1777227,1821121,1777199,1820645,1776801,1820579,1775975,1820005,1775847,1820139,1775845,1819555,1774539,1818991,1774099,1819245,1774247,1818719,1773383,1818675,1773563,1818791,1774507,1819827,1776039,1819635,1775619,1819863,1775813,1819399,1774935,1819159,1774599,1818537,1773767,1818973,1773683,1817563,1772195,1816719,1771193},\r
+{1,54,1816439,1770893,1816497,1770653,1816021,1770379,1815945,1769969,1816019,1769913,1815701,1769797,1815695,1769489,1815829,1769099,1814869,1769189,1815429,1769169,1815005,1768841,1815127,1768777,1814807,1768449,1815069,1768503,1814833,1768411,1814667,1768117,1814673,1767747,1814187,1767043,1814171,1766827,1813321,1765607,1812461,1764623,1811547,1763381,1811347,1762825,1811605,1763061,1811461,1763159,1811267,1763141,1811417,1763043},\r
+{1,52,1811207,1763505,1811399,1763381,1811279,1762695,1811127,1762769,1810949,1762285,1810439,1761947,1810625,1762151,1810679,1761753,1810119,1760941,1810021,1760303,1809585,1760031,1809807,1759923,1809531,1760353,1810315,1761195,1809123,1759887,1809127,1759245,1808331,1757739,1807961,1757407,1807691,1756865,1807641,1756431,1806881,1754813,1805857,1753145,1805035,1752749,1805217,1752675,1804987,1752327,1804667,1752295},\r
+{1,52,1804585,1751465,1803327,1749265,1803413,1749487,1803309,1749749,1803243,1749473,1803393,1750037,1803025,1749159,1802261,1747897,1801561,1747231,1800863,1746159,1799649,1745263,1799405,1744755,1798743,1743721,1798005,1742265,1798061,1742259,1797767,1741831,1796901,1740061,1796891,1740181,1796599,1739815,1798083,1743175,1799139,1743641,1798311,1742347,1797813,1740889,1797559,1740953,1799387,1743481,1798947,1742593},\r
+{1,54,1799303,1742917,1799445,1742663,1799517,1743083,1799889,1743079,1799733,1743379,1799933,1743517,1799961,1743591,1800597,1744391,1801647,1745711,1802941,1747685,1803389,1748443,1804265,1749357,1804725,1750605,1805401,1751169,1806089,1752397,1806809,1754191,1807241,1754333,1807415,1755207,1808975,1757327,1809331,1757363,1809041,1757489,1809379,1758127,1809705,1759277,1809865,1759227,1808869,1757333,1808459,1757331,1808091,1756473},\r
+{1,52,1807045,1755147,1807231,1755243,1806873,1755451,1806761,1754827,1806757,1754295,1806217,1753817,1806027,1753769,1806401,1754069,1806711,1754661,1806859,1755233,1806933,1755225,1807365,1755345,1807071,1755757,1807251,1755761,1807623,1756141,1807495,1756057,1807387,1755677,1807371,1755835,1807757,1756141,1807543,1755461,1806361,1754421,1805533,1753405,1805511,1753201,1805605,1753187,1805401,1752729,1805263,1752781},\r
+{1,52,1805613,1752315,1805137,1752665,1805399,1752813,1805449,1753159,1805729,1753197,1806223,1753723,1806507,1754129,1806973,1754699,1807193,1755253,1807833,1755965,1808139,1756455,1808989,1757391,1809501,1758191,1809683,1758837,1810497,1759453,1810839,1760163,1810781,1760455,1810839,1760599,1811329,1761517,1812057,1762755,1811983,1762155,1812405,1762877,1812733,1763441,1813155,1764143,1812799,1763593,1812693,1763099},\r
+{1,54,1812481,1762807,1812405,1762063,1812249,1761607,1812057,1761435,1812155,1761647,1811813,1761203,1811925,1761757,1811969,1761647,1811403,1761043,1811723,1761365,1810887,1760215,1810353,1759897,1809919,1759359,1809891,1759121,1809359,1758787,1809403,1758791,1808939,1757795,1808829,1757503,1808451,1756935,1808371,1756989,1808229,1756681,1807947,1755785,1807993,1756061,1807975,1755867,1807775,1755789,1807797,1755511,1807659,1754985},\r
+{1,52,1807571,1755303,1808317,1755933,1807913,1755669,1807827,1755669,1807589,1755723,1807089,1755683,1807089,1755355,1806965,1755235,1806689,1754925,1806067,1754607,1806019,1754393,1805933,1754103,1805657,1753807,1805565,1753949,1805707,1753847,1805747,1754023,1805729,1753903,1805827,1754413,1805801,1754563,1805921,1754255,1805897,1754011,1805921,1754429,1805871,1754121,1805919,1754323,1805671,1754277,1805263,1754413},\r
+{1,52,1805209,1754227,1805897,1755557,1806035,1755549,1806173,1755697,1806917,1756611,1806969,1757139,1806929,1757599,1807535,1758705,1807847,1759115,1807765,1758737,1807761,1759143,1808165,1759313,1807975,1758823,1807067,1757647,1807303,1758459,1807947,1759133,1807415,1758703,1807023,1758117,1805867,1757439,1805501,1756357,1805079,1756339,1804715,1755955,1804569,1756201,1804279,1755947,1804421,1756037,1804527,1756601},\r
+{1,52,1804421,1756603,1804003,1756661,1804229,1756589,1804137,1756763,1804239,1756745,1804127,1756897,1803851,1756615,1803973,1756601,1804061,1756971,1803985,1757065,1803905,1757175,1803039,1756335,1802317,1755469,1802149,1755613,1801841,1755233,1801673,1754699,1801405,1755127,1801317,1755405,1801865,1755553,1801775,1755783,1802007,1756199,1802047,1756413,1802665,1757401,1802757,1758035,1802861,1758265,1803333,1758617},\r
+{1,54,1803509,1759013,1803501,1758825,1803795,1759225,1803461,1759059,1802741,1758075,1801625,1757051,1801379,1756855,1801095,1756713,1801011,1756625,1800729,1756575,1800587,1757069,1800615,1757869,1800587,1757725,1801113,1758269,1801113,1758713,1800655,1757585,1799911,1756633,1799735,1756663,1800747,1757825,1800325,1756675,1799329,1755123,1799205,1755179,1799257,1755341,1798751,1755963,1798707,1756185,1798551,1755997,1797879,1755225},\r
+{1,52,1797367,1754219,1796909,1753631,1796335,1752809,1796371,1753193,1796439,1752919,1795339,1751653,1795025,1751049,1794957,1751515,1795433,1752569,1795659,1753511,1795905,1753413,1796083,1754171,1795839,1753729,1795621,1753535,1795993,1754393,1795527,1754129,1795243,1754023,1794505,1753095,1794037,1752227,1793841,1752365,1794041,1752597,1794273,1753441,1794505,1753691,1794229,1753579,1794331,1753715,1794029,1753835},\r
+{1,52,1794295,1753793,1793707,1753123,1793787,1753483,1793619,1753311,1793601,1753293,1793553,1753311,1794067,1753995,1794167,1754753,1794223,1754135,1794091,1754389,1793681,1753663,1792693,1752901,1792507,1753105,1792355,1753073,1792199,1753371,1792045,1752957,1792649,1753473,1792303,1753857,1792405,1753733,1792671,1753691,1792351,1753631,1793255,1754989,1794139,1756167,1794665,1757393,1795615,1759015,1797051,1760923},\r
+{1,54,1797991,1762359,1798559,1763421,1799031,1764405,1799703,1764909,1799057,1764355,1798547,1763805,1798737,1763389,1798591,1763057,1798417,1762189,1797965,1761883,1797911,1762243,1798551,1762849,1797751,1761471,1797311,1760659,1797417,1760673,1797075,1760535,1797289,1760857,1797417,1760483,1797421,1760539,1797065,1760297,1797083,1760017,1796897,1760843,1797111,1760641,1796375,1759817,1796065,1759407,1795299,1758599,1794891,1757997},\r
+{1,52,1795229,1758153,1794979,1758241,1794927,1758215,1794753,1758163,1794531,1757951,1794695,1758301,1794971,1758681,1794939,1758113,1794869,1757941,1794863,1758579,1794913,1758357,1795135,1758257,1795121,1758229,1795145,1758331,1795241,1758783,1795439,1758945,1795717,1758843,1795145,1758755,1794829,1758243,1794325,1757997,1794269,1757651,1793837,1757147,1793867,1756763,1793707,1756767,1793947,1756901,1793907,1757069},\r
+{1,52,1793863,1757511,1794237,1757447,1794113,1757077,1794527,1757489,1794525,1757479,1794553,1757143,1794273,1757065,1794167,1756233,1794219,1755963,1793971,1756111,1794189,1755799,1794015,1755489,1793939,1755603,1793237,1755003,1793173,1755039,1793027,1755271,1793255,1755335,1793263,1755113,1793111,1755211,1793295,1754985,1792939,1754713,1793013,1754815,1793161,1754861,1793095,1754365,1792969,1754167,1793191,1754639},\r
+{1,54,1793451,1754383,1793197,1754107,1793031,1753455,1793121,1753197,1792693,1752887,1792279,1751911,1792253,1752093,1792703,1752489,1792099,1752093,1791591,1751783,1791697,1752701,1792059,1752601,1792155,1752739,1792431,1752761,1792067,1752901,1792537,1753275,1792721,1753297,1792775,1753497,1793449,1753821,1793771,1754181,1794665,1754975,1795037,1755147,1795439,1756265,1796243,1757069,1796545,1757719,1797129,1757675,1797421,1757989},\r
+{1,52,1797827,1758691,1797973,1759365,1797889,1759835,1797707,1759929,1798089,1760553,1797719,1759745,1797963,1760145,1798387,1760733,1797475,1759877,1797719,1760201,1797945,1760113,1797449,1759531,1797545,1758953,1797247,1759083,1797243,1759055,1797479,1758935,1797465,1759611,1797809,1759615,1797825,1760007,1798013,1760127,1798061,1760455,1798125,1760327,1798311,1760599,1798243,1760345,1797265,1759101,1797247,1759037},\r
+{1,58,1797381,1759389,1797111,1758861,1797007,1758981,1796897,1758719,1796803,1758561,1796629,1758353,1796679,1758385,1796871,1758779,1796733,1758215,1796683,1758241,1796821,1758251,1796949,1758399,1797217,1757969,1797221,1758569,1797319,1758283,1797675,1758897,1797475,1758991,1797933,1759147,1797947,1759319,1797337,1758603,1797155,1758227,1797247,1758575,1797071,1758301,1796851,1758195,1797163,1758279,1796999,1758539,1797443,1758195,1797407,1758985,1797523,1759019},\r
+{1,54,1797665,1758957,1798177,1759151,1798279,1759715,1798257,1759849,1798347,1759957,1798085,1759513,1798725,1760179,1798381,1759415,1798631,1758657,1798133,1757821,1797741,1757073,1797115,1756099,1796243,1756261,1796673,1756537,1796193,1756149,1795713,1755589,1796811,1757377,1797029,1757761,1796433,1757651,1796611,1758049,1796941,1758911,1797003,1759107,1797399,1759213,1797483,1759619,1797973,1760635,1798445,1760547,1798707,1761071},\r
+{1,52,1799277,1761591,1799209,1762007,1799747,1762487,1800085,1763007,1800473,1763689,1800161,1763315,1799281,1762309,1799427,1762225,1799285,1762189,1798857,1761577,1798671,1760497,1798751,1760641,1798501,1760441,1798503,1759999,1798485,1759943,1798421,1760427,1798507,1759929,1798729,1760695,1798759,1760803,1799001,1760787,1798863,1760853,1799271,1761001,1799417,1761055,1799539,1761569,1799453,1761439,1799939,1761785},\r
+{1,52,1799521,1761459,1799089,1760973,1799063,1760833,1799165,1761269,1799197,1761375,1799115,1761385,1799119,1761357,1799431,1762063,1799201,1761749,1799539,1762119,1799779,1762307,1800183,1762571,1799943,1762585,1800245,1762687,1800507,1762937,1800815,1762705,1800153,1761703,1799965,1761459,1799775,1761463,1800245,1761255,1799463,1760381,1798795,1759877,1798223,1759481,1798399,1759619,1797981,1758723,1797529,1758127},\r
+{1,54,1797773,1758939,1797609,1759523,1797559,1758847,1797547,1759313,1797853,1759703,1797737,1759285,1797625,1759403,1797621,1759287,1797315,1758769,1797235,1758349,1797071,1758349,1797053,1757913,1797129,1758529,1797079,1758487,1796995,1757601,1796661,1758003,1795985,1757139,1795833,1756439,1795385,1756513,1795277,1756237,1794699,1755395,1794647,1754749,1794263,1754773,1794245,1754819,1794165,1754841,1794481,1755679,1794903,1755807},\r
+{1,52,1794625,1755947,1795273,1756347,1795101,1756915,1795403,1756917,1795127,1756865,1795403,1757271,1795659,1757553,1795611,1757319,1795523,1757197,1794793,1756527,1794047,1755617,1793775,1755553,1793823,1755307,1793357,1755129,1793289,1754855,1793255,1754727,1793405,1755159,1793295,1755351,1793335,1755091,1793449,1755155,1793713,1755899,1794673,1757867,1795135,1757937,1795539,1758279,1795975,1759213,1796069,1759687},\r
+{1,52,1796651,1759951,1796531,1759435,1796831,1759809,1796203,1759315,1796145,1759375,1795647,1758913,1796029,1759623,1796669,1760941,1796847,1761305,1796799,1761905,1797447,1762993,1797381,1763315,1797489,1763569,1798253,1764323,1798027,1764683,1798155,1764631,1798285,1765205,1798461,1764483,1798137,1764147,1798227,1764217,1798097,1763989,1799093,1766027,1799693,1766979,1799867,1767313,1799303,1765971,1798503,1765287},\r
+{1,54,1798307,1764545,1797951,1762859,1796985,1760899,1796723,1759923,1795953,1758823,1795443,1758565,1795571,1757899,1795531,1758375,1795553,1758657,1795931,1758991,1795749,1759015,1795917,1759203,1796105,1759485,1796149,1759805,1796439,1760077,1796647,1760847,1795843,1760169,1795723,1759507,1795759,1759849,1795887,1759327,1795799,1759411,1795665,1759475,1795647,1759827,1795957,1759475,1795777,1759623,1796025,1759873,1796037,1759975},\r
+{1,52,1796411,1760465,1796949,1761305,1797151,1761693,1797209,1761859,1797519,1762475,1798107,1763275,1798577,1764179,1798555,1763559,1797825,1762927,1797563,1762803,1797861,1763227,1797271,1762681,1797409,1762409,1797541,1762711,1797527,1762651,1797239,1762659,1797439,1762603,1797333,1762863,1797541,1762637,1797289,1762525,1797537,1762531,1797351,1762169,1797573,1761901,1797083,1761043,1797367,1761623,1797621,1761873},\r
+{1,52,1797069,1761279,1796973,1761463,1796817,1761251,1796341,1760013,1796203,1760165,1796109,1760417,1796381,1760849,1796693,1761665,1796749,1762427,1797123,1762151,1797207,1762723,1797189,1762507,1797507,1762963,1797247,1762963,1797439,1762715,1797345,1762151,1797163,1762137,1797283,1762127,1797269,1761891,1797275,1762087,1797221,1762317,1797551,1762243,1797199,1762437,1796967,1762469,1796577,1761907,1796891,1762031},\r
+{1,52,1796879,1762087,1796475,1761633,1796335,1761369,1796221,1761323,1796229,1760927,1796153,1761189,1796033,1761195,1796261,1761369,1796469,1761509,1796653,1761787,1796653,1762295,1796705,1762353,1797003,1762373,1797435,1762933,1796999,1762913,1797213,1762739,1797319,1762451,1797275,1762415,1797029,1762161,1796643,1761667,1796665,1761683,1796581,1761725,1796493,1761791,1796331,1761933,1796933,1762189,1796705,1761861},\r
+{1,54,1796393,1761875,1796577,1762031,1796785,1762059,1796927,1762581,1797395,1762817,1797349,1763037,1797311,1762709,1797705,1763311,1797773,1763181,1798243,1763395,1798337,1764331,1798319,1764243,1798777,1764225,1798547,1764299,1797991,1764139,1797627,1763685,1797763,1763559,1797817,1763385,1797261,1763007,1797181,1762803,1797279,1762903,1797123,1762785,1796995,1762405,1796875,1761985,1796715,1762127,1796755,1762299,1796795,1762247},\r
+{1,52,1796705,1761915,1796639,1761781,1796781,1762017,1796567,1761625,1796635,1761759,1796767,1761637,1796937,1761569,1796915,1761163,1796447,1761505,1795793,1760875,1795665,1760205,1795341,1759965,1795361,1759703,1795201,1759231,1795069,1759093,1794975,1758815,1794749,1758741,1794819,1758807,1794557,1758145,1794405,1758375,1794743,1758325,1794645,1757997,1794807,1758123,1794579,1758205,1794727,1758081,1794757,1757881},\r
+{1,52,1794385,1757605,1794561,1757691,1794659,1757157,1794645,1757035,1794735,1757133,1794549,1757525,1794019,1756869,1793285,1755965,1793183,1756265,1793175,1756043,1792965,1755397,1793139,1755405,1792573,1755299,1792889,1755007,1792437,1754819,1792645,1754827,1792471,1754855,1792623,1754449,1792529,1754653,1792695,1754523,1792885,1754707,1792867,1754815,1792827,1754847,1793089,1755175,1793173,1754949,1793333,1755165},\r
+{1,54,1793223,1754919,1793253,1755275,1793161,1754949,1793089,1754847,1792231,1754005,1792143,1753613,1791987,1753709,1791881,1753131,1791841,1753123,1791729,1753063,1791609,1753251,1791681,1752855,1791387,1752771,1791439,1752961,1791569,1752805,1791639,1752447,1791547,1752809,1792019,1752869,1791845,1753193,1792187,1753505,1792449,1753787,1792877,1754295,1792853,1754417,1793015,1754361,1793085,1754431,1793117,1754845,1793055,1754759},\r
+{1,52,1792707,1754499,1792507,1754283,1792915,1754739,1792681,1754707,1792783,1754495,1792445,1754611,1792783,1754883,1792657,1754647,1792635,1754231,1792965,1754795,1793209,1755035,1793481,1755817,1793771,1756199,1794081,1756745,1794263,1756981,1794367,1757439,1795033,1757721,1795113,1758629,1795901,1759047,1795817,1759439,1796159,1760469,1797013,1761309,1797127,1761781,1796853,1762017,1796891,1761851,1796785,1762085},\r
+{1,52,1796719,1761901,1797007,1762303,1797167,1762295,1796429,1761611,1796465,1761439,1796491,1761473,1796509,1761593,1796275,1761301,1796283,1761033,1796399,1761139,1795989,1760871,1796039,1760751,1796101,1761115,1796265,1761037,1796175,1761319,1796453,1761213,1796417,1761319,1796083,1761287,1795105,1759139,1794157,1757065,1793851,1756269,1793677,1756107,1793037,1754947,1792279,1754457,1792489,1755755,1792743,1756163},\r
+{1,54,1792657,1756201,1792783,1756523,1793001,1757021,1793215,1757845,1793271,1757961,1792601,1756879,1793499,1758159,1793027,1757799,1792929,1757563,1793259,1758237,1793343,1758329,1793467,1758671,1793659,1758523,1793223,1758423,1792769,1757645,1792245,1757271,1792151,1757807,1791901,1757467,1791333,1756099,1791435,1756375,1791097,1755941,1790999,1755859,1790493,1755525,1790839,1755977,1790609,1755849,1791075,1756593,1791239,1756499},    \r
+};\r
+static const int16_t PAH8009_mems_SPO2[][3*NF_PPG_PER_CHANNEL] = \r
+{\r
+{80, 155,370,2007,136,383,2012,170,393,2021,170,381,2016,150,376,2012,155,376,2010,163,383,2016,163,377,2015,156,367,2029,153,373,2014,161,402,1999,168,390,2012,151,385,2015,159,386,2015,167,390,2013,162,394,2014,161,391,2014,163,395,2014,166,394,2010,158,398,2010,159,396,2007,164,396,2007,162,397,2010,157,397,2008,160,403,2009,162,402,2008,162,400,2009,162,395,2009,161,396,2009,161,397,2013,161,394,2014,162,388,2011,159,386,2011,160,392,2012,159,391,2016,161,385,2015,162,386,2012,158,389,2016,161,392,2014,161,391,2011,159,394,2015,163,394,2011,161,393,2011,160,399,2010,162,402,2010,163,412,2014,159,428,1982,162,439,1993,173,352,2029,139,371,2020,162,419,2015,188,416,2011,164,412,2012,152,401,2004,165,402,1999,164,420,2002,157,443,1997,165,430,2007,166,388,2023,154,366,2016,156,396,2002,171,407,2010,162,408,2015,158,391,2010,161,386,2008,163,388,2012,163,363,2044,159,345,2022,151,404,2012,164,426,1988,169,409,2005,156,392,2018,158,382,2016,161,387,2013,157,408,2002,157,413,2008,162,400,2016,158,393,2012,158,392,2009,161,392,2010},\r
+{52, 162,411,2012,164,406,2008,164,407,2005,161,413,2006,165,412,2005,164,417,2005,169,407,2000,165,403,2010,160,409,2011,166,409,2008,161,412,2010,159,421,2016,165,417,2012,162,409,2008,166,391,2001,163,400,2005,164,411,2004,159,426,2013,160,420,2017,167,408,2004,170,402,2000,163,406,2003,161,410,2010,165,415,2010,161,415,2013,162,409,2010,165,395,2003,163,392,2003,168,398,2004,154,409,2017,157,409,2017,166,402,2016,161,400,2013,160,387,2006,157,391,2010,161,396,2012,164,395,2011,159,392,2012,159,392,2009,159,396,2013,160,399,2012,158,392,2009,159,391,2010,163,386,2007,161,384,2006,155,393,2014,165,387,2014,158,384,2015,162,342,2044,152,371,2009,164,419,1993,168,420,2003},\r
+{53, 158,390,2012,150,377,2025,160,377,2018,166,391,2011,164,403,2010,157,403,2009,157,398,2009,156,406,2013,161,402,2008,156,393,2012,152,393,2011,161,393,2012,164,393,2011,157,387,2010,160,397,2012,167,394,2010,151,396,2014,159,394,2013,161,395,2017,163,395,2011,159,390,2010,159,394,2013,164,393,2009,158,392,2013,159,393,2006,157,398,2012,163,404,2014,165,396,2013,165,388,2007,167,396,2004,161,400,2011,161,405,2015,167,399,2000,152,402,2041,180,407,2000,145,369,2002,159,417,2022,181,384,2001,143,413,2025,169,393,2004,159,412,2020,167,399,2006,160,399,2009,165,396,2003,161,410,2010,169,413,2006,168,412,2008,158,418,1996,163,441,1985,179,390,2022,155,380,2030,163,399,2005,175,415,2011},\r
+{52, 169,408,2005,161,400,2006,162,403,2009,171,408,2008,165,413,2009,166,417,2015,169,418,2012,172,406,2005,160,429,1989,167,441,1995,177,411,2006,158,409,2022,158,408,2010,173,400,2006,174,388,2003,161,392,2019,164,408,2011,166,419,2012,167,411,1997,161,417,2006,166,420,2009,163,395,2011,156,399,2000,165,410,2006,170,424,2015,166,420,2016,167,418,2011,167,417,2010,168,415,2006,163,423,1996,164,446,1991,175,396,2016,162,398,2019,161,429,2006,164,459,1984,170,422,2004,165,370,2017,157,368,2018,164,398,2000,167,404,2007,167,406,2008,159,402,2014,152,397,2013,159,388,2022,159,372,2026,151,408,2003,165,411,2000,159,399,2012,154,386,2010,153,393,2017,158,378,2014,157,383,2018},\r
+{52, 155,398,2007,160,397,2012,152,392,2014,159,379,2016,155,393,2018,153,407,2007,161,402,2010,153,391,2014,150,388,2011,154,391,2012,159,391,2010,154,394,2013,157,393,2011,154,390,2013,155,390,2013,155,391,2014,153,393,2015,156,381,2014,163,367,2031,147,382,2011,153,421,2002,169,415,2006,149,400,2016,154,399,2015,159,395,2008,152,392,2008,149,399,2009,161,404,2012,162,402,2012,158,395,2008,155,398,2008,157,403,2012,158,405,2011,156,401,2011,158,405,2009,158,401,2012,158,402,2011,159,399,2008,156,401,2011,158,402,2009,154,403,2009,155,402,2011,158,400,2010,158,402,2009,160,400,2010,154,399,2011,153,399,2009,156,400,2011,157,402,2013,153,399,2012,155,399,2011,158,399,2012},\r
+{53, 157,401,2011,157,398,2012,155,398,2011,154,396,2009,154,402,2011,159,400,2012,156,399,2012,159,398,2011,157,394,2008,155,399,2012,158,399,2011,155,398,2014,156,397,2011,156,398,2014,157,394,2009,155,395,2011,156,395,2012,156,393,2008,155,395,2014,157,398,2012,155,396,2013,154,397,2012,159,399,2014,158,392,2009,154,394,2011,157,395,2010,156,397,2015,158,400,2013,157,398,2012,156,397,2011,158,397,2009,160,395,2010,156,399,2011,158,402,2011,158,404,2012,157,401,2011,156,402,2012,157,404,2008,159,404,2010,158,403,2011,157,402,2012,157,404,2009,158,406,2010,160,405,2012,156,403,2011,156,401,2010,159,403,2008,159,404,2010,159,408,2010,158,408,2012,159,405,2010,157,397,2006,160,406,2012},\r
+{52, 160,407,2009,154,407,2013,160,403,2009,160,402,2008,159,405,2012,157,403,2010,156,404,2010,158,405,2010,157,407,2011,159,405,2009,158,402,2010,159,405,2010,160,406,2009,158,406,2012,156,408,2011,157,405,2008,159,405,2010,162,406,2007,156,404,2009,157,405,2008,159,405,2010,160,408,2010,157,405,2010,156,405,2008,161,402,2007,156,407,2014,159,405,2006,154,405,2013,158,410,2012,159,403,2009,156,405,2009,161,403,2006,157,405,2011,154,407,2012,157,404,2011,155,404,2013,158,402,2008,158,402,2013,157,403,2011,158,402,2009,157,402,2010,157,405,2011,157,406,2009,155,406,2011,156,406,2009,155,405,2011,159,404,2008,157,404,2007,157,407,2011,159,406,2008,156,407,2012,161,405,2007},\r
+{52, 157,406,2009,156,406,2011,159,408,2011,160,407,2007,158,408,2009,160,404,2011,158,405,2008,157,404,2008,158,407,2014,157,405,2011,156,408,2010,157,405,2007,158,407,2011,159,407,2009,156,405,2010,154,404,2007,158,407,2008,158,408,2009,158,405,2009,157,405,2007,158,405,2010,158,407,2007,159,407,2010,158,405,2009,155,406,2007,158,406,2008,157,409,2011,160,407,2006,156,406,2009,160,404,2005,154,405,2011,160,411,2012,157,407,2010,155,406,2011,158,402,2010,156,404,2006,161,408,2012,159,407,2006,154,406,2011,158,407,2011,159,405,2011,158,405,2010,156,404,2008,156,406,2010,157,408,2010,160,405,2009,153,403,2007,157,405,2008,157,408,2008,159,410,2011,159,405,2007,156,406,2007},\r
+{53, 157,405,2014,159,407,2006,156,411,2013,160,405,2004,159,407,2009,160,405,2006,153,406,2012,158,405,2005,156,409,2013,158,406,2007,157,404,2010,158,405,2009,159,408,2011,158,404,2010,156,402,2009,158,404,2010,158,406,2009,157,407,2012,157,405,2012,159,403,2008,159,404,2010,158,404,2010,157,407,2008,157,406,2012,157,405,2009,158,403,2009,157,407,2010,159,406,2011,159,406,2011,158,403,2008,157,406,2013,157,407,2011,155,409,2012,158,406,2008,156,406,2011,162,404,2006,159,403,2008,158,407,2010,158,408,2013,159,405,2011,155,408,2012,158,407,2010,157,407,2007,157,408,2010,158,405,2010,157,405,2008,159,407,2011,159,407,2012,156,405,2010,156,405,2008,157,406,2011,157,404,2009,156,405,2012},\r
+{52, 159,405,2010,159,400,2010,158,399,2009,155,404,2011,156,406,2013,155,405,2009,155,402,2012,160,401,2012,156,398,2009,158,402,2011,160,403,2009,157,403,2009,154,398,2013,154,405,2011,157,402,2009,155,402,2014,159,400,2010,155,397,2010,158,401,2011,158,404,2013,155,405,2012,156,400,2009,153,400,2011,158,399,2008,159,401,2012,155,400,2010,156,399,2008,159,404,2010,156,402,2012,153,399,2010,154,400,2010,158,402,2010,158,403,2011,160,401,2009,156,402,2014,157,404,2007,152,401,2012,157,403,2008,159,402,2011,158,405,2009,158,401,2010,158,403,2010,155,401,2008,156,404,2012,156,407,2012,156,405,2011,156,402,2010,158,402,2011,159,403,2009,155,400,2011,154,404,2012,159,405,2010},\r
+{52, 157,404,2012,157,404,2010,156,401,2009,155,402,2011,157,406,2012,161,403,2012,156,402,2012,156,402,2009,158,405,2013,157,404,2011,155,405,2012,157,403,2008,157,404,2011,159,404,2009,157,403,2008,157,405,2008,157,406,2012,156,405,2010,155,404,2009,156,403,2009,158,407,2008,157,406,2010,157,409,2010,158,403,2010,157,403,2008,157,403,2009,157,407,2012,160,402,2009,158,402,2010,158,400,2009,155,403,2008,156,405,2012,158,406,2011,159,403,2010,156,399,2012,157,400,2013,158,404,2007,156,403,2013,158,405,2011,155,399,2008,157,403,2013,160,403,2008,159,401,2014,160,403,2011,157,401,2011,161,405,2011,155,394,2007,151,401,2009,160,404,2010,158,404,2014,159,397,2008,158,400,2008},\r
+{53, 157,404,2011,157,401,2012,158,396,2010,156,397,2009,155,401,2010,158,404,2012,160,400,2012,158,397,2008,158,400,2010,156,404,2013,160,405,2009,156,401,2009,156,404,2011,158,401,2006,157,404,2007,161,405,2009,160,403,2008,159,408,2013,167,414,2010,168,405,2007,155,396,2006,154,394,2007,161,400,2008,163,399,2008,162,390,2008,155,392,2014,147,396,2024,159,365,2019,177,274,2086,159,354,2003,160,433,1978,145,472,1978,124,461,2001,145,446,2029,156,437,1987,152,444,1982,164,351,2016,134,333,2034,144,399,2014,177,420,2013,152,416,2013,143,414,2012,156,426,2011,159,453,1983,159,411,2010,146,366,2029,143,385,2013,162,417,2007,160,417,2005,151,410,1998,149,413,2024,171,416,2002,149,391,1996},\r
+{52, 147,423,2013,163,416,2007,143,434,2023,154,418,2010,152,423,2013,157,415,2004,157,415,1997,147,449,1979,160,416,2015,154,384,2029,144,410,2005,157,416,2006,157,414,2004,150,412,2007,157,416,2005,154,420,2007,152,421,2012,157,417,2010,156,413,2007,156,415,2007,156,413,2007,155,417,2010,156,409,2004,150,412,2010,154,417,2006,152,414,2012,154,417,2010,157,409,2006,156,411,2008,153,414,2011,154,418,2011,156,417,2009,156,420,2009,160,421,2007,148,433,2012,150,456,1968,156,466,1996,161,381,2024,147,358,2034,147,396,1999,165,401,2002,165,429,2017,167,409,2010,147,409,2014,158,413,2006,159,423,2016,160,415,2016,159,407,2010,161,402,2000,157,410,2007,162,420,2010,162,425,2008},\r
+{52, 162,427,2011,164,419,2006,153,423,1989,158,425,1990,170,379,2026,150,415,2006,165,422,2011,162,414,2010,156,409,2007,162,404,2006,162,412,2009,158,410,2011,155,409,2012,158,408,2011,162,405,2011,156,399,2007,155,401,2010,159,401,2009,160,402,2007,156,402,2012,157,402,2011,157,402,2011,159,405,2011,159,402,2011,158,404,2010,159,400,2010,157,404,2009,158,399,2009,159,403,2011,159,399,2007,154,404,2012,158,407,2011,160,405,2009,158,402,2010,157,404,2012,159,402,2008,162,406,2010,159,405,2010,158,405,2009,157,405,2011,157,404,2010,157,403,2012,160,404,2010,158,405,2011,157,407,2009,158,404,2012,158,404,2010,156,402,2009,156,406,2008,157,404,2010,160,403,2009,159,401,2009},\r
+{52, 158,403,2010,155,405,2012,159,400,2008,157,404,2012,157,402,2010,152,401,2012,158,403,2009,158,402,2011,156,403,2011,159,402,2011,157,402,2011,155,399,2009,156,401,2010,153,402,2012,155,403,2011,157,403,2009,155,401,2011,157,402,2010,156,398,2010,155,402,2011,156,403,2010,154,404,2014,155,400,2008,155,403,2011,157,401,2010,157,401,2012,156,398,2013,156,396,2009,155,400,2010,156,405,2011,151,401,2013,156,395,2010,158,393,2010,150,403,2021,161,399,2005,154,386,2008,153,410,2015,152,392,2012,153,395,2015,161,396,2011,156,394,2011,152,392,2011,154,399,2010,152,398,2011,152,396,2015,153,395,2015,153,395,2011,158,398,2012,158,396,2011,155,396,2016,155,395,2011,152,393,2010},\r
+{52, 151,397,2010,154,400,2013,155,398,2016,158,396,2012,157,393,2011,153,395,2014,155,399,2011,152,399,2009,151,396,2011,152,395,2013,156,395,2010,156,395,2011,156,396,2010,154,397,2013,155,396,2012,154,399,2012,153,398,2011,150,395,2013,155,396,2010,156,398,2012,157,398,2012,155,397,2014,154,397,2013,154,396,2013,152,397,2011,155,400,2013,154,401,2011,156,398,2014,157,395,2009,153,396,2011,154,399,2011,154,400,2009,154,397,2011,155,397,2010,153,396,2012,155,400,2013,157,400,2011,154,400,2013,156,395,2012,155,397,2011,155,397,2010,152,400,2013,154,402,2013,154,398,2012,155,398,2012,152,398,2012,153,401,2012,155,400,2011,154,398,2011,152,399,2012,154,399,2013,154,399,2012},\r
+{53, 154,399,2014,153,397,2011,155,398,2012,154,399,2013,156,399,2012,154,400,2012,154,399,2010,155,396,2012,155,398,2011,155,397,2009,155,399,2011,153,400,2012,154,401,2013,155,398,2010,153,398,2010,155,399,2011,155,400,2013,154,399,2012,155,399,2008,153,398,2010,156,401,2010,156,402,2010,154,398,2012,155,400,2011,157,400,2012,153,401,2014,156,400,2011,154,398,2012,157,399,2012,154,398,2011,153,398,2012,155,401,2011,153,402,2011,154,400,2015,155,396,2012,153,397,2009,155,399,2012,155,399,2011,154,398,2010,156,398,2010,154,397,2010,155,400,2014,157,401,2013,154,397,2010,153,398,2014,157,397,2012,153,397,2011,153,397,2012,155,400,2011,156,398,2012,155,395,2009,155,397,2012,155,401,2011},\r
+{52, 154,398,2011,154,398,2011,155,396,2011,154,397,2013,157,396,2011,156,400,2012,156,399,2012,154,397,2012,155,398,2012,155,398,2012,157,399,2011,154,398,2009,157,397,2010,156,399,2013,157,398,2011,152,400,2012,154,400,2011,157,398,2010,155,398,2011,155,399,2010,156,399,2012,158,401,2014,156,401,2011,152,398,2012,151,397,2013,156,398,2011,156,398,2011,153,398,2011,154,398,2012,154,399,2010,158,400,2015,156,397,2011,154,397,2012,153,399,2013,153,399,2015,157,398,2009,154,396,2013,154,397,2015,155,398,2013,154,397,2010,154,396,2012,156,398,2011,155,396,2010,155,395,2012,155,396,2012,157,395,2011,154,398,2014,153,395,2010,152,395,2012,154,398,2012,155,397,2012,155,396,2013},\r
+{52, 153,395,2012,155,395,2010,154,398,2014,159,399,2013,154,398,2012,154,397,2012,153,396,2010,156,396,2011,158,397,2013,157,398,2013,154,398,2012,153,399,2012,154,400,2013,154,397,2010,152,396,2015,154,399,2011,157,398,2013,158,400,2012,154,398,2013,152,397,2009,154,399,2013,153,400,2012,154,398,2014,153,397,2012,156,398,2013,156,398,2013,157,399,2012,154,400,2013,152,401,2016,156,403,2010,153,398,2012,154,397,2012,155,397,2009,155,402,2011,156,403,2011,154,398,2009,154,402,2009,157,406,2011,158,411,2014,157,404,2010,155,402,2007,157,400,2007,157,402,2010,158,403,2010,154,409,2015,159,407,2011,157,403,2012,156,397,2009,154,395,2008,158,395,2010,154,392,2005,152,399,2012},\r
+{53, 156,400,2012,153,398,2014,151,394,2011,149,391,2011,150,395,2013,156,396,2014,155,393,2012,154,389,2010,155,393,2014,157,395,2015,154,394,2011,151,395,2014,153,397,2012,154,394,2013,154,396,2014,152,395,2014,157,398,2013,157,397,2012,154,395,2012,152,400,2015,155,394,2011,155,392,2012,154,389,2010,152,396,2013,157,397,2013,153,395,2016,154,395,2013,157,390,2008,153,391,2014,155,393,2010,151,396,2016,157,397,2015,156,391,2015,152,391,2011,153,392,2014,157,393,2013,154,393,2014,155,393,2015,155,390,2010,156,392,2013,158,395,2014,156,392,2014,155,392,2012,154,393,2011,157,395,2012,156,395,2013,157,395,2012,155,390,2011,154,394,2012,159,393,2009,155,395,2015,155,393,2014,153,391,2014},\r
+{52, 155,394,2011,156,394,2011,155,393,2014,156,394,2010,151,395,2013,156,398,2013,156,393,2010,155,394,2012,156,397,2012,156,403,2015,157,397,2012,152,394,2011,156,395,2009,161,406,2010,165,409,2013,156,412,2012,155,402,2008,157,397,2004,156,407,2007,161,416,2012,155,414,2012,153,406,2007,156,402,2006,159,409,2008,163,406,2006,159,402,2010,158,407,2010,159,411,2015,158,404,2011,156,393,2011,153,396,2009,158,401,2011,162,409,2013,155,402,2013,151,398,2012,156,394,2009,157,395,2010,156,397,2013,157,397,2012,158,401,2012,159,398,2010,155,396,2013,157,396,2010,158,393,2012,157,402,2012,156,399,2010,154,401,2011,153,397,2009,157,396,2010,158,393,2009,155,399,2011,155,402,2015},\r
+{52, 158,404,2015,155,396,2014,154,395,2012,154,396,2013,158,403,2012,159,401,2011,156,398,2010,155,396,2011,155,393,2009,158,398,2010,156,400,2012,155,402,2013,156,397,2012,156,397,2015,156,396,2012,155,395,2010,158,396,2006,149,396,2017,166,397,2005,146,394,2013,166,403,2013,154,382,2013,156,396,2010,162,395,2011,156,402,2014,156,393,2014,154,391,2012,156,392,2012,160,396,2013,156,394,2014,158,390,2010,153,392,2013,155,394,2010,156,393,2013,155,392,2012,154,392,2011,156,396,2013,157,394,2011,157,392,2016,156,391,2010,152,393,2012,156,398,2012,159,401,2010,156,393,2012,157,394,2012,156,395,2011,157,401,2012,158,402,2012,156,402,2014,157,396,2008,156,396,2010,158,401,2010},\r
+{52, 159,404,2013,158,402,2011,158,399,2010,157,399,2010,159,401,2013,155,403,2014,155,401,2011,156,401,2009,160,401,2010,160,399,2010,156,397,2011,156,398,2009,157,401,2013,158,402,2014,155,399,2009,157,397,2010,160,401,2010,160,400,2012,156,400,2011,159,396,2011,156,399,2008,157,408,2013,158,406,2015,154,397,2011,156,390,2006,158,395,2007,160,403,2011,157,406,2015,157,401,2015,155,393,2008,155,392,2008,158,398,2011,158,396,2014,156,393,2012,154,395,2012,156,399,2015,154,396,2018,152,385,2019,150,382,2008,160,408,2004,165,408,2013,152,394,2013,150,395,2009,160,401,2011,156,404,2013,154,398,2013,157,395,2009,159,402,2012,156,402,2014,156,402,2011,159,398,2009,155,398,2012},\r
+{53, 155,400,2008,154,404,2014,158,404,2009,156,399,2012,157,400,2010,156,403,2009,155,402,2013,156,401,2014,158,397,2008,158,401,2012,156,404,2013,156,401,2007,157,399,2009,155,401,2010,157,401,2013,156,401,2012,155,399,2010,156,402,2009,159,403,2013,155,401,2012,157,398,2009,153,401,2010,155,400,2012,155,403,2016,156,397,2008,153,398,2008,157,399,2013,157,399,2013,157,403,2014,160,399,2010,156,399,2012,157,401,2013,155,400,2014,157,403,2013,158,399,2008,157,400,2009,156,402,2013,157,401,2013,156,404,2013,157,397,2007,157,402,2012,160,405,2011,159,405,2011,156,400,2011,158,399,2010,158,398,2007,156,401,2011,154,401,2012,157,402,2011,158,402,2013,159,392,2021,153,407,2010,161,394,2000},\r
+{52, 150,402,2014,161,398,2010,159,401,2013,158,402,2015,156,398,2015,158,396,2010,156,395,2011,157,400,2011,158,403,2014,156,400,2011,155,399,2011,155,396,2009,155,397,2010,156,399,2010,157,404,2014,157,404,2014,156,400,2011,155,402,2006,157,403,2011,157,402,2009,154,398,2005,155,399,2016,163,410,2011,155,397,2004,155,403,2013,158,394,2011,156,402,2013,164,405,2012,158,405,2016,149,396,2010,151,397,2010,160,400,2009,158,402,2009,151,398,2007,151,400,2009,158,403,2008,159,405,2012,158,402,2009,158,404,2008,160,409,2009,155,409,2011,152,408,2012,161,404,2005,166,401,2005,161,411,2009,163,408,2007,165,411,2008,160,407,2010,158,410,2011,157,404,2008,156,404,2011,160,405,2007},\r
+{52, 160,408,2012,160,414,2012,159,408,2010,158,403,2008,161,399,2001,159,402,2006,162,409,2009,156,410,2015,154,406,2011,166,399,2007,156,402,2011,159,404,2010,161,410,2011,156,404,2014,155,399,2009,161,397,2005,155,400,2009,157,404,2013,160,407,2011,160,403,2008,162,402,2010,154,400,2010,154,403,2011,161,403,2007,161,405,2010,157,407,2013,156,399,2006,160,401,2009,165,396,2005,154,409,2013,162,413,2013,160,408,2013,153,398,2008,158,396,2004,163,407,2010,167,412,2015,161,395,2009,152,390,2006,158,398,2009,165,416,2019,159,411,2018,149,397,2011,156,392,2006,163,401,2011,160,404,2013,157,392,2007,157,390,2004,158,393,2007,159,409,2015,167,420,2020,161,398,2010,151,392,2010},\r
+{53, 164,398,2005,161,405,2015,159,403,2012,157,397,2008,157,403,2009,161,405,2012,161,406,2015,159,401,2008,156,402,2008,161,406,2010,160,407,2009,158,408,2012,160,402,2008,159,407,2007,158,404,2007,161,407,2010,156,403,2009,156,409,2012,171,404,2009,154,411,2016,154,402,2007,160,405,2009,163,405,2009,159,403,2011,159,401,2009,160,408,2012,160,403,2008,155,403,2010,161,398,2008,159,400,2010,158,412,2013,164,412,2015,161,404,2011,161,394,2006,160,390,2004,157,399,2010,163,410,2016,161,409,2020,159,400,2012,159,393,2009,157,392,2009,162,394,2010,162,398,2011,160,394,2012,156,399,2018,161,403,2015,161,399,2014,154,397,2015,156,390,2012,165,386,2004,161,398,2013,157,404,2016,161,402,2013},\r
+{52, 157,394,2012,157,394,2008,165,393,2008,165,396,2010,160,403,2013,158,403,2014,158,403,2015,160,398,2011,158,394,2008,160,401,2013,164,400,2009,162,399,2011,157,397,2010,161,399,2009,160,405,2013,158,398,2009,156,401,2012,164,401,2009,164,401,2014,159,397,2011,158,397,2011,160,393,2010,159,396,2011,160,397,2012,158,395,2015,161,394,2011,161,393,2011,159,392,2012,158,391,2011,157,395,2015,161,398,2013,156,394,2013,158,396,2013,158,390,2010,159,394,2013,161,392,2010,155,395,2012,161,397,2012,160,398,2014,154,396,2013,153,392,2010,162,399,2012,166,396,2009,157,395,2014,159,394,2009,161,395,2010,159,404,2015,159,401,2014,157,394,2013,160,395,2010,162,397,2012,163,399,2012},\r
+{52, 158,396,2012,155,397,2012,159,395,2011,161,395,2013,161,396,2013,158,397,2014,157,398,2014,160,394,2013,160,393,2010,159,397,2013,157,394,2013,156,394,2014,159,393,2010,160,394,2011,158,393,2012,156,392,2011,155,394,2015,158,394,2011,156,393,2014,158,395,2013,159,392,2012,157,390,2011,157,394,2012,157,394,2013,157,393,2013,155,393,2012,156,395,2012,156,390,2012,159,390,2011,161,392,2012,161,393,2013,156,392,2010,155,391,2014,156,388,2013,154,388,2012,159,390,2012,158,394,2014,157,390,2013,157,393,2015,160,391,2013,157,392,2010,157,391,2012,157,393,2014,153,388,2012,157,390,2012,164,391,2013,161,397,2013,158,394,2014,155,394,2013,157,390,2012,161,392,2014,157,395,2013},\r
+{53, 157,397,2013,162,396,2010,163,396,2013,161,390,2006,159,394,2012,158,397,2011,155,400,2012,156,397,2011,164,398,2013,163,392,2009,157,390,2013,158,388,2009,160,400,2012,160,404,2015,153,398,2017,149,388,2010,158,391,2010,173,395,2009,168,395,2014,152,391,2015,148,392,2012,160,393,2011,159,397,2012,154,393,2013,155,394,2011,165,393,2009,165,393,2011,156,392,2013,156,393,2009,155,397,2015,162,399,2012,159,395,2014,159,391,2010,160,394,2010,162,398,2010,160,401,2013,157,392,2009,154,395,2013,160,399,2012,162,399,2012,160,399,2011,158,398,2013,160,394,2012,159,394,2010,156,399,2012,156,400,2012,160,396,2011,156,396,2009,157,398,2010,162,401,2017,165,398,2008,156,396,2013,159,398,2010},\r
+{52, 155,394,2014,156,398,2012,159,397,2012,159,402,2013,161,397,2014,160,394,2011,161,394,2010,157,394,2013,156,398,2014,156,397,2013,159,394,2010,159,394,2013,159,392,2012,158,393,2013,160,391,2015,157,393,2012,159,396,2011,158,393,2013,157,392,2013,159,390,2011,160,392,2010,157,395,2011,156,395,2012,158,393,2014,157,393,2014,161,388,2012,160,392,2012,157,393,2010,152,394,2013,155,391,2013,158,390,2014,158,392,2016,157,390,2014,158,387,2010,159,392,2012,161,393,2013,155,389,2013,155,390,2013,157,390,2012,158,391,2016,160,388,2013,153,387,2014,155,390,2013,157,388,2014,157,394,2015,159,391,2012,156,387,2013,161,389,2014,162,392,2015,159,391,2011,153,394,2011,153,392,2016},\r
+{52, 155,388,2014,160,384,2011,159,391,2013,162,389,2012,157,394,2018,157,388,2014,152,385,2009,159,384,2011,156,389,2016,155,388,2014,158,391,2015,163,385,2015,163,385,2010,159,382,2011,158,391,2015,156,391,2017,156,393,2018,161,390,2015,159,386,2014,157,384,2013,162,383,2011,162,388,2013,161,391,2013,158,391,2014,155,397,2015,158,395,2013,159,388,2011,159,383,2008,162,386,2011,161,387,2011,156,394,2015,155,395,2011,155,396,2016,159,391,2013,158,389,2012,160,387,2013,161,393,2014,161,390,2013,158,393,2014,159,388,2011,156,387,2012,156,393,2014,158,390,2014,159,388,2013,160,387,2011,160,390,2014,160,388,2014,158,388,2012,156,390,2014,158,392,2016,157,389,2014,158,386,2013},\r
+{53, 160,388,2012,161,388,2013,155,389,2015,155,387,2012,156,387,2011,156,389,2012,157,390,2016,157,385,2013,157,385,2013,163,387,2011,159,390,2016,158,389,2014,156,387,2013,158,387,2010,156,388,2016,158,387,2012,158,385,2015,161,386,2010,157,390,2015,158,387,2009,155,386,2014,159,391,2014,158,389,2013,157,387,2015,157,384,2014,157,385,2013,158,387,2014,157,388,2014,156,389,2014,159,386,2011,159,387,2012,159,389,2012,155,384,2013,154,390,2015,162,385,2008,152,386,2021,163,390,2011,154,385,2015,158,385,2013,157,387,2013,159,388,2017,158,383,2012,154,384,2015,158,384,2012,156,385,2014,159,386,2014,158,385,2017,158,386,2011,156,388,2013,159,392,2014,156,386,2014,158,387,2012,159,386,2009},\r
+{52, 158,390,2015,157,390,2015,155,387,2012,158,390,2013,161,388,2014,158,390,2016,161,391,2014,163,391,2011,161,389,2010,154,388,2011,153,389,2012,161,392,2015,163,389,2010,158,393,2016,160,389,2009,155,391,2013,160,389,2010,159,390,2013,156,383,2011,156,388,2015,160,385,2012,160,389,2017,163,380,2017,155,367,2027,151,390,2009,168,407,2001,161,395,2012,151,393,2016,160,395,2015,162,394,2014,157,391,2011,159,392,2009,163,390,2008,159,387,2011,158,392,2012,164,398,2012,161,406,2016,161,404,2019,160,396,2012,158,395,2007,157,387,2005,157,398,2010,165,402,2013,163,408,2013,156,395,2009,156,397,2009,159,397,2011,158,399,2013,161,401,2014,165,400,2010,159,398,2014,157,396,2010},\r
+{52, 154,398,2013,165,403,2010,166,402,2009,155,401,2014,159,403,2009,163,397,2008,163,399,2006,160,404,2011,156,409,2013,161,413,2015,165,401,2004,154,401,2011,165,409,2009,165,408,2012,155,400,2008,163,397,2003,162,406,2012,159,402,2009,154,399,2011,160,402,2008,162,403,2016,164,399,2013,161,395,2008,162,397,2011,162,407,2015,164,397,2011,156,390,2011,160,389,2008,160,396,2010,163,401,2013,163,400,2015,161,393,2010,161,390,2011,157,395,2013,158,399,2016,163,400,2016,162,393,2010,160,393,2011,163,392,2009,159,395,2012,160,396,2009,159,397,2011,160,395,2013,161,398,2013,159,393,2011,154,394,2012,160,397,2011,162,397,2011,157,394,2015,158,393,2011,159,394,2012,160,402,2011},\r
+{53, 159,397,2010,159,397,2013,161,396,2009,155,390,2010,162,397,2012,163,396,2011,157,393,2014,162,395,2011,158,395,2014,162,394,2013,158,394,2013,160,392,2008,160,390,2008,157,393,2012,159,393,2012,160,397,2014,161,398,2014,157,391,2011,157,388,2011,158,390,2012,159,396,2014,161,397,2015,161,391,2014,159,384,2010,157,391,2007,157,397,2015,162,395,2014,158,393,2013,154,390,2010,157,390,2013,161,388,2010,159,385,2013,159,390,2012,158,388,2012,158,388,2015,159,379,2022,154,382,2017,156,407,2000,170,400,2012,156,396,2018,159,390,2012,160,390,2011,156,390,2010,158,392,2011,161,390,2013,156,393,2016,157,387,2012,156,385,2011,158,388,2015,162,375,2024,153,378,2013,157,403,2002,163,402,2007},\r
+{52, 152,389,2014,153,386,2011,159,389,2015,162,384,2011,156,385,2019,158,386,2019,160,399,2014,162,391,2014,152,385,2012,156,390,2012,161,393,2014,160,393,2013,162,391,2010,160,396,2012,165,396,2010,158,401,2014,159,397,2009,160,388,2007,161,399,2012,165,393,2006,160,399,2014,159,403,2016,159,408,2014,168,405,2012,163,402,2013,157,395,2008,160,396,2005,161,404,2007,158,404,2008,158,408,2013,162,401,2008,155,404,2013,169,403,2005,165,406,2013,157,403,2013,158,399,2009,162,408,2013,164,406,2011,159,399,2009,157,399,2011,163,400,2006,159,405,2011,159,407,2012,157,404,2010,161,404,2011,163,402,2014,163,398,2008,160,399,2008,163,407,2010,159,409,2012,155,406,2010,152,396,2008},\r
+{52, 162,404,2010,171,404,2010,163,403,2011,157,402,2007,155,406,2010,156,406,2016,161,401,2007,161,402,2010,162,403,2012,162,403,2009,162,402,2005,158,401,2009,157,404,2009,159,404,2009,159,404,2014,168,404,2012,163,399,2008,159,398,2009,158,399,2009,160,404,2011,159,403,2011,158,408,2012,162,407,2012,162,403,2012,159,397,2008,160,401,2010,164,403,2010,161,401,2010,159,400,2011,158,403,2008,157,403,2011,161,404,2012,160,401,2011,161,400,2010,163,401,2011,162,403,2013,158,398,2007,157,402,2011,163,400,2010,160,398,2011,159,399,2011,165,403,2012,161,402,2010,155,400,2012,159,396,2009,160,400,2011,162,400,2012,159,401,2013,162,400,2009,160,399,2010,161,397,2013,162,399,2012},\r
+{53, 159,399,2010,160,402,2016,158,399,2010,161,396,2010,164,399,2010,159,398,2011,157,393,2012,162,397,2012,164,399,2010,158,402,2014,158,399,2012,161,397,2012,159,401,2012,167,399,2007,158,402,2015,157,401,2011,157,398,2009,162,401,2007,160,405,2012,162,402,2010,159,403,2013,161,402,2011,162,403,2010,161,398,2009,158,405,2011,160,406,2014,164,405,2007,158,396,2012,160,399,2009,161,400,2013,162,404,2011,160,401,2013,160,401,2009,154,400,2019,162,401,2012,160,393,2008,160,401,2009,161,399,2010,156,399,2010,160,401,2015,161,397,2010,158,398,2010,160,398,2010,162,398,2011,161,399,2010,159,400,2011,160,400,2012,158,400,2010,158,398,2013,158,397,2009,163,397,2010,163,401,2011,162,400,2010},\r
+{52, 157,400,2013,165,405,2014,162,402,2008,156,401,2012,164,400,2009,160,397,2009,158,401,2010,160,405,2011,158,406,2014,162,407,2013,164,399,2006,161,394,2006,160,396,2006,163,408,2013,159,406,2013,156,404,2012,161,401,2009,165,400,2012,161,393,2009,158,396,2010,162,400,2015,161,397,2012,155,398,2013,161,401,2012,160,396,2010,157,392,2012,160,395,2009,159,399,2012,159,399,2015,164,396,2013,160,397,2012,157,398,2011,159,400,2013,165,398,2008,159,393,2007,156,400,2012,160,402,2011,161,400,2012,163,397,2011,163,402,2008,161,403,2012,162,402,2013,159,400,2010,159,397,2007,161,398,2010,163,403,2014,163,403,2008,165,404,2012,168,406,2012,163,402,2010,157,401,2011,160,404,2011},\r
+{52, 161,403,2005,161,404,2012,167,403,2010,166,402,2009,161,402,2009,159,404,2010,163,398,2009,158,396,2010,156,408,2016,172,407,2012,169,406,2014,157,394,2011,160,392,2005,158,391,2008,157,401,2013,164,404,2014,165,402,2013,161,395,2009,160,394,2007,163,396,2009,160,402,2016,161,401,2011,160,402,2013,162,400,2012,161,397,2011,161,398,2009,165,400,2009,162,401,2012,164,403,2008,160,402,2010,160,401,2011,161,396,2008,163,398,2007,161,403,2015,166,400,2013,162,398,2011,160,398,2014,159,398,2012,161,394,2012,165,397,2011,162,398,2013,161,397,2013,160,396,2011,160,394,2009,163,395,2012,164,396,2014,162,398,2013,159,397,2012,161,398,2013,163,392,2010,160,392,2009,160,396,2011},\r
+{58, 165,399,2011,162,398,2012,162,398,2014,157,393,2012,158,396,2009,161,397,2011,162,395,2012,166,396,2011,161,395,2008,161,399,2014,164,396,2007,158,395,2012,158,397,2014,160,392,2010,161,396,2009,163,397,2014,162,398,2014,163,393,2010,161,394,2013,160,396,2010,160,395,2012,161,396,2011,164,394,2010,162,394,2017,161,398,2010,163,388,2009,163,405,2013,161,391,2011,157,396,2017,163,387,2006,161,399,2017,166,394,2009,158,394,2014,160,394,2011,159,393,2012,159,392,2012,161,396,2012,161,400,2013,164,395,2013,162,392,2012,160,388,2009,159,394,2012,161,397,2014,160,396,2013,159,395,2015,160,393,2012,160,392,2013,163,392,2011,161,393,2014,159,394,2013,159,397,2013,161,394,2014,162,393,2012,160,391,2010,160,395,2012,164,393,2010,160,391,2012,157,400,2018},\r
+{52, 164,389,2004,153,390,2017,165,391,2009,159,392,2012,164,396,2012,159,395,2017,165,392,2007,162,393,2009,160,398,2017,165,394,2010,160,390,2009,162,398,2012,161,399,2014,159,399,2011,161,400,2014,166,402,2010,163,401,2009,158,405,2011,162,403,2013,163,402,2007,161,410,2010,161,412,2010,162,406,2010,163,393,1999,162,407,2010,166,417,2011,159,406,2010,157,406,2010,167,410,2011,160,397,2009,158,390,2006,164,397,2005,164,407,2017,167,408,2016,162,395,2011,159,396,2006,160,395,2013,163,396,2014,161,391,2012,162,392,2009,163,393,2013,164,392,2011,162,393,2014,163,392,2011,157,389,2013,159,389,2013,161,387,2010,163,390,2011,162,394,2015,163,391,2014,163,387,2009,159,387,2013},\r
+{52, 158,392,2014,161,391,2013,159,390,2013,160,390,2010,161,387,2010,162,390,2010,158,391,2012,159,390,2010,156,388,2012,160,387,2012,160,393,2016,161,397,2016,161,387,2015,163,382,2006,160,386,2010,161,391,2014,162,394,2017,165,391,2014,162,392,2013,162,391,2011,160,394,2013,163,388,2009,161,389,2011,160,393,2011,160,397,2014,162,396,2010,159,396,2013,161,393,2010,163,395,2014,166,395,2007,157,393,2014,163,399,2014,163,395,2011,158,393,2010,162,396,2014,161,393,2012,162,395,2013,163,393,2010,161,396,2011,163,394,2011,159,395,2014,161,393,2013,161,392,2010,164,395,2012,163,397,2016,163,393,2012,159,395,2012,165,397,2012,165,396,2010,161,394,2010,160,396,2012,164,399,2015},\r
+{53, 164,395,2013,162,398,2011,161,396,2011,164,394,2012,165,396,2010,161,392,2008,162,396,2014,167,394,2012,163,397,2012,161,394,2013,163,398,2015,166,391,2010,161,391,2012,161,394,2010,162,398,2013,164,394,2011,163,394,2014,162,394,2014,160,392,2011,161,392,2012,165,393,2012,163,395,2013,164,397,2014,164,393,2011,161,392,2013,164,394,2012,162,397,2014,163,397,2013,163,395,2014,167,395,2010,165,400,2010,163,401,2013,162,401,2015,164,397,2009,161,400,2010,162,400,2013,169,400,2009,164,397,2009,161,402,2008,168,404,2010,166,406,2014,161,401,2011,161,401,2008,166,401,2008,168,404,2015,165,399,2009,159,403,2010,163,409,2008,165,408,2013,159,400,2010,161,394,2005,164,399,2007,164,406,2014},\r
+{52, 170,404,2011,162,405,2010,160,403,2013,160,404,2013,166,397,2011,165,396,2008,162,397,2008,160,404,2012,165,404,2014,164,398,2011,160,396,2009,162,398,2011,164,400,2013,165,402,2010,167,402,2011,158,403,2010,160,398,2007,165,400,2009,165,397,2009,163,403,2012,163,405,2015,161,400,2010,165,396,2008,166,401,2010,162,404,2015,168,408,2013,162,406,2014,162,394,2007,160,393,2009,164,399,2007,161,405,2014,162,408,2013,164,400,2009,161,398,2010,167,399,2009,163,402,2012,162,402,2014,165,403,2009,164,404,2011,162,404,2010,162,399,2010,164,400,2009,163,400,2007,163,404,2011,166,404,2011,163,405,2010,163,401,2008,163,400,2011,164,400,2010,162,400,2009,160,403,2012,161,404,2011},\r
+{52, 164,398,2008,161,397,2007,162,396,2009,165,399,2010,165,399,2012,159,396,2013,161,396,2009,162,399,2012,161,398,2011,161,395,2012,161,394,2013,164,395,2012,163,394,2011,161,399,2017,161,396,2012,159,396,2013,160,393,2012,164,396,2013,163,394,2010,162,397,2014,162,396,2012,166,395,2013,164,391,2011,158,394,2012,164,393,2014,163,393,2013,159,392,2010,163,396,2010,162,395,2017,164,392,2010,161,391,2012,160,390,2014,161,393,2010,162,394,2015,162,395,2014,164,392,2009,162,393,2015,162,394,2016,162,395,2010,162,396,2017,163,391,2013,161,385,2011,162,385,2007,159,391,2011,164,404,2018,165,398,2018,158,386,2012,156,385,2004,157,391,2013,161,394,2018,171,395,2010,159,386,2011},\r
+{53, 161,394,2011,164,394,2013,163,394,2015,164,389,2008,157,397,2011,166,392,2008,164,395,2015,166,391,2006,161,393,2012,166,400,2015,162,398,2012,165,394,2011,164,392,2011,166,392,2007,165,393,2012,167,397,2016,166,392,2014,163,391,2009,164,389,2013,163,391,2013,160,385,2012,164,389,2015,168,387,2012,163,386,2015,163,389,2016,164,385,2013,163,383,2014,163,381,2012,160,388,2017,164,386,2014,164,383,2018,164,379,2011,164,379,2012,161,388,2019,161,384,2014,160,384,2016,167,382,2012,164,380,2014,165,383,2016,162,382,2011,161,385,2018,169,379,2012,162,371,2008,158,378,2015,164,376,2017,166,360,2057,156,354,2005,162,425,1995,183,403,2007,150,390,2018,159,384,2015,172,392,2015,163,389,2012},\r
+{52, 160,390,2015,168,398,2016,172,398,2013,164,396,2011,162,395,2011,163,401,2009,166,406,2012,167,417,1996,169,412,2005,171,375,2020,158,393,2016,172,404,2010,165,403,2009,157,399,2010,163,400,2008,165,401,2011,165,401,2013,172,396,2011,169,402,2010,166,401,2013,164,400,2010,162,397,2010,163,399,2012,165,398,2012,167,400,2013,167,395,2010,167,397,2011,167,394,2010,163,393,2012,165,395,2014,167,398,2014,165,396,2014,163,395,2015,169,393,2012,167,392,2011,165,391,2012,164,394,2011,164,396,2013,166,398,2011,166,393,2011,163,395,2012,166,394,2011,166,396,2011,168,399,2015,167,398,2011,165,395,2010,164,395,2010,164,396,2010,165,396,2013,166,396,2013,167,394,2010,164,397,2014},\r
+{52, 166,392,2010,165,393,2010,165,395,2009,165,392,2010,163,393,2013,167,395,2012,167,391,2014,165,394,2013,167,387,2007,164,394,2017,169,389,2009,163,388,2015,164,389,2011,163,392,2016,166,393,2014,165,392,2014,166,392,2012,164,388,2013,165,389,2010,166,389,2013,166,391,2015,164,389,2010,165,392,2012,166,393,2013,165,392,2010,164,392,2013,166,391,2009,167,390,2010,163,392,2010,164,393,2015,165,395,2012,167,392,2010,166,393,2014,164,396,2014,166,391,2009,166,391,2011,164,391,2011,164,394,2013,165,394,2015,168,392,2008,165,389,2010,166,393,2010,167,395,2012,165,395,2015,167,394,2009,164,395,2012,164,397,2014,166,397,2011,166,391,2006,163,392,2007,165,398,2007,165,403,2014},\r
+{52, 165,401,2012,166,400,2009,164,396,2012,165,396,2009,166,394,2010,165,403,2013,168,402,2012,168,401,2013,165,394,2009,161,394,2008,162,399,2009,167,403,2013,168,400,2010,165,394,2009,162,396,2013,167,398,2012,165,391,2012,164,397,2010,163,397,2012,165,401,2011,161,391,2012,162,398,2013,167,396,2013,165,392,2011,163,388,2004,160,394,2013,163,398,2014,164,394,2013,164,391,2014,169,394,2008,164,395,2012,165,398,2015,166,395,2012,164,393,2009,164,390,2010,165,398,2012,166,400,2014,167,394,2011,165,391,2012,167,392,2008,163,395,2016,165,394,2011,165,397,2014,164,393,2011,162,393,2014,166,391,2010,163,395,2013,166,396,2011,166,393,2013,164,390,2012,160,390,2012,164,392,2011},\r
+{53, 166,393,2012,161,393,2014,163,395,2013,165,391,2011,162,390,2011,162,392,2011,162,393,2010,164,393,2014,163,396,2012,163,392,2011,163,392,2011,163,395,2011,165,393,2012,165,395,2012,160,394,2014,163,393,2010,164,390,2011,164,391,2011,163,393,2015,161,393,2012,164,389,2012,163,391,2012,163,390,2013,162,391,2013,162,388,2013,164,391,2012,164,390,2011,161,393,2013,163,390,2013,163,387,2014,165,390,2013,165,390,2013,163,391,2012,161,393,2015,161,390,2013,165,388,2012,164,391,2016,165,390,2009,159,393,2014,167,392,2012,164,390,2010,160,389,2012,163,392,2013,164,393,2013,166,390,2015,166,389,2011,162,389,2011,161,389,2013,164,390,2011,162,389,2013,162,390,2014,162,387,2013,164,388,2013},\r
+{52, 164,387,2016,161,389,2013,162,390,2012,165,391,2014,162,388,2011,161,388,2013,165,391,2014,165,385,2013,162,389,2012,164,392,2013,161,395,2014,167,392,2013,162,388,2012,159,387,2010,165,392,2013,167,395,2014,165,393,2016,165,389,2011,162,388,2011,164,390,2014,164,393,2011,167,394,2015,167,393,2014,164,388,2010,163,390,2012,165,392,2013,165,390,2014,160,390,2015,164,392,2013,167,394,2010,167,390,2011,163,388,2015,163,391,2012,164,392,2014,164,392,2014,166,393,2015,164,391,2015,163,390,2012,167,390,2014,162,392,2013,162,393,2014,164,392,2013,167,393,2012,163,390,2013,164,390,2010,164,392,2012,166,391,2014,164,391,2014,163,390,2013,165,389,2013,162,390,2014,164,391,2011},\r
+{52, 163,391,2014,165,392,2013,168,389,2012,164,390,2012,163,389,2014,164,391,2012,162,391,2013,164,391,2014,164,388,2013,166,388,2013,163,388,2014,161,389,2012,161,388,2012,163,391,2014,165,392,2015,163,389,2014,166,386,2012,166,389,2010,163,393,2013,164,393,2014,164,390,2012,163,389,2012,162,389,2011,164,391,2012,165,390,2014,166,391,2014,164,392,2011,163,392,2014,164,391,2010,161,390,2013,165,391,2011,167,391,2013,165,388,2011,163,389,2012,165,390,2010,164,391,2014,163,395,2014,163,390,2012,166,388,2013,165,391,2010,163,391,2014,165,391,2013,163,391,2012,164,392,2013,164,392,2013,163,391,2013,164,390,2013,163,390,2013,164,388,2016,162,388,2011,163,391,2015,162,392,2014},\r
+{53, 162,390,2013,165,389,2011,164,391,2012,163,392,2013,162,392,2012,162,391,2013,163,393,2013,165,390,2013,164,390,2012,162,391,2012,163,389,2011,164,390,2012,162,393,2015,163,394,2015,163,392,2015,166,386,2011,166,388,2013,161,389,2012,161,390,2013,164,394,2015,164,393,2015,163,387,2013,163,387,2011,163,390,2012,166,390,2012,164,388,2014,161,389,2013,162,391,2012,165,392,2016,165,392,2014,160,388,2014,163,388,2013,167,391,2014,163,390,2012,163,391,2012,162,392,2011,160,392,2014,164,390,2014,164,389,2014,163,389,2011,163,390,2014,165,391,2014,162,390,2011,160,390,2014,161,391,2014,163,386,2014,164,386,2014,164,389,2013,165,390,2014,163,390,2013,162,390,2015,162,390,2011,163,390,2017},\r
+{52, 164,389,2012,165,388,2012,165,391,2012,162,390,2013,164,390,2015,161,388,2012,160,392,2014,163,393,2013,166,388,2011,161,388,2011,163,387,2013,165,391,2015,163,392,2011,162,391,2014,160,390,2010,162,390,2011,164,393,2013,163,389,2014,163,389,2012,164,390,2012,166,392,2013,162,388,2014,160,389,2015,161,391,2015,164,390,2013,165,387,2011,162,389,2012,164,391,2013,167,389,2014,162,389,2011,162,390,2012,161,390,2013,163,391,2013,165,388,2013,165,390,2012,165,389,2012,162,390,2012,161,387,2012,162,392,2012,164,390,2013,160,388,2013,163,389,2011,168,390,2013,164,391,2014,162,389,2015,163,390,2012,161,389,2013,161,390,2014,164,388,2014,163,385,2012,165,391,2016,165,389,2013},\r
+{52, 162,391,2014,162,391,2013,162,388,2014,162,387,2013,164,388,2010,165,389,2012,165,391,2012,162,389,2012,161,389,2014,162,391,2013,162,390,2014,166,388,2014,163,387,2013,162,389,2013,164,391,2015,162,389,2013,162,389,2011,162,386,2011,160,389,2011,162,389,2013,167,396,2012,162,392,2016,163,392,2015,162,389,2014,164,391,2013,165,388,2013,161,390,2013,161,390,2012,163,395,2014,166,390,2013,165,389,2012,161,390,2010,162,392,2014,164,387,2013,161,390,2013,165,390,2013,163,392,2013,164,392,2013,166,392,2010,163,386,2012,161,388,2012,161,385,2011,160,392,2011,165,389,2011,162,388,2015,163,384,2013,164,385,2015,165,386,2012,165,386,2011,159,387,2015,161,387,2013,160,387,2013},\r
+{53, 165,384,2013,164,386,2014,163,381,2013,163,384,2012,165,387,2014,161,393,2017,163,391,2016,162,389,2013,165,386,2011,166,386,2010,162,387,2011,164,390,2012,164,392,2016,161,389,2013,164,391,2014,166,392,2011,163,388,2012,162,388,2013,164,390,2011,163,389,2013,164,392,2012,162,392,2014,162,392,2013,164,387,2010,162,389,2013,165,391,2014,166,391,2012,163,392,2012,160,388,2013,160,388,2009,165,389,2013,166,389,2015,165,390,2012,163,388,2016,162,390,2013,162,392,2015,162,399,2017,162,398,2014,164,395,2012,164,393,2007,165,399,2012,167,398,2008,163,398,2007,158,399,2010,164,412,2010,167,409,2010,158,398,2009,161,395,2004,167,396,2006,166,403,2008,164,404,2014,162,406,2017,166,397,2007},\r
+{53, 167,395,2010,167,393,2010,161,389,2012,162,393,2013,166,393,2016,165,388,2013,162,386,2014,165,395,2014,166,394,2017,164,387,2014,165,379,2012,163,381,2007,160,388,2013,164,394,2018,164,388,2016,163,383,2013,165,380,2013,164,383,2010,164,388,2012,160,390,2014,161,386,2012,160,384,2012,159,386,2013,164,382,2014,164,384,2015,164,383,2015,162,385,2015,163,386,2015,161,382,2012,160,382,2016,160,381,2009,160,381,2013,163,384,2017,167,386,2017,167,386,2016,160,385,2019,159,376,2012,159,378,2011,162,384,2013,164,387,2014,162,382,2016,163,381,2015,165,383,2013,164,383,2016,162,379,2013,158,385,2014,159,385,2014,163,384,2016,165,379,2014,162,378,2013,164,383,2014,163,384,2015,158,383,2017},    \r
+};\r
+static const uint32_t duration_SPO2[] = \r
+{\r
+1013,\r
+1048,\r
+1062,\r
+1059,\r
+1037,\r
+1062,\r
+1065,\r
+1038,\r
+1058,\r
+1060,\r
+1040,\r
+1058,\r
+1060,\r
+1039,\r
+1060,\r
+1060,\r
+1036,\r
+1061,\r
+1061,\r
+1040,\r
+1059,\r
+1062,\r
+1035,\r
+1060,\r
+1062,\r
+1034,\r
+1062,\r
+1059,\r
+1060,\r
+1038,\r
+1060,\r
+1061,\r
+1036,\r
+1060,\r
+1061,\r
+1037,\r
+1062,\r
+1063,\r
+1037,\r
+1059,\r
+1060,\r
+1145,\r
+1059,\r
+1063,\r
+1036,\r
+1062,\r
+1062,\r
+1037,\r
+1059,\r
+1061,\r
+1035,\r
+1060,\r
+1061,\r
+1048,\r
+1047,\r
+1064,\r
+1048,\r
+1049,\r
+1063,    \r
+};\r
+\r
+static const uint8_t frame_SPO2[] = \r
+{\r
+1,\r
+2,\r
+3,\r
+4,\r
+5,\r
+6,\r
+7,\r
+8,\r
+9,\r
+10,\r
+11,\r
+12,\r
+13,\r
+14,\r
+15,\r
+16,\r
+17,\r
+18,\r
+19,\r
+20,\r
+21,\r
+22,\r
+23,\r
+24,\r
+25,\r
+26,\r
+27,\r
+28,\r
+29,\r
+30,\r
+31,\r
+32,\r
+33,\r
+34,\r
+35,\r
+36,\r
+37,\r
+38,\r
+39,\r
+40,\r
+41,\r
+42,\r
+43,\r
+44,\r
+45,\r
+46,\r
+47,\r
+48,\r
+49,\r
+50,\r
+51,\r
+52,\r
+53,\r
+54,\r
+55,\r
+56,\r
+57,\r
+58,\r
+59,    \r
+};\r
+       \r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pxialg_spo2.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/pxialg_spo2.h
new file mode 100644 (file)
index 0000000..fdda926
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef __PXIALG_SPO2_H__\r
+#define __PXIALG_SPO2_H__\r
+\r
+\r
+#include <stdint.h>\r
+\r
+\r
+#if defined(WIN32) && !defined(PXIALG_STATIC_LIB)\r
+#   ifdef PXIALG_EXPORTS\r
+#       define PXIALG_API   __declspec(dllexport)\r
+#   else\r
+#       define PXIALG_API   __declspec(dllimport)\r
+#   endif\r
+#else\r
+#   define PXIALG_API\r
+#endif // WIN32\r
+\r
+#pragma pack(1)\r
+typedef struct SpO2_mems {\r
+       int16_t data[3];\r
+} SpO2_mems_t;\r
+\r
+typedef struct SpO2_info {\r
+       float IR_DC;\r
+       float R_DC;\r
+       float G_DC;\r
+       float IR_AC;\r
+       float R_AC;\r
+       float G_AC;\r
+       float R_IR_Ratio;\r
+       float R_G_Ratio;\r
+       float G_IR_Ratio;\r
+       float Noise;\r
+       float SpO2_ref;\r
+       float PI;\r
+       float PVI;\r
+       float RMS;\r
+       float MEMS;\r
+       float Output[5];\r
+       float xyz_mean[3];\r
+} SpO2_info_t;\r
+#pragma pack()\r
+\r
+typedef enum {\r
+       SPO2_MSG_SUCCESS = 0,\r
+       SPO2_MSG_ALG_NOT_OPEN,\r
+       SPO2_MSG_ALG_REOPEN,\r
+       SPO2_MSG_ALG_NOT_SUPPORT,\r
+    SPO2_MSG_INVALID_ARGUMENT,\r
+       SPO2_MSG_MOVING_SPO2_READY = 0x100,\r
+       SPO2_MSG_MOVING_SPO2_NOT_READY,\r
+       SPO2_MSG_MOVING_SPO2_STOP,\r
+}spo2_msg_code_t;\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+\r
+PXIALG_API uint32_t SpO2_OpenSize(void);\r
+PXIALG_API int SpO2_Open(void *mem);\r
+PXIALG_API int SpO2_Close(void);\r
+PXIALG_API int SpO2_GetSpO2(float *spo2);\r
+PXIALG_API int SpO2_GetReadyFlag(uint8_t *ready_flag);\r
+PXIALG_API int SpO2_GetPeriodicity(float *periodicity);\r
+PXIALG_API int SpO2_Version(void);\r
+PXIALG_API int SpO2_Process(int touch_flag, int total_channel, int *input, int samples_per_ch, float time_in);\r
+PXIALG_API int SpO2_ProcessD(int touch_flag, int total_channel, int *input, int samples_per_ch, float time_in);\r
+PXIALG_API int SpO2_GetFilteredData(int touch_flag, int total_channel, int expo_R,  int expo_IR, int DAC_R, int DAC_IR, float **filter_R, float **filter_IR, int *FilteredDataLength);\r
+\r
+//parameters\r
+PXIALG_API int SpO2_SetIIRFilterRatio(float IIRFilterRatio);   //0 ~ 0.5. bigger value more smooth.\r
+PXIALG_API int SpO2_SetMotionDetectionLevel(float level);\r
+PXIALG_API int SpO2_SetInputModelScale(float scale);\r
+PXIALG_API int SpO2_SetInputCorrelationTh(float th);\r
+PXIALG_API int SpO2_SetInputRatioLow(float ratio);\r
+PXIALG_API int SpO2_SetInputCoefLow0(float coef);\r
+PXIALG_API int SpO2_SetInputCoefLow1(float coef);\r
+PXIALG_API int SpO2_SetInputCoefLow2(float coef);\r
+PXIALG_API int SpO2_SetInputCoefLow3(float coef);\r
+PXIALG_API int SpO2_SetInputCoefMid0(float coef);\r
+PXIALG_API int SpO2_SetInputCoefMid1(float coef);\r
+PXIALG_API int SpO2_SetInputCoefMid2(float coef);\r
+PXIALG_API int SpO2_SetInputCoefMid3(float coef);\r
+PXIALG_API int SpO2_SetInputCoefHigh0(float coef);\r
+PXIALG_API int SpO2_SetInputCoefHigh1(float coef);\r
+PXIALG_API int SpO2_SetInputCoefHigh2(float coef);\r
+PXIALG_API int SpO2_SetInputCoefHigh3(float coef);\r
+PXIALG_API int SpO2_SetInputRatioHighBound(float bound);\r
+PXIALG_API int SpO2_SetInputRatioLowBound(float bound);\r
+PXIALG_API int SpO2_SetInputFlagCheckHr(int value);\r
+PXIALG_API int SpO2_SetOutputHighBound(float value);\r
+PXIALG_API int SpO2_SetOutputLowBound(float value);\r
+PXIALG_API int SpO2_Set_Init_Low_SpO2_Constrain(int value);\r
+PXIALG_API int SpO2_Set_Init_Low_SpO2_Th(float value);\r
+\r
+PXIALG_API int SpO2_Set_Init_Low_SpO2_Check_Sec(int value);\r
+\r
+PXIALG_API int SpO2_Set_Motion_Rms_Th(float value);\r
+PXIALG_API int SpO2_Set_Motion_Rms_Th2(float value);\r
+\r
+PXIALG_API int SpO2_Set_Correlation_Th2_Count(int value);\r
+PXIALG_API int SpO2_Set_Input_Correlation_Th2(float value);\r
+\r
+PXIALG_API int SpO2_Set_Flag_Hold_Breathe_Mode(char value);\r
+\r
+PXIALG_API int SpO2_Set_Keep_Init_SpO2_Bound(float value);\r
+PXIALG_API int SpO2_Set_Keep_Init_SpO2_Count_Th(int value);\r
+PXIALG_API int SpO2_Set_SpO2_Bias_Value(float value);\r
+PXIALG_API int SpO2_Set_SpO2_Outlier_Smooth_Coef(float value);\r
+PXIALG_API int SpO2_Set_SpO2_Decrease_Coef(float value);\r
+\r
+PXIALG_API int SpO2_Set_Motion_MEMS_Th(float value);\r
+\r
+PXIALG_API int SpO2_Set_T1(float value);\r
+PXIALG_API int SpO2_Set_T2(float value);\r
+PXIALG_API int SpO2_Set_T3(float value);\r
+PXIALG_API int SpO2_Set_T4(float value);\r
+PXIALG_API int SpO2_Set_T5(float value);\r
+PXIALG_API int SpO2_Set_Spo2_Force_Output_Second(int value);\r
+\r
+PXIALG_API int Spo2_Set_SpO2_First_Smooth_Th(float value);\r
+PXIALG_API int Spo2_Set_SpO2_First_Smooth_Sec(int value);\r
+PXIALG_API int Spo2_Set_SpO2_Correlation_Smooth_Th(float value);\r
+\r
+//set HR\r
+PXIALG_API int SpO2_SetHrValue(int value);\r
+\r
+//get SPO2_Info\r
+PXIALG_API int SpO2_GetInfo(SpO2_info_t *info);\r
+\r
+PXIALG_API int SpO2_SetMems(SpO2_mems_t *mems, int samples);\r
+\r
+PXIALG_API int SpO2_Set_Update_Sec(int spo2_update_sec);\r
+\r
+PXIALG_API int SpO2_SetMemsRmsThr(float mems_rms_thr);\r
+PXIALG_API int SpO2_CalAvgSpO2(float mySpO2, float trust_flag, float mems_rms, float *result); //called every one second\r
+PXIALG_API int SpO2_SetSkipDataLen(int len);\r
+PXIALG_API int SpO2_SetChMapping(int8_t *alg_ch, int8_t ch_nr);\r
+\r
+PXIALG_API int Spo2_Set_Force_Output_Value(float value);\r
+PXIALG_API int Spo2_Set_Force_Output_Value2(float value);\r
+\r
+PXIALG_API int SpO2_Set_Signal_Periodicity_Th(float value);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/test_library_SPO2.c b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_spo2/V703/test_library_SPO2.c
new file mode 100644 (file)
index 0000000..2f76e52
--- /dev/null
@@ -0,0 +1,432 @@
+// algorithm\r
+#include "pxialg_spo2.h"\r
+// HR algorithm\r
+#include "pxialg.h"\r
+// testpattern\r
+#include "pah8009_testpattern_SPO2.h"\r
+// platform\r
+#include <stdlib.h>\r
+\r
+#include "pah800x_main.h"\r
+//#include "system_clock.h"\r
+//#include "i2c.h"\r
+//#include "gpio_ctrl.h"\r
+//#include "pah_comm.h"\r
+#include <math.h>  \r
+#include "nrf_delay.h"\r
+#define array_szie(arr) (sizeof(arr) / sizeof(arr[0]))\r
+\r
+#define SAMPLES_PER_CHANNEL 25\r
+#define TOTAL_CHANNEL 3\r
+\r
+//#define Open_Rest_Flow\r
+\r
+static SpO2_mems_t  mems_data_raw[150];        //add item\r
+\r
+typedef struct\r
+{\r
+    void *pBuffer;\r
+    void *hr_pBuffer;\r
+} pxialg_spo2_state;\r
+\r
+//#define parameter_printf(...) NRF_LOG_RAW_INFO(__VA_ARGS__)\r
+\r
+extern void spo2_log_printf(char s, float f);\r
+//static void spo2_log_printf(char s, float f)\r
+//{\r
+//    parameter_printf("%s= "LOG_FLOAT_MARKER"   \n",s, LOG_FLOAT(f));\r
+\r
+//}\r
+\r
+\r
+\r
+\r
+static void bubblesort(float *input,int count) \r
+{\r
+    int i,j;\r
+    float sort_temp;\r
+    for(i=0;i<count - 1;i++)\r
+    {\r
+        for(j=0;j<count-i - 1;j++) \r
+        {\r
+            if(input[j+1]<input[j])\r
+            {\r
+                sort_temp=input[j+1];\r
+                input[j+1]=input[j];\r
+                input[j]=sort_temp;\r
+            }\r
+        }\r
+    }\r
+}\r
+    \r
+    \r
+    \r
+    \r
+    \r
+\r
+    \r
+void test_library_SPO2(void)\r
+{\r
+    int i               = 0;\r
+    int j               = 0;\r
+    int32_t version     = 0;\r
+    uint8_t ReadyFlag   = 0;\r
+    int     buffer_size = 0;\r
+    void *pBuffer       = NULL;\r
+    \r
+    \r
+    \r
+    \r
+    \r
+    // add for new flow\r
+    float            spo2_array[31]={0.0f};   \r
+    int              count         =0;\r
+\r
+    //int     time_s,time_e,time_c;\r
+    int8_t alg_ch[2]    = {0, 1};\r
+    static pxialg_spo2_state    _spo2_state;\r
+    pah8series_data_t   pxialg_data;\r
+        \r
+    version     = SpO2_Version();\r
+    LOG_PRINT("SPO2_version =%d \n",version);\r
+    buffer_size = SpO2_OpenSize();\r
+    LOG_PRINT("SPO2_size = %d  \n", buffer_size);\r
+    pBuffer = malloc(buffer_size);\r
+\r
+    \r
+    nrf_delay_ms(50);\r
+    if (!pBuffer)\r
+    {\r
+        LOG_PRINT("Out of memory. \n");\r
+        return;\r
+    }\r
+    nrf_delay_ms(50);\r
+    if (SpO2_Open(pBuffer) != SPO2_MSG_SUCCESS)\r
+    {\r
+        LOG_PRINT("SpO2_Open() failed. \n");\r
+        free(pBuffer);\r
+        return;\r
+    }\r
+    \r
+       //log_printf("pBuffer =%x \n",pBuffer);\r
+    SpO2_SetChMapping(alg_ch, 2);\r
+    SpO2_SetInputRatioHighBound(94.0f);\r
+    SpO2_SetInputRatioLowBound(87.0f);\r
+    SpO2_SetInputModelScale(0.50f);\r
+    \r
+    SpO2_SetInputCoefHigh0(-36877.85546875f);\r
+    SpO2_SetInputCoefHigh1(1135.91394042969f);\r
+    SpO2_SetInputCoefHigh2(-11.6429319381714f);\r
+    SpO2_SetInputCoefHigh3(0.0398150011897087f);\r
+    \r
+    SpO2_SetInputCoefMid0(-1430.70520019531f);\r
+    SpO2_SetInputCoefMid1(50.1599006652832f);\r
+    SpO2_SetInputCoefMid2(-0.567422986030579f);\r
+    SpO2_SetInputCoefMid3(0.00219199992716312f);\r
+    \r
+    SpO2_SetInputCoefLow0(-8.19796657562256f);\r
+    SpO2_SetInputCoefLow1(1.74200701713562f);\r
+    SpO2_SetInputCoefLow2(-0.0173850003629923f);\r
+    SpO2_SetInputCoefLow3(0.000105999999505002f);\r
+    \r
+    SpO2_SetIIRFilterRatio(0.5f);\r
+    SpO2_SetInputCorrelationTh(0.850000078678131f);\r
+    SpO2_SetInputRatioLow(0.05f);        \r
+    \r
+    SpO2_SetInputFlagCheckHr(1);\r
+    SpO2_SetMotionDetectionLevel(2.0f);\r
+    SpO2_Set_Update_Sec(1);\r
+    \r
+    SpO2_Set_Init_Low_SpO2_Constrain(0.0);\r
+    SpO2_SetOutputHighBound(100.0f);\r
+    SpO2_SetOutputLowBound(60.0f);\r
+    SpO2_Set_Keep_Init_SpO2_Bound(95.0f);    \r
+    SpO2_Set_Keep_Init_SpO2_Count_Th(18.0f);\r
+    SpO2_Set_SpO2_Bias_Value(0.5f);\r
+    SpO2_Set_SpO2_Outlier_Smooth_Coef(5.5f);\r
+    SpO2_Set_SpO2_Decrease_Coef(0.5f);\r
+    SpO2_SetSkipDataLen(25);\r
+             \r
+    SpO2_Set_Flag_Hold_Breathe_Mode(0);\r
+    SpO2_Set_Input_Correlation_Th2(0.85000f);\r
+    SpO2_Set_Correlation_Th2_Count(30.0f);\r
+    SpO2_Set_Init_Low_SpO2_Th(94.5f);\r
+    SpO2_Set_Motion_Rms_Th(3000.0f);\r
+    SpO2_Set_Motion_Rms_Th2(1500.0f);\r
+    SpO2_Set_Motion_MEMS_Th(0.0f);     \r
+    SpO2_Set_T1(0.85f);\r
+    SpO2_Set_Spo2_Force_Output_Second(30.0f);\r
+    \r
+    Spo2_Set_Force_Output_Value(97.50f);  // Good Signal Force SpO2\r
+    Spo2_Set_Force_Output_Value2(95.00f); // Bad  Signal Force SpO2\r
+    \r
+    SpO2_Set_Init_Low_SpO2_Check_Sec(20);\r
+    Spo2_Set_SpO2_First_Smooth_Th(95.0f);\r
+    Spo2_Set_SpO2_First_Smooth_Sec(15);\r
+    Spo2_Set_SpO2_Correlation_Smooth_Th(0.85f);\r
+    SpO2_Set_Signal_Periodicity_Th(0.50f);\r
+             \r
+    \r
+   /// static  Hr\r
+    version = PxiAlg_Version();\r
+    LOG_PRINT("HR_Version = %d \r\n", version);        \r
+    \r
+    uint32_t Query_Mem_Size = PxiAlg_Query_Mem_Size();\r
+    LOG_PRINT("HR_Mem_Size = %d \r\n", Query_Mem_Size);\r
+    \r
+    _spo2_state.hr_pBuffer = malloc(Query_Mem_Size);\r
+    \r
+    PxiAlg_Open_Mem(_spo2_state.hr_pBuffer);\r
+    \r
+////                \r
+    PxiAlg_SetQualityThreshold(0.35f); \r
+    PxiAlg_SetHRSmoothWeight(0.9f); \r
+    PxiAlg_SetProcWindow(5.0f, 5.0f); \r
+    PxiAlg_SetTimeoutLength(30.0f);\r
+    PxiAlg_SetMemsScale(0);              //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetSkipSampleNum(10); \r
+    PxiAlg_SetMemsScaleBase(1, 0);    //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetForceOutputLink(15, 90, 60, 1, 0.9f); \r
+    PxiAlg_SetNormalOutput(200, 40, 1); \r
+    PxiAlg_SetForceRipple(3, 1); \r
+\r
+    PxiAlg_SetPackage(0, 1);\r
+         \r
+\r
+//-----------------------------------------------//\r
+\r
+       int32_t  alg_count=0;\r
+\r
+       LOG_PRINT("ARRAY_SIZE = %d\n",array_szie(PAH8009_rawdata_SPO2));\r
+//******************************************************************         \r
+    \r
+      \r
+    float   mySpO2          = 0      ;\r
+    float   MEMS_RMS        = 0.0f   ;\r
+    float   myHR            = 0.0f   ;\r
+    int     ret_value  = 0   ;\r
+    float   hr_grader       = 0.0f   ;\r
+    uint8_t ready_flag = 0   ;\r
+    float   correlation     = 0.0f   ;\r
+    float   trust_flag      = 0.0f   ;\r
+    uint8_t no_value_reason = 0      ;\r
+    int     time_accu       = 0      ;\r
+    float   SignalPeriodicity=0.0f   ;\r
+//*******************************************************************         \r
+         \r
+    nrf_delay_ms(10);\r
+         \r
+\r
+    for( i = 0 ; i <array_szie(PAH8009_rawdata_SPO2) ; i ++)\r
+    {\r
+    \r
+        uint32_t  touch_flag         = PAH8009_rawdata_SPO2[i][0];               \r
+        uint32_t  time               = duration_SPO2[i];              \r
+        int       ppg_count_per_ch   = PAH8009_rawdata_SPO2[i][1];    \r
+        int       frame_number       = frame_SPO2[i]; \r
+        int       mems_number        =    PAH8009_mems_SPO2[i][0];         \r
+        int32_t   RAW_DATA [75]       = {0}; \r
+              \r
+        \r
+        //log_printf("RAW_DATA =\n");\r
+        for (j=0;j<ppg_count_per_ch; j++)\r
+        {\r
+            RAW_DATA[j] = PAH8009_rawdata_SPO2[i][j+2] ;\r
+            //log_printf("%d , ", RAW_DATA[j]);\r
+            \r
+        }\r
+         \r
+        \r
+         for( j = 0 ; j <(PAH8009_mems_SPO2[i][0]) ; j ++)\r
+        {            \r
+            mems_data_raw[j].data[0]=PAH8009_mems_SPO2[i][3*j+1];\r
+            mems_data_raw[j].data[1]=PAH8009_mems_SPO2[i][3*j+2];\r
+            mems_data_raw[j].data[2]=PAH8009_mems_SPO2[i][3*j+3];   \r
+        \r
+        }\r
+         \r
+                \r
+\r
+        nrf_delay_ms(10);\r
+        pxialg_data.touch_flag         = touch_flag;\r
+        pxialg_data.time               = time;\r
+        pxialg_data.ppg_data           = (int32_t*)RAW_DATA;\r
+        pxialg_data.nf_ppg_channel     = NF_PPG_CHANNEL;\r
+        pxialg_data.nf_ppg_per_channel = ppg_count_per_ch/NF_PPG_CHANNEL;\r
+        pxialg_data.frame_count        = frame_number;\r
+        pxialg_data.nf_mems            = mems_number;\r
+        pxialg_data.mems_data          = (int16_t*)mems_data_raw;\r
+                 \r
+                 \r
+        \r
+        ret_value = PxiAlg_Entrance(&pxialg_data); \r
+        \r
+        \r
+        alg_count  = alg_count + PAH8009_rawdata_SPO2[i][1]/NF_PPG_CHANNEL ;\r
+        nrf_delay_ms(10);\r
+        \r
+        //if( ret_value == FLAG_DATA_READY) \r
+        if(PxiAlg_GetHrUpdateFlag())\r
+        {\r
+            PxiAlg_HrGet(&myHR);\r
+            ready_flag = PxiAlg_GetReadyFlag();\r
+            PxiAlg_GetSigGrade(&hr_grader);\r
+        \r
+        }\r
+        //ready_flag = PxiAlg_GetReadyFlag();\r
+        //PxiAlg_GetSigGrade(&hr_grader);\r
+                 \r
+                 \r
+        nrf_delay_ms(50);\r
+        SpO2_SetHrValue(myHR);\r
+        SpO2_SetMems(mems_data_raw, pxialg_data.nf_mems);\r
+//        uint32_t time_s = get_tick_count();\r
+        ret_value = SpO2_Process(1, NF_PPG_CHANNEL, pxialg_data.ppg_data, pxialg_data.nf_ppg_per_channel,pxialg_data.time );\r
+        \r
+      //  uint32_t time_e = pah_get_tick_count();\r
+//        uint32_t time_diff=time_e-time_s;\r
+//        log_printf("process-time = %d \n",time_diff);\r
+        \r
+        \r
+        SpO2_GetSpO2(&mySpO2);\r
+        SpO2_GetReadyFlag(&ReadyFlag);\r
+        SpO2_info_t    _spo2_detect_item;\r
+        SpO2_GetInfo(&_spo2_detect_item);\r
+        correlation=_spo2_detect_item.Noise;\r
+        trust_flag =_spo2_detect_item.Output[3];\r
+        no_value_reason=_spo2_detect_item.Output[4];\r
+        SpO2_GetPeriodicity(&SignalPeriodicity);\r
+        MEMS_RMS  =_spo2_detect_item.RMS;\r
+         \r
+                                  \r
+                 \r
+        #if defined(Optimize_SPO2_flow)     \r
+            time_accu=time_accu+time;\r
+        #endif\r
+        nrf_delay_ms(10);\r
+        if( ret_value == 0  && (alg_count>=25) )\r
+        {        \r
+            alg_count = alg_count -25;\r
+            if (ReadyFlag > 0)\r
+            {\r
+                LOG_PRINT("myHR = "LOG_FLOAT_MARKER" ",LOG_FLOAT(myHR));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",grade = "LOG_FLOAT_MARKER" ",LOG_FLOAT(hr_grader));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",spo2 = "LOG_FLOAT_MARKER" ",LOG_FLOAT(mySpO2));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",correlation = "LOG_FLOAT_MARKER" ",LOG_FLOAT(correlation));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",trust_flag = "LOG_FLOAT_MARKER" ",LOG_FLOAT(trust_flag));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(", SignalPeriodicity = "LOG_FLOAT_MARKER" ",LOG_FLOAT(SignalPeriodicity));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",MEMS_RMS    = "LOG_FLOAT_MARKER"  ",LOG_FLOAT(MEMS_RMS));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",reason = %d \n",no_value_reason);\r
+            }\r
+                else\r
+            {\r
+                LOG_PRINT("myHR = "LOG_FLOAT_MARKER" ",LOG_FLOAT(myHR));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",grade = "LOG_FLOAT_MARKER" ",LOG_FLOAT(hr_grader));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",spo2 = "LOG_FLOAT_MARKER" ",LOG_FLOAT(mySpO2));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",correlation = "LOG_FLOAT_MARKER" ",LOG_FLOAT(correlation));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",trust_flag = "LOG_FLOAT_MARKER" ",LOG_FLOAT(trust_flag));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(", SignalPeriodicity = "LOG_FLOAT_MARKER" ",LOG_FLOAT(SignalPeriodicity));\r
+                //nrf_delay_ms(10);\r
+                LOG_PRINT(",MEMS_RMS    = "LOG_FLOAT_MARKER"  ",LOG_FLOAT(MEMS_RMS));\r
+                 //nrf_delay_ms(10);\r
+                LOG_PRINT(",reason = %d \n",no_value_reason);\r
+\r
+            }\r
+                     \r
+//                float  new_spo2=mySpO2;\r
+            \r
+                \r
+       #if defined(Optimize_SPO2_flow)     \r
+            //time_accu=time_accu+time;\r
+            LOG_PRINT("time_accu = %d\n",time_accu);\r
+            if(time_accu>=31000)\r
+            {\r
+                spo2_array[count]=mySpO2;\r
+                count=count+1;\r
+                \r
+                LOG_PRINT("Over_30_sec_Stop_measurement\n");\r
+                LOG_PRINT("This_meausrement_suggest_spo2_value is");\r
+                \r
+                bubblesort(spo2_array,count);\r
+                \r
+                if(count % 2 == 0)\r
+                {\r
+                    //LOG_PRINT(" "LOG_FLOAT_MARKER" \n", LOG_FLOAT(spo2_array[count/2]));\r
+                    LOG_PRINT(" "LOG_FLOAT_MARKER" \n",LOG_FLOAT((spo2_array[(int)(count/2)] + spo2_array[(int)(count/2) - 1]) / 2.0f));  \r
+                }\r
+                else\r
+                {\r
+                    LOG_PRINT(" "LOG_FLOAT_MARKER"\n", LOG_FLOAT(spo2_array[(int)(count/2)]*1.0f));\r
+                }\r
+                count=0;\r
+                nrf_delay_ms(50);\r
+              //add sensor stop here              \r
+                SpO2_Close();\r
+                PxiAlg_Close();\r
+                free(pBuffer);\r
+                free(_spo2_state.hr_pBuffer);\r
+                //NRF_LOG_FLUSH();\r
+                return;                \r
+\r
+            }\r
+            else\r
+            {\r
+                if(mySpO2>0)\r
+                {\r
+                    spo2_array[count]=mySpO2;\r
+                    count=count+1;                    \r
+                }\r
+                                    \r
+            }\r
+            #endif  \r
+        }\r
+        else\r
+        {\r
+        \r
+            switch (ret_value)\r
+            {\r
+                case SPO2_MSG_ALG_NOT_OPEN:\r
+                     LOG_PRINT("Algorithm is not initialized. \n");\r
+                break;\r
+                                \r
+                case SPO2_MSG_ALG_REOPEN:\r
+                     LOG_PRINT("Algorithm is re initialized. \n");\r
+                break;\r
+                                \r
+                case SPO2_MSG_ALG_NOT_SUPPORT:\r
+                     LOG_PRINT("Algorithm is not support. \n");\r
+                break;\r
+                case SPO2_MSG_SUCCESS:\r
+                     //LOG_PRINT("Algorithm is SUCCESS. \n");\r
+                break;                \r
+                default:\r
+                     LOG_PRINT("Algorithm unhandle error = %d \n", ret_value);\r
+                break;\r
+            }\r
+        }\r
+\r
+                \r
+        \r
+        nrf_delay_ms(40); \r
+    }\r
+    \r
+    LOG_PRINT("Out of memory. \n");\r
+    nrf_delay_ms(10);\r
+    SpO2_Close();\r
+    PxiAlg_Close();\r
+    free(pBuffer);\r
+    free(_spo2_state.hr_pBuffer);\r
+    return;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_stress/V6033/pxialg_hrv.h b/code/sdk/drivers/peripheral/ppg/pah8009/algorithm/pah_stress/V6033/pxialg_hrv.h
new file mode 100644 (file)
index 0000000..0e2a007
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _PXIALG_HRV_\r
+#define _PXIALG_HRV_\r
+#include "stdint.h"\r
+\r
+typedef struct\r
+{\r
+    void            *pBuffer;\r
+    float           collect_duration;\r
+    uint8_t         has_got_sdnn;\r
+} hrv_state_s;\r
+\r
+\r
+\r
+#if defined(WIN32) && !defined(PXIALG_STATIC_LIB)\r
+#   ifdef PXIALG_EXPORTS\r
+#       define PXIALG_API   __declspec(dllexport)\r
+#   else\r
+#       define PXIALG_API   __declspec(dllimport)\r
+#   endif\r
+#else\r
+#   define PXIALG_API\r
+#endif // WIN32\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+       PXIALG_API int HRVReset(void);\r
+       PXIALG_API int HRVGetMemorySize(int enable_lhr, int test_seconds, int sampling_rate);\r
+       PXIALG_API int HRVOpen(void *p_buffer);\r
+       PXIALG_API int HRVProcess(int data_ready, float data);\r
+       PXIALG_API int HRVProcessD(int data_ready, uint32_t data);\r
+       PXIALG_API int HRVClose(void);\r
+\r
+       PXIALG_API int HRVGetVersion(void);\r
+       PXIALG_API float HRVGetSDNN(void);\r
+       PXIALG_API int HRVGetSDNNLevel(int m_iAge, float dSDNN);\r
+       PXIALG_API float HRVGetLHRatio(float *nlf, float *nhf);\r
+       PXIALG_API float HRVGetRMSSD(void);\r
+       PXIALG_API int HRVGetSleepQuality(int age);\r
+       PXIALG_API int HRVGetOnlineRRIReportFlag(void);\r
+       PXIALG_API float HRVGetOnlineRRI(void);\r
+       PXIALG_API int HRVGetRawRRINum(void);\r
+       PXIALG_API float * HRVGetRawRRIBuf(void);\r
+       PXIALG_API float HRVGetNoiseRate(void);\r
+       PXIALG_API float HRVGetRRIStability(void);\r
+       PXIALG_API float HRVGetRRIQuality(void);\r
+       PXIALG_API int HRVGetReadyFlag(void);\r
+       PXIALG_API int HRVGetMotionFlag(void);\r
+       PXIALG_API int HRVGetAnomalyFlag(void);\r
+       PXIALG_API int HRVGetHRAvg(void);\r
+\r
+       PXIALG_API void HRVSetSkipCounterTh(int SkipCounterTh);\r
+       PXIALG_API void HRVSetFreqOffset(float FreqOffset);\r
+       PXIALG_API void HRVSetDiffTime(float DiffTime, int SampleNum);\r
+       PXIALG_API void HRVSetPeakProcessReadyCounterTh(int PeakProcessReady3Counter_Th0,\r
+                                                                                       int PeakProcessReady3Counter_Th1,\r
+                                                                                       int PeakProcessReady3Counter_Th2,\r
+                                                                                       int PeakProcessReady3Counter_Th3,\r
+                                                                                       int m_PeakProcessReady3Counter_HeartRate_Th1,\r
+                                                                                       int m_PeakProcessReady3Counter_HeartRate_Th2,\r
+                                                                                       int m_PeakProcessReady3Counter_HeartRate_Th3);\r
+\r
+       PXIALG_API float HRVGetStress(int grade);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* _PXIALG_HRV_ */\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah8009_factory_reg.h b/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah8009_factory_reg.h
new file mode 100644 (file)
index 0000000..af20cbf
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef __pah8009_factory_reg_h__\r
+#define __pah8009_factory_reg_h__\r
+\r
+// pah\r
+#include "pah800x_factory_test.h"\r
+\r
+\r
+static const uint8_t PAH_800x_REG_DEVICE_INIT_FACTORY[][2] = {\r
+//  { 0xEE,0x07 }, //SW RESET\r
+    { 0xE8,0x00 },//Close suspend\r
+    { 0xD1,0xD0 },//{R_GPIO_0_IEB, R_GPIO_1_IEB, R_GPIO_0_OEB, R_GPIO_1_OEB, R_GPIO_0_PULLL_EnH, R_GPIO_1_PULLL_EnH, R_GPIO_0_PULLH_EnH, R_GPIO_1_PULLH_EnH};\r
+    { 0xD2,0x00 },//R_GPIO_0_Open_Drain_EnH(0xD2[5]), 1(0x20):GPIO default open-drain mode, 0(0x00):GPIO debug mode\r
+    { 0xD3,0x20 },//GPIO debug select\r
+//     { 0xD6,0x30 },//{Dummy, R_I2C_SLEW, R_I2C_DRV[1:0], Dummy[3:0]}\r
+//     { 0xD5,0x44 },//IO-level(I2C), 44:3.3V, 00:1.8V\r
+//     { 0xB2,0x25 },\r
+       { 0x55,0x24 },//Soft Reset:04 Hard Reset:24\r
+       { 0x52,0x12 },//VDDAY=1.63V\r
+//     { 0xA6,0xF7 },//Cmd_vdday_pwrsv_sel_EnH=0\r
+       { 0xAE,0x3F },//R_LPO_Cali_mode=1\r
+};\r
+\r
+static const uint8_t PAH_800x_REG_BRIGHTNESS_TEST_FACTORY[][2] = {\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x08,0x00 },//A period\r
+    { 0x09,0x08 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x08 },//C period\r
+    { 0x0E,0x01 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x01 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x77 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x52 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x44 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x44 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x00 },//RDB_expo_A[7:0]\r
+    { 0x18,0x01 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x01 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x00 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x01 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x2F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x4F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x2A },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0xEB,0x80 },//update_flag\r
+//  { 0x20,0xF7 },//Clear INT\r
+};\r
+\r
+static const uint8_t PAH_800x_REG_LEAK_LIGHT_TEST_FACTORY[][2] = {\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x08,0x00 },//A period\r
+    { 0x09,0x08 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x08 },//C period\r
+    { 0x0E,0x01 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x01 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x77 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x0A },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x8A },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x00 },//RDB_expo_A[7:0]\r
+    { 0x18,0x02 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x02 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x2F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x4F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x2A },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0xEB,0x80 },//update_flag\r
+//  { 0x20,0xF7 },//Clear INT\r
+};\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void factory_test_mode(factory_test_type test_type, bool expo_adjust_en, uint16_t expo_a, uint16_t expo_b, uint16_t expo_c);\r
+\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.c b/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.c
new file mode 100644 (file)
index 0000000..d4cd39c
--- /dev/null
@@ -0,0 +1,556 @@
+// pah\r
+#include "pah800x_factory_test.h"\r
+#include "pah8009_factory_reg.h"\r
+\r
+static uint16_t factory_test_ch[3] = {0};\r
+\r
+//============================================================================\r
+// Static Global Variable\r
+//============================================================================\r
+static pah_800x_test_t _factory_state;\r
+static pah_verify_config_t     g_config_table[test_type_num] =\r
+{\r
+       //factory_tesst_num=0\r
+       {\r
+               .ch_spec[0] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_GLODEN_CHA_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_GLODEN_CHA_MIN_ENABLE, .max_enabled = BRIGHTNESS_GLODEN_CHA_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_GLODEN_CHA_MIN, .max = BRIGHTNESS_GLODEN_CHA_MAX\r
+               },\r
+               .ch_spec[1] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_GLODEN_CHB_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_GLODEN_CHB_MIN_ENABLE, .max_enabled = BRIGHTNESS_GLODEN_CHB_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_GLODEN_CHB_MIN, .max = BRIGHTNESS_GLODEN_CHB_MAX\r
+               },\r
+               .ch_spec[2] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_GLODEN_CHC_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_GLODEN_CHC_MIN_ENABLE, .max_enabled = BRIGHTNESS_GLODEN_CHC_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_GLODEN_CHC_MIN, .max = BRIGHTNESS_GLODEN_CHC_MAX\r
+               },\r
+               .test_regs =\r
+               {\r
+                       .init_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_DEVICE_INIT_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_DEVICE_INIT_FACTORY)\r
+                       },\r
+                       .test_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_BRIGHTNESS_TEST_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_BRIGHTNESS_TEST_FACTORY)\r
+                       }\r
+               }\r
+       },\r
+\r
+       //factory_tesst_num=1\r
+       {\r
+               .ch_spec[0] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_TARGET_CHA_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_TARGET_CHA_MIN_ENABLE, .max_enabled = BRIGHTNESS_TARGET_CHA_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_TARGET_CHA_MIN, .max = BRIGHTNESS_TARGET_CHA_MAX\r
+               },\r
+               .ch_spec[1] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_TARGET_CHB_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_TARGET_CHB_MIN_ENABLE, .max_enabled = BRIGHTNESS_TARGET_CHB_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_TARGET_CHB_MIN, .max = BRIGHTNESS_TARGET_CHB_MAX\r
+               },\r
+               .ch_spec[2] =\r
+               {\r
+                       .verify_enabled = BRIGHTNESS_TARGET_CHC_ENABLE,\r
+                       .min_enabled = BRIGHTNESS_TARGET_CHC_MIN_ENABLE, .max_enabled = BRIGHTNESS_TARGET_CHC_MAX_ENABLE,\r
+                       .min = BRIGHTNESS_TARGET_CHC_MIN, .max = BRIGHTNESS_TARGET_CHC_MAX\r
+               },\r
+               .test_regs =\r
+               {\r
+                       .init_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_DEVICE_INIT_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_DEVICE_INIT_FACTORY)\r
+                       },\r
+                       .test_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_BRIGHTNESS_TEST_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_BRIGHTNESS_TEST_FACTORY)\r
+                       }\r
+               }\r
+       },\r
+\r
+       //factory_tesst_num=2\r
+       {\r
+               .ch_spec[0] =\r
+               {\r
+                       .verify_enabled = LEAK_LIGHT_TARGET_CHA_ENABLE,\r
+                       .min_enabled = LEAK_LIGHT_TARGET_CHA_MIN_ENABLE, .max_enabled = LEAK_LIGHT_TARGET_CHA_MAX_ENABLE,\r
+                       .min = LEAK_LIGHT_TARGET_CHA_MIN, .max = LEAK_LIGHT_TARGET_CHA_MAX\r
+               },\r
+               .ch_spec[1] =\r
+               {\r
+                       .verify_enabled = LEAK_LIGHT_TARGET_CHB_ENABLE,\r
+                       .min_enabled = LEAK_LIGHT_TARGET_CHB_MIN_ENABLE, .max_enabled = LEAK_LIGHT_TARGET_CHB_MAX_ENABLE,\r
+                       .min = LEAK_LIGHT_TARGET_CHB_MIN, .max = LEAK_LIGHT_TARGET_CHB_MAX\r
+               },\r
+               .ch_spec[2] =\r
+               {\r
+                       .verify_enabled = LEAK_LIGHT_TARGET_CHC_ENABLE,\r
+                       .min_enabled = LEAK_LIGHT_TARGET_CHC_MIN_ENABLE, .max_enabled = LEAK_LIGHT_TARGET_CHC_MAX_ENABLE,\r
+                       .min = LEAK_LIGHT_TARGET_CHC_MIN, .max = LEAK_LIGHT_TARGET_CHC_MAX\r
+               },\r
+               .test_regs =\r
+               {\r
+                       .init_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_DEVICE_INIT_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_DEVICE_INIT_FACTORY)\r
+                       },\r
+                       .test_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_LEAK_LIGHT_TEST_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_LEAK_LIGHT_TEST_FACTORY)\r
+                       }\r
+               }\r
+       },\r
+\r
+       //factory_tesst_num=3\r
+       {\r
+               .test_regs =\r
+               {\r
+                       .init_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_DEVICE_INIT_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_DEVICE_INIT_FACTORY)\r
+                       },\r
+                       .test_reg_arr =\r
+                       {\r
+                               .reg_arr = (pah_reg*)PAH_800x_REG_LEAK_LIGHT_TEST_FACTORY,\r
+                               .reg_arr_len = PAH_ARRAY_SIZE(PAH_800x_REG_LEAK_LIGHT_TEST_FACTORY)\r
+                       }\r
+               }\r
+       }\r
+\r
+};\r
+\r
+//============================================================================\r
+// Private function\r
+//============================================================================\r
+static void pah_sensor_factory_mode_init(factory_test_type test_type, bool expo_adjust_en, uint16_t expo_a, uint16_t expo_b, uint16_t expo_c);\r
+static void pah_sensor_factory_mode_start(void);\r
+static void pah_sensor_factory_mode_stop(void);\r
+static void pah_sensor_factory_mode_task(void);\r
+static void pah_sensor_factory_mode_verify_result(void);\r
+\r
+static pah_ret _pah_800x_hal_comm_write(uint8_t addr, const uint8_t *data, size_t write_size);\r
+static pah_ret _pah_800x_hal_comm_read(uint8_t addr, uint8_t *data, size_t read_size);\r
+static pah_ret _comm_write(uint8_t addr, uint8_t data);\r
+\r
+static pah_ret _pah_800x_hal_write_reg_arr(const pah_reg_arr *reg_arr);\r
+static pah_ret _pah_800x_hal_write_reg_array(const uint8_t reg_array[][2], size_t length);\r
+static pah_ret _pah_800x_hal_write_suspend_state(bool suspend);\r
+static pah_ret _pah_800x_hal_write_interrupt_clear(void);\r
+static pah_ret _pah_800x_hal_write_ch_exposure(uint16_t expo_a, uint16_t expo_b, uint16_t expo_c, uint8_t ch_num);\r
+static pah_ret _pah_800x_hal_tg_toggle(bool enable);\r
+static pah_ret _pah_800x_hal_update_flag(void);\r
+\r
+static pah_ret _pah_800x_hal_read_product_id(uint16_t *product_id);\r
+static pah_ret _pah_800x_hal_read_ppg_interrupt(uint8_t *ppg_interrupt);\r
+static pah_ret _pah_800x_hal_read_ppg_overflow(uint8_t *ppg_overflow, uint8_t *overflow_num);\r
+static pah_ret _pah_800x_hal_read_ppg_adc(uint16_t *ppg_adc, uint8_t ch_num);\r
+static pah_ret _pah_800x_hal_check_enable_channel(pah_800x_test_t *factory_state, const pah_reg_arr *reg_arr);\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void factory_test_mode(factory_test_type test_type, bool expo_adjust_en, uint16_t expo_a, uint16_t expo_b, uint16_t expo_c)\r
+{\r
+       LOG_PRINT("test_type=%d\n{\n factory_test_brightness_golden_sample=0\n "        \\r
+                         "factory_test_brightness_target_sample=1\n factory_test_leak_light_target_sample=2\n "        \\r
+                         "factory_test_power_noise=3\n factory_test_INT_high=4\n factory_test_INT_low=5\n}\n", test_type);\r
+\r
+       pah_sensor_factory_mode_init(test_type, expo_adjust_en, expo_a, expo_b, expo_c);\r
+\r
+       pah_sensor_factory_mode_start();\r
+\r
+    pah_delay_ms(25);\r
+\r
+    if (test_type < factory_test_power_noise)\r
+    {\r
+       pah_sensor_factory_mode_task();\r
+       pah_sensor_factory_mode_verify_result();\r
+        pah_sensor_factory_mode_stop();\r
+    }\r
+    else\r
+    {\r
+       return;\r
+    }\r
+\r
+    pah_delay_ms(500);\r
+\r
+    return;\r
+\r
+}\r
+\r
+\r
+//============================================================================\r
+// Private function \r
+//============================================================================\r
+static void pah_sensor_factory_mode_init(factory_test_type test_type, bool expo_adjust_en, uint16_t expo_a, uint16_t expo_b, uint16_t expo_c)\r
+{\r
+       DEBUG_PRINT("%s(%d)\n", __func__, test_type);\r
+\r
+    memset(&_factory_state, 0, sizeof(_factory_state));\r
+\r
+    uint16_t product_id = 0;\r
+    _pah_800x_hal_read_product_id(&product_id);\r
+    DEBUG_PRINT("product_id = 0x%04X\n", product_id);\r
+    if (product_id != PAH_800x_PRODUCT_ID)\r
+    {\r
+       DEBUG_PRINT("Failed to verify product_id\n");\r
+    }\r
+/**/\r
+       for (int ch_index=0; ch_index<3; ch_index++)\r
+       {\r
+               _factory_state.verify_config.ch_spec[ch_index] = g_config_table[test_type].ch_spec[ch_index];\r
+       }\r
+\r
+       _factory_state.verify_config.test_regs = g_config_table[test_type].test_regs;\r
+    _pah_800x_hal_write_reg_arr(&_factory_state.verify_config.test_regs.init_reg_arr);\r
+    _pah_800x_hal_write_reg_arr(&_factory_state.verify_config.test_regs.test_reg_arr);\r
+       _pah_800x_hal_check_enable_channel(&_factory_state, &_factory_state.verify_config.test_regs.test_reg_arr);\r
+/**/\r
+       if (expo_adjust_en) \r
+       {\r
+        for(uint8_t ch_num=0; ch_num<PAH_800x_MAX_CH_NUM; ch_num++)\r
+               {\r
+               _pah_800x_hal_write_ch_exposure(expo_a, expo_b, expo_c, ch_num);\r
+               }\r
+        _pah_800x_hal_update_flag();\r
+       }\r
+\r
+       _pah_800x_hal_write_interrupt_clear();\r
+\r
+//     PAH_REG_ARR_SETUP(_factory_state.verify_config.test_regs.init_reg_arr, PAH_800x_REG_DEVICE_INIT_FACTORY);\r
+//     _pah_800x_hal_write_reg_arr(&_factory_state.verify_config.test_regs.init_reg_arr);\r
+}\r
+\r
+static void pah_sensor_factory_mode_start(void)\r
+{\r
+       DEBUG_PRINT("%s\n", __func__);\r
+\r
+    _pah_800x_hal_write_suspend_state(false);\r
+    _pah_800x_hal_tg_toggle(true);\r
+\r
+}\r
+\r
+static void pah_sensor_factory_mode_stop(void)\r
+{\r
+       DEBUG_PRINT("%s\n", __func__);\r
+\r
+    _pah_800x_hal_tg_toggle(false);\r
+    _pah_800x_hal_write_suspend_state(true);\r
+\r
+}\r
+\r
+static void pah_sensor_factory_mode_task(void)\r
+{\r
+       DEBUG_PRINT("%s\n", __func__);\r
+\r
+    uint8_t ppg_interrupt = 0;\r
+    bool has_ppg_interrupt = false;\r
+    uint8_t ppg_overflow = 0;\r
+    uint8_t overflow_num = 0;\r
+\r
+    _pah_800x_hal_read_ppg_interrupt(&ppg_interrupt);\r
+    _pah_800x_hal_read_ppg_overflow(&ppg_overflow, &overflow_num);\r
+\r
+    has_ppg_interrupt = (ppg_interrupt > 0);\r
+    if (has_ppg_interrupt > 0)\r
+    {\r
+        for (uint8_t ch_num=0; ch_num < PAH_800x_MAX_CH_NUM; ch_num++)\r
+        {\r
+            if (_factory_state.test_ch_enabled[ch_num])\r
+            {\r
+               _pah_800x_hal_read_ppg_adc(&_factory_state.test_result.adc[ch_num], ch_num);\r
+            }\r
+        }\r
+    }\r
+\r
+    //clear_interrupt(state, has_ppg_interrupt, state->ppg_result.has_overflow);\r
+\r
+}\r
+\r
+static void pah_sensor_factory_mode_verify_result(void)\r
+{\r
+       DEBUG_PRINT("%s\n", __func__);\r
+       LOG_PRINT("=============== Verify_Result ===============\n"     \\r
+                         "{\n result=1 : pass\n result=0 : fail\n}\n");\r
+\r
+       for (int i=0; i<PAH_800x_MAX_CH_NUM; ++i)\r
+       {\r
+               if (_factory_state.verify_config.ch_spec[i].verify_enabled\r
+                       && _factory_state.verify_config.ch_spec[i].min_enabled\r
+                       && _factory_state.verify_config.ch_spec[i].max_enabled)\r
+               {\r
+                       if (_factory_state.test_result.adc[i] < _factory_state.verify_config.ch_spec[i].min\r
+                               || _factory_state.test_result.adc[i] > _factory_state.verify_config.ch_spec[i].max)\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = true;\r
+                       }\r
+                       printf("ch[%d] : (min, value, max)=(%d, %d, %d), result=%d \n",\\r
+                                               i, _factory_state.verify_config.ch_spec[i].min, \\r
+                                               _factory_state.test_result.adc[i], \\r
+                                               _factory_state.verify_config.ch_spec[i].max, \\r
+                                               _factory_state.verify_result.ch_result[i].is_passed);\r
+               }\r
+               else if (_factory_state.verify_config.ch_spec[i].verify_enabled\r
+                                && _factory_state.verify_config.ch_spec[i].min_enabled)\r
+               {\r
+                       if (_factory_state.test_result.adc[i] < _factory_state.verify_config.ch_spec[i].min)\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = true;\r
+                       }\r
+                       printf("ch[%d] : (min, value)=(%d, %d), result=%d \n",\\r
+                                               i, _factory_state.verify_config.ch_spec[i].min, \\r
+                                               _factory_state.test_result.adc[i], \\r
+                                               _factory_state.verify_result.ch_result[i].is_passed);\r
+               }\r
+               else if (_factory_state.verify_config.ch_spec[i].verify_enabled\r
+                               && _factory_state.verify_config.ch_spec[i].max_enabled)\r
+               {\r
+                       if (_factory_state.test_result.adc[i] > _factory_state.verify_config.ch_spec[i].max)\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               _factory_state.verify_result.ch_result[i].is_passed = true;\r
+                       }\r
+\r
+                       factory_test_ch[i] = _factory_state.test_result.adc[i];\r
+\r
+                       printf("ch[%d] : (value, max)=(%d, %d), result=%d \n",\\r
+                                               i, _factory_state.test_result.adc[i], \\r
+                                               _factory_state.verify_config.ch_spec[i].max, \\r
+                                               _factory_state.verify_result.ch_result[i].is_passed);\r
+               }\r
+       }\r
+}\r
+\r
+\r
+//============================================================================\r
+// Private function (HAL)\r
+//============================================================================\r
+static pah_ret _pah_800x_hal_comm_write(uint8_t addr, const uint8_t *data, size_t write_size)\r
+{\r
+    //return plat->comm.write(&plat->comm, addr, data, write_size);\r
+    //return plat->comm.write(addr, data, write_size);\r
+    return pah_comm_i2c_write(addr, data, write_size);\r
+}\r
+\r
+static pah_ret _pah_800x_hal_comm_read(uint8_t addr, uint8_t *data, size_t read_size)\r
+{\r
+\r
+    //return plat->comm.read(&plat->comm, addr, data, read_size);\r
+    return pah_comm_i2c_read(addr, data, read_size);\r
+}\r
+\r
+static pah_ret _comm_write(uint8_t addr, uint8_t data)\r
+{\r
+    //return pah_800x_hal_comm_write( addr, &data, 1);\r
+    return _pah_800x_hal_comm_write(addr, &data, 1);\r
+}\r
+#define _comm_read(addr, data)                     _pah_800x_hal_comm_read(addr, data, 1)\r
+#define _comm_burst_read(addr, data, read_size)    _pah_800x_hal_comm_read(addr, data, read_size)\r
+\r
+\r
+static pah_ret _pah_800x_hal_write_reg_arr(const pah_reg_arr *reg_arr)\r
+{\r
+    return _pah_800x_hal_write_reg_array(reg_arr->reg_arr, reg_arr->reg_arr_len);\r
+}\r
+\r
+static pah_ret _pah_800x_hal_write_reg_array(const uint8_t reg_array[][2], size_t length)\r
+{\r
+    size_t i = 0;\r
+    uint8_t reg_value = 0;\r
+    for (i = 0; i < length; ++i)\r
+    {\r
+        //for trim bit\r
+        if(reg_array[i][0] == 0x14)\r
+        {\r
+            _comm_read(0x14, &reg_value);\r
+            reg_value = (reg_value & 0x1F) | (reg_array[i][1] & 0xE0);\r
+            _comm_write(reg_array[i][0], reg_value);\r
+        }\r
+        else\r
+               _comm_write(reg_array[i][0], reg_array[i][1]);\r
+    }\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_write_suspend_state(bool suspend)\r
+{\r
+    uint8_t data = 0;\r
+    DEBUG_PRINT("%s(%d)\n", __func__, suspend);\r
+    if (suspend)\r
+    {\r
+        _comm_read(PAH_800x_ADDR_E8, &data);\r
+        PAH_SET_BIT(data, PAH_800x_ADDR_E8_CMD_SUSPEND_MODE_BIT);\r
+        _comm_write(PAH_800x_ADDR_E8, data);\r
+    }\r
+    else\r
+    {\r
+        _comm_read(PAH_800x_ADDR_E8, &data);\r
+        PAH_CLEAR_BIT(data, PAH_800x_ADDR_E8_CMD_SUSPEND_MODE_BIT);\r
+        _comm_write(PAH_800x_ADDR_E8, data);\r
+\r
+    }\r
+    DEBUG_PRINT("%s(%d) end\n", __func__, suspend);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_write_interrupt_clear(void)\r
+{\r
+    uint8_t data = 0;\r
+    // DR interrupt\r
+    _comm_read(PAH_800x_ADDR_20, &data);\r
+    //PAH_CLEAR_BIT(data, PAH_800x_ADDR_20_BIT_DR_FLAG);\r
+    _comm_write(PAH_800x_ADDR_20, (data|0x04));        //SD-revise-20191205\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_write_ch_exposure(uint16_t expo_a, uint16_t expo_b, uint16_t expo_c, uint8_t ch_num)\r
+{\r
+    //uint8_t data = 0;\r
+    DEBUG_PRINT("%s(%d, %d, %d, %d)\n", __func__, expo_a, expo_b, expo_c, ch_num);\r
+\r
+    uint8_t a_exposure_low = PAH_UINT16_LOW(expo_a);\r
+    uint8_t a_exposure_high = PAH_UINT16_HIGH(expo_a);\r
+    uint8_t b_exposure_low = PAH_UINT16_LOW(expo_b);\r
+    uint8_t b_exposure_high = PAH_UINT16_HIGH(expo_b);\r
+    uint8_t c_exposure_low = PAH_UINT16_LOW(expo_c);\r
+    uint8_t c_exposure_high = PAH_UINT16_HIGH(expo_c);\r
+\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+    {\r
+        _comm_write(PAH_800x_ADDR_17, a_exposure_low);\r
+        _comm_write(PAH_800x_ADDR_18, a_exposure_high);\r
+    }\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+    {\r
+        _comm_write(PAH_800x_ADDR_19, b_exposure_low);\r
+        _comm_write(PAH_800x_ADDR_1A, b_exposure_high);\r
+    }\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+    {\r
+        _comm_write(PAH_800x_ADDR_1B, c_exposure_low);\r
+        _comm_write(PAH_800x_ADDR_1C, c_exposure_high);\r
+    }\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_tg_toggle(bool enable)\r
+{\r
+    uint8_t data = 0;\r
+    DEBUG_PRINT("%s(%d)\n", __func__, enable);\r
+    _comm_read( PAH_800x_ADDR_07_TG, &data);\r
+    if(enable)\r
+        PAH_SET_BIT(data, PAH_800x_ADDR_07_TG_BIT_EN);\r
+    else\r
+        PAH_CLEAR_BIT(data, PAH_800x_ADDR_07_TG_BIT_EN);\r
+    _comm_write(PAH_800x_ADDR_07_TG, data);\r
+\r
+       return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_update_flag(void)\r
+{\r
+     _comm_write(PAH_800x_ADDR_EB, PAH_800x_ADDR_E8_UPDATE_FLAG);\r
+\r
+     return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_read_product_id(uint16_t *product_id)\r
+{\r
+    return _comm_burst_read(PAH_800x_ADDR_00_PRODUCT_ID, (uint8_t *)product_id,2);\r
+}\r
+\r
+static pah_ret _pah_800x_hal_read_ppg_interrupt(uint8_t *ppg_interrupt)\r
+{\r
+    uint8_t data = 0;\r
+    _comm_read(PAH_800x_ADDR_20, &data);\r
+    if (ppg_interrupt)\r
+        *ppg_interrupt = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_DR_FLAG);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_read_ppg_overflow(uint8_t *ppg_overflow, uint8_t *overflow_num)\r
+{\r
+    uint8_t data = 0;\r
+    _comm_read( PAH_800x_ADDR_20, &data);\r
+    if (ppg_overflow)\r
+    {\r
+        *ppg_overflow = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_OVERFLOW_FLAG);\r
+        *overflow_num = (data&0x70)>>4;\r
+    }\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_read_ppg_adc(uint16_t *ppg_adc, uint8_t ch_num)\r
+{\r
+    uint16_t data = 0;\r
+\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+        _comm_burst_read(PAH_800x_ADDR_2E, (uint8_t*)&data, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+        _comm_burst_read(PAH_800x_ADDR_39, (uint8_t*)&data, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+        _comm_burst_read(PAH_800x_ADDR_44, (uint8_t*)&data, 2);\r
+\r
+    //*ppg_adc = data >> 2;\r
+    *ppg_adc = data >> 2;\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret _pah_800x_hal_check_enable_channel(pah_800x_test_t *factory_state, const pah_reg_arr *reg_arr)\r
+{\r
+    for(int i=0;i<reg_arr->reg_arr_len;i++)\r
+    {\r
+        if(reg_arr->reg_arr[i][0] == PAH_800x_ADDR_11_EnCh)\r
+        {\r
+            uint8_t data = reg_arr->reg_arr[i][1];\r
+            factory_state->test_ch_enabled[0] = PAH_CHECK_BIT(data, 0); // CH A\r
+            factory_state->test_ch_enabled[1] = PAH_CHECK_BIT(data, 1); // CH B\r
+            factory_state->test_ch_enabled[2] = PAH_CHECK_BIT(data, 2); // CH C\r
+        }\r
+    }\r
+\r
+               return PAH_RET_SUCCESS;\r
+}\r
+\r
+\r
+void pah8009_get_leaklight_data(uint16_t *ch0,uint16_t *ch1,uint16_t *ch2)\r
+{\r
+       *ch0 = factory_test_ch[0];\r
+       *ch1 = factory_test_ch[1];\r
+       *ch2 = factory_test_ch[2];\r
+\r
+       factory_test_ch[0] = 0;\r
+       factory_test_ch[1] = 0;\r
+       factory_test_ch[2] = 0;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.h b/code/sdk/drivers/peripheral/ppg/pah8009/factory/pah800x_factory_test.h
new file mode 100644 (file)
index 0000000..7519958
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef __pah800x_factory_test_h__\r
+#define __pah800x_factory_test_h__\r
+\r
+// pah\r
+//#include "pah_800x.h"\r
+#include "pah_unit.h"\r
+#include "pah_800x_config.h"\r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+\r
+/*---------Brightness Test Golden Option---------*/\r
+#define BRIGHTNESS_GLODEN_CHA_ENABLE           true\r
+#define BRIGHTNESS_GLODEN_CHA_MIN_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHA_MAX_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHA_MIN                      7600\r
+#define BRIGHTNESS_GLODEN_CHA_MAX                      8400\r
+#define BRIGHTNESS_GLODEN_CHB_ENABLE           true\r
+#define BRIGHTNESS_GLODEN_CHB_MIN_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHB_MAX_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHB_MIN                      7600\r
+#define BRIGHTNESS_GLODEN_CHB_MAX                      8400\r
+#define BRIGHTNESS_GLODEN_CHC_ENABLE           true\r
+#define BRIGHTNESS_GLODEN_CHC_MIN_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHC_MAX_ENABLE       true\r
+#define BRIGHTNESS_GLODEN_CHC_MIN                      7600\r
+#define BRIGHTNESS_GLODEN_CHC_MAX                      8400\r
+\r
+/*---------Brightness Test Target Option---------*/\r
+#define BRIGHTNESS_TARGET_CHA_ENABLE           true\r
+#define BRIGHTNESS_TARGET_CHA_MIN_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHA_MAX_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHA_MIN                      2400\r
+#define BRIGHTNESS_TARGET_CHA_MAX                      15200\r
+#define BRIGHTNESS_TARGET_CHB_ENABLE           true\r
+#define BRIGHTNESS_TARGET_CHB_MIN_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHB_MAX_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHB_MIN                      2400\r
+#define BRIGHTNESS_TARGET_CHB_MAX                      15200\r
+#define BRIGHTNESS_TARGET_CHC_ENABLE           true\r
+#define BRIGHTNESS_TARGET_CHC_MIN_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHC_MAX_ENABLE       true\r
+#define BRIGHTNESS_TARGET_CHC_MIN                      4000\r
+#define BRIGHTNESS_TARGET_CHC_MAX                      12000\r
+\r
+/*---------Brightness Test Target Option---------*/\r
+#define LEAK_LIGHT_TARGET_CHA_ENABLE           true\r
+#define LEAK_LIGHT_TARGET_CHA_MIN_ENABLE       false\r
+#define LEAK_LIGHT_TARGET_CHA_MAX_ENABLE       true\r
+#define LEAK_LIGHT_TARGET_CHA_MIN                      0\r
+#define LEAK_LIGHT_TARGET_CHA_MAX                      160\r
+#define LEAK_LIGHT_TARGET_CHB_ENABLE           true\r
+#define LEAK_LIGHT_TARGET_CHB_MIN_ENABLE       false\r
+#define LEAK_LIGHT_TARGET_CHB_MAX_ENABLE       true\r
+#define LEAK_LIGHT_TARGET_CHB_MIN                      0\r
+#define LEAK_LIGHT_TARGET_CHB_MAX                      160\r
+#define LEAK_LIGHT_TARGET_CHC_ENABLE           true\r
+#define LEAK_LIGHT_TARGET_CHC_MIN_ENABLE       false\r
+#define LEAK_LIGHT_TARGET_CHC_MAX_ENABLE       true\r
+#define LEAK_LIGHT_TARGET_CHC_MIN                      0\r
+#define LEAK_LIGHT_TARGET_CHC_MAX                      160\r
+\r
+\r
+//============================================================================\r
+// Type Definition\r
+//============================================================================\r
+typedef enum\r
+{\r
+       factory_test_brightness_golden_sample,\r
+       factory_test_brightness_target_sample,\r
+       factory_test_leak_light_target_sample,\r
+       factory_test_power_noise,\r
+       factory_test_INT_high,\r
+       factory_test_INT_low,\r
+       test_type_num,\r
+\r
+} factory_test_type;\r
+\r
+typedef struct\r
+{\r
+       bool            verify_enabled;\r
+\r
+       bool            min_enabled;\r
+       bool            max_enabled;\r
+\r
+       uint16_t    min;\r
+    uint16_t    max;\r
+\r
+} pah_ch_verify_spec_t;\r
+\r
+typedef struct\r
+{\r
+    pah_reg_arr     init_reg_arr;\r
+    pah_reg_arr                test_reg_arr;\r
+\r
+} pah_verify_reg_t;\r
+\r
+typedef struct\r
+{\r
+       pah_ch_verify_spec_t    ch_spec[PAH_800x_MAX_CH_NUM];\r
+\r
+       pah_verify_reg_t                test_regs;\r
+\r
+} pah_verify_config_t;\r
+\r
+typedef struct\r
+{\r
+    bool        has_data;\r
+\r
+    // Avaiable only if has_data is true\r
+    bool        has_overflow;\r
+\r
+    uint8_t     overflow_num;\r
+\r
+    // Avaiable only if has_data is true\r
+    uint16_t    exposure_time[PAH_800x_MAX_CH_NUM];\r
+    uint16_t    adc[PAH_800x_MAX_CH_NUM];\r
+\r
+} pah_test_result_t;\r
+\r
+typedef struct\r
+{\r
+    uint16_t   adc;\r
+\r
+    bool               is_passed;\r
+\r
+} pah_ch_verify_result_t;\r
+\r
+typedef struct\r
+{\r
+    pah_ch_verify_result_t             ch_result[PAH_800x_MAX_CH_NUM];\r
+\r
+} pah_verify_result_t;\r
+\r
+typedef struct\r
+{\r
+    // Config\r
+    //pah_plat            plat;\r
+       pah_verify_config_t             verify_config;\r
+\r
+    bool                                       test_ch_enabled[PAH_800x_MAX_CH_NUM];\r
+\r
+    // PPG state\r
+    pah_test_result_t          test_result;\r
+\r
+    // verify\r
+    pah_verify_result_t                verify_result;\r
+\r
+} pah_800x_test_t;\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void factory_test_mode(factory_test_type test_type, bool expo_adjust_en, uint16_t expo_a, uint16_t expo_b, uint16_t expo_c);\r
+void pah8009_get_leaklight_data(uint16_t *ch0,uint16_t *ch1,uint16_t *ch2);\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c
new file mode 100644 (file)
index 0000000..a208d81
--- /dev/null
@@ -0,0 +1,85 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-05-27 11:09:04\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-06-04 15:38:48\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_bsp.c\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+// pah\r
+#include "pah800x_bsp.h"\r
+#include "custom_utils.h"\r
+#include "systick.h"\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+#define PAH800xx_I2C_SLAVE_ID 0x40\r
+#define I2C_PPG_PORT_ID 1\r
+#define PAH800xx_I2C_BUS I2C_BUS_2\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void pah_delay_ms(uint32_t ms)\r
+{\r
+    // pxi_nrf_delay_ms(ms);\r
+    LOS_Mdelay(ms);\r
+}\r
+\r
+uint64_t pah_get_tick_count(void)\r
+{\r
+    // return pxi_nrf_get_tick_count();\r
+    uint64_t cnt = uapi_systick_get_ms();\r
+    // printf("cnt : %llu\n",cnt);\r
+    return cnt;\r
+}\r
+\r
+pah_ret pah_comm_i2c_write(uint8_t addr, const uint8_t *data, size_t write_size)\r
+{\r
+    //DEBUG_PRINT("W A:0x%02x,D:0x%02x\n",addr,*data);\r
+    // pxi_nrf_i2c_write(addr, data, write_size);\r
+    custom_i2c_write_reg(PAH800xx_I2C_SLAVE_ID, addr, 1, data, write_size, PAH800xx_I2C_BUS);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_comm_i2c_read(uint8_t addr, uint8_t *data, size_t read_size)\r
+{\r
+    // pxi_nrf_i2c_read(addr, data, read_size);\r
+    custom_i2c_read_regs(PAH800xx_I2C_SLAVE_ID, addr, 1 , data, read_size, PAH800xx_I2C_BUS);\r
+    //DEBUG_PRINT("R A:0x%02x,D:0x%02x\n",addr,*data);\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+void pah_print(\r
+    int32_t                         fileline,\r
+    const char                      *funcname,\r
+    const char                      *filename,\r
+    const char                      *format, ...)\r
+{\r
+    UNUSED_VAR(fileline);\r
+    UNUSED_VAR(funcname);\r
+    UNUSED_VAR(filename);\r
+\r
+    char dest[256];\r
+    va_list argptr;\r
+    int char_num = 0;\r
+\r
+    if (!format)\r
+        return;\r
+\r
+    va_start(argptr, format);\r
+    char_num = vsprintf(dest, format, argptr);\r
+    va_end(argptr);\r
+\r
+    //uart_printf("%s", dest);\r
+\r
+    //dest[char_num] = '\n';\r
+    // pxi_nrf_uart_transmit((uint8_t*)dest, (uint16_t)(char_num + 1));\r
+}\r
+\r
+void ReadGSensor(float *x, float *y, float *z)\r
+{\r
+    \r
+}\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.h
new file mode 100644 (file)
index 0000000..cae483f
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-05-27 11:09:04\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-05-27 11:32:50\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_bsp.h\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+#ifndef __pah_800x_bsp_h__\r
+#define __pah_800x_bsp_h__\r
+\r
+// c\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdbool.h>\r
+#include <stdlib.h>\r
+\r
+// pah\r
+#include "pah_unit.h"\r
+#include "pah_800x_config.h"\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+#ifdef __cplusplus\r
+extern  "C" {\r
+#endif \r
+\r
+void pah_delay_ms(uint32_t ms);\r
+uint64_t pah_get_tick_count(void);\r
+pah_ret pah_comm_i2c_write(uint8_t addr, const uint8_t *data, size_t write_size);\r
+pah_ret pah_comm_i2c_read(uint8_t addr, uint8_t *data, size_t read_size);\r
+void pah_print(\r
+    int32_t                         fileline,\r
+    const char                      *funcname,\r
+    const char                      *filename,\r
+    const char                      *format, ...);\r
+\r
+void ReadGSensor(float *x, float *y, float *z);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c
new file mode 100644 (file)
index 0000000..6cb58fa
--- /dev/null
@@ -0,0 +1,1725 @@
+// pah\r
+#include "pah800x_main.h"\r
+//#include "pah_8009_reg_arr_default.h"\r
+#include "pxialg_spo2.h"\r
+#include "pxialg_hrv.h"\r
+#include "pxivar.h"\r
+#include "pah_8009_reg_arr_default_20220623.h"\r
+#include "pah800x_factory_test.h"\r
+#include "cmsis_os2.h"\r
+\r
+#ifdef SUPPORT_PPG_SERVICE\r
+#include "ppg_service.h"\r
+#include "ppg_hal.h"\r
+#endif\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+#include "cywee_service.h"\r
+#endif\r
+#include "custom_runtime.h"\r
+\r
+//============================================================================\r
+// Static Global Variable\r
+//============================================================================\r
+static main_state _main;\r
+static ppg_mems_data_t ppg_mems_data_buf[FIFO_SIZE] ;\r
+static int _read_index = 0 ;\r
+static int _write_index = 0 ;\r
+    \r
+// hr algotirhm\r
+static float hr = 0.0f;\r
+static float hr_grader =0.0f;\r
+static ppg_mems_data_t ppg_mems_data_alg;\r
+\r
+// spo2 algorithm\r
+void *pBuffer                 = NULL;\r
+void *hr_pBuffer              = NULL;    \r
+static float myHR             = 0.0f;\r
+static float mySpO2           = 0.0f;\r
+static float correlation      = 0.0f;\r
+static float trust_flag       = 0.0f;\r
+static float MEMS_RMS         = 0.0f;\r
+uint8_t      mySPO2_ReadyFlag = 0   ;\r
+static uint8_t no_value_reason = 0      ;\r
+static float   SignalPeriodicity=0.0f   ;\r
+\r
+static int     time_accu       = 0      ;\r
+static int              count         =0;\r
+static float            spo2_array[31]={0.0f};   \r
+\r
+static  uint32_t   data_buf_count_spo2_alg=0;\r
+\r
+static  SpO2_info_t    _spo2_detect_item;\r
+pah8series_data_t      pxialg_data_spo2;\r
+static  SpO2_mems_t    mems_data_raw[150];  \r
+#ifdef PPG_MEMS_Synchronize \r
+//int16_t mems_int_data_in[90] ={0};\r
+int16_t mems_int_data_out[90]={0};\r
+int time_temp=0;  \r
+static uint8_t ppg_data_num=0;\r
+uint8_t mems_data_polling_ready = 0 ;  \r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+// Stress Algorithm \r
+static hrv_state_s _hrv_state;\r
+void *stress_pBuffer              = NULL;    \r
+#define HRV_ENABLE_LHR                1\r
+#define HRV_SAMPLING_RATE                20\r
+#define HRV_COLLECTION_SECONDS          180   \r
+static     uint32_t  duration_total  = 0;\r
+uint8_t SDNN_ReadyFlag               = 0;\r
+uint8_t Get_Stress                   = 0;\r
+static  float Stress                 = 0.0f;\r
+static  uint8_t HRAvg                = 0;\r
+static  float SQ_Stress              = 0.0f;\r
+static  uint8_t AnomalyFlag          = 0;\r
+uint8_t Stress_ReadyFlag             = 0;\r
+uint8_t Weak_Flag                    = 0;\r
+\r
+static uint32_t factory_data = 0;\r
+static uint8_t work_mode = 0;\r
+\r
+\r
+static osTimerId_t g_pah8009_timer = NULL;\r
+\r
+static uint8_t time_cnt = 0;\r
+\r
+static uint8_t history_wear_status = 2;\r
+\r
+static uint8_t cywee_wear_status = 0;\r
+\r
+//============================================================================\r
+// Private function\r
+//============================================================================\r
+static bool sensor_basic_verification(void);    \r
+static void process(uint64_t timestamp);\r
+static void ppg_sensor_enable(void);\r
+static void ppg_sensor_disable(void);\r
+static void touch_sensor_enable(void);\r
+static void touch_sensor_disable(void);\r
+\r
+static void report_touch_data(uint64_t timestamp, const int8_t *touch_flag);\r
+static void report_ppg_data(const ppg_mems_data_t *ppg_mems_data_alg);\r
+static void report_hr_data(const ppg_mems_data_t *ppg_mems_data_alg, int32_t ret, float hr, float hr_grader);\r
+static void report_spo2_data(const ppg_mems_data_t *ppg_mems_data_alg, int32_t ret, float myHR, float mySpO2,  float correlation, float trust_flag, float MEMS_RMS, int data_buf_count_spo2_alg, uint8_t no_value_reason,  float   SignalPeriodicity,  int     time_accu );\r
+static void report_stress_data(const ppg_mems_data_t *ppg_mems_data_alg, uint8_t Stress_ReadyFlag, uint32_t measuretime, float collect_time);\r
+\r
+static void error_handle(void);\r
+\r
+static void pah8009_wearstatus_update(void)\r
+{\r
+    if(history_wear_status != cywee_wear_status)\r
+    {\r
+        history_wear_status = cywee_wear_status;\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+        do_cywee_service_check_msg(CYWEE_SERVICE_CMD_WEAR_STATUS_CHANGE,&cywee_wear_status);\r
+#endif\r
+    }\r
+}\r
+\r
+static void pah8009_unwearstatus_update(void)\r
+{\r
+#ifdef SUPPORT_PPG_SERVICE\r
+    ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
+    uint8_t data = 0;\r
+    if(func != NULL && !uapi_dev_runtime_get_train_status())\r
+    {\r
+        //为了主界面脱腕灵敏;需要增加未佩戴\r
+        func(PPG_MSG_TYPE_HRS_UPDATE, &data, 1);\r
+        func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &data,1);\r
+        func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&data,1);\r
+        func(PPG_MSG_TYPE_WEARSTAT_UPDATE,&data,1);\r
+    }\r
+\r
+    if(uapi_dev_runtime_get_train_status())\r
+    {\r
+        cywee_wear_status = 0;\r
+        pah8009_wearstatus_update();\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+        do_cywee_service_check_msg(CYWEE_SERVICE_CMD_HRS_CHANGE,&data);\r
+#endif\r
+    }\r
+#endif\r
+}   \r
+\r
+static void bubblesort(float *input,int count) \r
+{\r
+    int i,j;\r
+    float sort_temp;\r
+    for(i=0;i<count - 1;i++)\r
+    {\r
+        for(j=0;j<count-i - 1;j++) \r
+        {\r
+            if(input[j+1]<input[j])\r
+            {\r
+                sort_temp=input[j+1];\r
+                input[j+1]=input[j];\r
+                input[j]=sort_temp;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void spo2_log_printf(char s, float f)\r
+{\r
+       LOG_PRINT("%s= "LOG_FLOAT_MARKER"   \n",s, LOG_FLOAT(f));\r
+\r
+}\r
+\r
+/*****************************\r
+FW FIFO Function\r
+*****************************/\r
+bool isFIFOEmpty(void)\r
+{\r
+    return (_write_index == _read_index) ;\r
+}\r
+\r
+bool pah_push(ppg_mems_data_t *data) //Push return data must be true. If return false, please increase FIFO size.  \r
+{\r
+    int tmp = _write_index ;\r
+    tmp++;\r
+    if(tmp >= FIFO_SIZE)\r
+        tmp = 0 ;\r
+    if(tmp == _read_index)\r
+        return false;\r
+    ppg_mems_data_buf[tmp] = *data ;\r
+    _write_index = tmp ;\r
+    return true;\r
+}\r
+\r
+bool pah_pop(ppg_mems_data_t *data)\r
+{\r
+    int tmp ;\r
+    if(isFIFOEmpty())\r
+        return false;\r
+    tmp = _read_index + 1;\r
+    if(tmp >= FIFO_SIZE)\r
+        tmp = 0 ;    \r
+    _read_index = tmp ;\r
+    *data = ppg_mems_data_buf[_read_index] ;\r
+    \r
+    return true;\r
+}\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void pah_sensor_init(reg_config_type type)\r
+{\r
+    memset(&_main, 0, sizeof(_main));\r
+\r
+    pah_800x_reg_setting  reg_setting;\r
+    memset(&reg_setting, 0, sizeof(reg_setting));\r
+    \r
+    if (!sensor_basic_verification())\r
+    {\r
+        // error_handle();\r
+        LOG_PRINT("sensor_basic_verification failed\n");\r
+        return;\r
+    }\r
+\r
+\r
+    // pah_800x\r
+    pah_800x_config     pah_800x_config;\r
+    pah_800x_get_default_config(&pah_800x_config);\r
+    LOG_PRINT("PPG_SETTING_VESION = %d \n" ,PPG_SETTING_VERSION);\r
+    \r
+#if (ENABLE_AE==0)\r
+    pah_800x_config.enable_ppg_convergence[0] = false;\r
+    pah_800x_config.enable_ppg_convergence[1] = false;\r
+    pah_800x_config.enable_ppg_convergence[2] = false;\r
+#endif\r
+\r
+#if (ENABLE_AE_RECONVERGENCE==0)\r
+    pah_800x_config.enable_ppg_reconvergence_if_out_of_bounds[0] = false;\r
+    pah_800x_config.enable_ppg_reconvergence_if_out_of_bounds[1] = false;\r
+    pah_800x_config.enable_ppg_reconvergence_if_out_of_bounds[2] = false;\r
+#endif\r
+\r
+    if (type == pc_4mm_2g_ir_hrd)\r
+    {\r
+#if (PC_4MM_2G_IR_HRD==1)\r
+        PAH_REG_ARR_SETUP(reg_setting.startup_init, PAH8009_REG_DEVICE_INIT);\r
+        PAH_REG_ARR_SETUP(reg_setting.ppg_enable, PAH8009_REG_PC_4MM_2G_IR_PPG);\r
+        PAH_REG_ARR_SETUP(reg_setting.touch_enable, PAH8009_REG_PC_4MM_2G_IR_TOUCH);\r
+#endif\r
+    }\r
+    else if (type == diw_4mm_g_ir_hrd)\r
+    {\r
+#if (DIW_4MM_G_IR_HRD==1)\r
+        PAH_REG_ARR_SETUP(reg_setting.startup_init, PAH8009_REG_DEVICE_INIT);\r
+        PAH_REG_ARR_SETUP(reg_setting.ppg_enable, PAH8009_REG_DIW_4MM_G_IR_PPG);\r
+        PAH_REG_ARR_SETUP(reg_setting.touch_enable, PAH8009_REG_DIW_4MM_G_IR_TOUCH);\r
+#endif\r
+    }\r
+    else if (type == diw_4mm_ir_r_ir_spo2)\r
+    {\r
+#if (DIW_4MM_IR_R_IR_SPO2==1)\r
+        for(int ch=0;ch<PAH_800x_MAX_CH_NUM;ch++)\r
+        {\r
+            pah_800x_config.ppg_convergence[ch].t_weight_normal_mode = 4;\r
+            pah_800x_config.ppg_convergence[ch].t_weight_fast_mode = 8;\r
+            pah_800x_config.ppg_convergence[ch].t_max = 150;\r
+        }\r
+        PAH_REG_ARR_SETUP(reg_setting.startup_init, PAH8009_REG_DEVICE_INIT);\r
+        PAH_REG_ARR_SETUP(reg_setting.ppg_enable, PAH8009_REG_DIW_4MM_IR_R_IR_PPG);\r
+        PAH_REG_ARR_SETUP(reg_setting.touch_enable, PAH8009_REG_DIW_4MM_IR_R_IR_TOUCH);\r
+#endif\r
+    }\r
+    else if (type == pc_22mm_2g_ir_hrd)\r
+    {\r
+#if (PC_22MM_2G_IR_HRD==1)\r
+        for(int ch=0;ch<PAH_800x_MAX_CH_NUM;ch++)\r
+        {\r
+            pah_800x_config.ppg_convergence[ch].t_max = 1280;\r
+            pah_800x_config.ppg_convergence[ch].raw_outer_high_bound = 14848;\r
+            pah_800x_config.ppg_convergence[ch].raw_inner_high_target = 13824;\r
+            pah_800x_config.ppg_convergence[ch].raw_inner_low_target = 10752;\r
+            pah_800x_config.ppg_convergence[ch].raw_outer_low_bound = 9728;\r
+\r
+        }\r
+        PAH_REG_ARR_SETUP(reg_setting.startup_init, PAH800x_REG_DEVICE_INIT);\r
+        PAH_REG_ARR_SETUP(reg_setting.ppg_enable, PAH800x_REG_PC_22MM_2G_IR_PPG);\r
+        PAH_REG_ARR_SETUP(reg_setting.touch_enable, PAH800x_REG_PC_22MM_2G_IR_TOUCH);\r
+#endif\r
+    }\r
+    else if (type == di_18mm_g_g_hrd)\r
+    {\r
+#if (DI_18MM_G_G_HRD==1)\r
+        for(int ch=0;ch<PAH_800x_MAX_CH_NUM;ch++)\r
+        {\r
+            pah_800x_config.ppg_convergence[ch].t_weight_normal_mode = 15;\r
+            pah_800x_config.ppg_convergence[ch].t_weight_fast_mode = 25;\r
+            pah_800x_config.ppg_convergence[ch].t_max = 2048;\r
+        }\r
+        PAH_REG_ARR_SETUP(reg_setting.startup_init, PAH8001_REG_DEVICE_INIT);\r
+        PAH_REG_ARR_SETUP(reg_setting.ppg_enable, PAH8001_REG_DI_18MM_G_G_PPG);\r
+        PAH_REG_ARR_SETUP(reg_setting.touch_enable, PAH8001_REG_DI_18MM_G_G_TOUCH);\r
+#endif\r
+    }\r
+\r
+    _main.pah_800x.is_powered= false ;\r
+    pah_800x_init(&_main.pah_800x,  &pah_800x_config);\r
+    pah_800x_device_init(&_main.pah_800x, &reg_setting);\r
+\r
+}\r
+\r
+void touch_only_sensor_start(void)\r
+{\r
+    pah_800x_power_toggle(&_main.pah_800x, true);\r
+    _main.is_Auto_mode = 0;\r
+    touch_sensor_enable();\r
+    _main.debug_print_header = true;\r
+\r
+}\r
+\r
+void ppg_only_sensor_start(void)\r
+{\r
+    pah_800x_power_toggle(&_main.pah_800x, true);\r
+\r
+    touch_sensor_enable();\r
+    ppg_sensor_enable();\r
+    _main.alg_is_enabled = MSG_ALG_ENABLE;\r
+    \r
+   \r
+    //_main.ppg_only_is_enabled = 1 ;\r
+    _main.is_Auto_mode = 0;\r
+    _main.debug_print_header = true;\r
+    \r
+}\r
+\r
+void auto_mode_sensor_start(void)\r
+{\r
+    pah_800x_power_toggle(&_main.pah_800x, true);\r
+    \r
+    touch_sensor_enable();\r
+    _main.is_Auto_mode = 1;\r
+    _main.debug_print_header = true;\r
+    \r
+}\r
+\r
+void pah_sensor_stop(void)\r
+{\r
+    if (_main.ppg_is_enabled)\r
+    {\r
+        ppg_sensor_disable();\r
+    }\r
+    if (_main.touch_is_enabled)\r
+    {\r
+        touch_sensor_disable();\r
+    }\r
+    pah_800x_deinit(&_main.pah_800x);      \r
+      \r
+}\r
+\r
+void ppg_interrupt_handle(void)\r
+{\r
+    _main.has_interrupt = true;\r
+    _main.interrupt_timestamp = pah_get_tick_count();\r
+}\r
+\r
+void ppg_sensor_task_interrupt(void)\r
+{\r
+    if (_main.has_interrupt)\r
+    {\r
+        //LOG_PRINT("ppg_sensor_task_interrupt111111\n");\r
+        _main.has_interrupt = false;\r
+        _main.interrupt_timestamp = pah_get_tick_count();\r
+        process(_main.interrupt_timestamp);\r
+    }\r
+\r
+} \r
+\r
+void ppg_sensor_task_polling(void)\r
+{\r
+    _main.interrupt_timestamp = pah_get_tick_count();\r
+    process(_main.interrupt_timestamp);\r
+} \r
+\r
+uint8_t Check_alg_enable(void)\r
+{\r
+    return _main.alg_is_enabled;\r
+}\r
+\r
+void Clear_alg_enable(void)\r
+{\r
+    _main.alg_is_enabled = MSG_ALG_NOCHANGE;\r
+}\r
+\r
+\r
+// HR\r
+void hr_algorithm_enable(void)\r
+{\r
+    if (_main.hr_is_enabled)\r
+        return;\r
+\r
+    // static  Hr-V301009\r
+        \r
+    PxiAlg_Close();\r
+    int version = PxiAlg_Version();\r
+    DEBUG_PRINT("HR_Version = %d \r\n", version);\r
+   \r
+\r
+    uint32_t Query_Mem_Size = PxiAlg_Query_Mem_Size();\r
+    DEBUG_PRINT("HR_Mem_Size = %d \r\n", Query_Mem_Size);\r
+    \r
+    hr_pBuffer = malloc(Query_Mem_Size);\r
+           \r
+   \r
+    if(!PxiAlg_Open_Mem(hr_pBuffer))\r
+        DEBUG_PRINT("PxiAlg_Open_Mem fail \n");\r
+                \r
+            \r
+    PxiAlg_SetQualityThreshold(0.35f); \r
+    PxiAlg_SetHRSmoothWeight(0.9f); \r
+    PxiAlg_SetProcWindow(5.0f, 5.0f); \r
+    PxiAlg_SetTimeoutLength(30.0f);\r
+    PxiAlg_SetMemsScale(3);              //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetSkipSampleNum(10); \r
+    PxiAlg_SetMemsScaleBase(3, 0);    //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetForceOutputLink(10, 150, 40, 1, 0.9f); \r
+    PxiAlg_SetNormalOutput(200, 40, 0); \r
+    PxiAlg_SetForceRipple(3, 1); \r
+    //PxiAlg_SetForceOutput(30, 120, 45);\r
+    //PxiAlg_SetForceOutputTime(10);\r
+    PxiAlg_SetPackage(0, 1);\r
+\r
+    _main.hr_is_enabled = true;\r
+}\r
+\r
+void hr_algorithm_disable(void)\r
+{\r
+    if (!_main.hr_is_enabled)\r
+        return;\r
+\r
+    PxiAlg_Close();\r
+    free(hr_pBuffer);\r
+    hr = 0.0f;\r
+    hr_grader =0.0f;\r
+    _main.hr_is_enabled = false;\r
+}\r
+\r
+void hr_alg_task(void)\r
+{\r
+    if(Check_alg_enable())\r
+    {\r
+        if(Check_alg_enable()==MSG_ALG_ENABLE)\r
+        {\r
+            hr_algorithm_enable();\r
+        }else if(Check_alg_enable()==MSG_ALG_DISABLE)\r
+        {\r
+            hr_algorithm_disable();\r
+        }\r
+        Clear_alg_enable();\r
+    }\r
+\r
+    if(!isFIFOEmpty())\r
+    {\r
+        if(pah_pop(&ppg_mems_data_alg))    //Get data from FIFO\r
+        {\r
+            if(_main.hr_is_enabled)\r
+            {\r
+                // 13Bytes format to hr lib;\r
+                sRaw_Data_13Bytes hr_data;\r
+\r
+                memset(&hr_data, 0, sizeof(hr_data));\r
+                hr_data.loss = (uint8_t)ppg_mems_data_alg.ppg_data.overflow_num + 1;\r
+                hr_data.rawData = ppg_mems_data_alg.ppg_data.data[1];\r
+                hr_data.non_zero1 = 1;\r
+                hr_data.non_zero2 = 2;\r
+                hr_data.non_zero3 = 3;\r
+                hr_data.frame_count = ppg_mems_data_alg.ppg_frame_count;\r
+                hr_data.time = ppg_mems_data_alg.duration;\r
+                hr_data.rsv = 0;\r
+                hr_data.touch = (ppg_mems_data_alg.touch_flag > 0 ? 0x80 : 0x00);\r
+                hr_data.rsv2 = 0;\r
+  \r
+  \r
+                int32_t ret = PxiAlg_Process_Expo((uint8_t*)&hr_data, ppg_mems_data_alg.MEMS_Data, ppg_mems_data_alg.ppg_data.exposure_time[1]);\r
+  \r
+\r
+                if(PxiAlg_GetHrUpdateFlag())\r
+                {\r
+                    PxiAlg_HrGet(&hr);\r
+                    PxiAlg_GetSigGrade(&hr_grader);\r
+                }\r
+                if(ppg_mems_data_alg.touch_flag==0)\r
+                {\r
+                    hr = 0 ;\r
+                    hr_grader = 0;\r
+                }\r
+\r
+                // if(hr > 0)\r
+                    // printf("hr:%f\n",hr);\r
+#ifdef SUPPORT_PPG_SERVICE\r
+                time_cnt++;\r
+\r
+                ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
+\r
+                if(func != NULL && time_cnt >= 25)\r
+                {\r
+                    uint8_t data = (uint8_t)hr;\r
+                    func(PPG_MSG_TYPE_HRS_UPDATE, &data, 1);\r
+                    // data = cywee_wear_status;\r
+                    // func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &data, 1);\r
+                    time_cnt = 0;\r
+                }\r
+#endif\r
+                report_hr_data(&ppg_mems_data_alg, ret, hr, hr_grader);\r
+\r
+    \r
+            }\r
+            else\r
+            {\r
+                report_ppg_data(&ppg_mems_data_alg);\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+// HRD- ALG-  Task2\r
+void hr_alg_task2(uint8_t ppg_num)\r
+{\r
+#ifdef PPG_MEMS_Synchronize\r
+    if(Check_alg_enable())\r
+    {\r
+        if(Check_alg_enable()==MSG_ALG_ENABLE)\r
+        {\r
+            hr_algorithm_enable();\r
+        }else if(Check_alg_enable()==MSG_ALG_DISABLE)\r
+        {\r
+            hr_algorithm_disable();\r
+        }\r
+        Clear_alg_enable();\r
+    }\r
+  \r
+    if(!isFIFOEmpty())\r
+    {\r
+        for (int i=0; i<ppg_num; i++)\r
+        {\r
+              \r
+            if(pah_pop(&ppg_mems_data_alg))  //Get data from FIFO\r
+            {\r
+                if(_main.hr_is_enabled)\r
+                {\r
+                    ppg_mems_data_alg.MEMS_Data[0]=mems_int_data_out[3*i];\r
+                    ppg_mems_data_alg.MEMS_Data[1]=mems_int_data_out[3*i+1];\r
+                    ppg_mems_data_alg.MEMS_Data[2]=mems_int_data_out[3*i+2];\r
+            \r
+                    // 13Bytes format to hr lib;\r
+                    sRaw_Data_13Bytes hr_data;\r
+      \r
+                    memset(&hr_data, 0, sizeof(hr_data));\r
+                    hr_data.loss = (uint8_t)ppg_mems_data_alg.ppg_data.overflow_num + 1;\r
+                    hr_data.rawData = ppg_mems_data_alg.ppg_data.data[1];\r
+                    hr_data.non_zero1 = 1;\r
+                    hr_data.non_zero2 = 2;\r
+                    hr_data.non_zero3 = 3;\r
+                    hr_data.frame_count = ppg_mems_data_alg.ppg_frame_count;\r
+                    hr_data.time = ppg_mems_data_alg.duration;\r
+                    hr_data.rsv = 0;\r
+                    hr_data.touch = (ppg_mems_data_alg.touch_flag > 0 ? 0x80 : 0x00);\r
+                    hr_data.rsv2 = 0;\r
+      \r
+                    int32_t ret = PxiAlg_Process_Expo((uint8_t*)&hr_data, ppg_mems_data_alg.MEMS_Data, ppg_mems_data_alg.ppg_data.exposure_time[1]);\r
+  \r
+\r
+                    if(PxiAlg_GetHrUpdateFlag())\r
+                    {\r
+                        PxiAlg_HrGet(&hr);\r
+                        PxiAlg_GetSigGrade(&hr_grader);\r
+                    }\r
+               \r
+                    report_hr_data(&ppg_mems_data_alg, ret, hr, hr_grader);\r
+      \r
+                }\r
+                else\r
+                {\r
+                    report_ppg_data(&ppg_mems_data_alg);\r
+                }\r
+            }\r
+        }\r
+    }\r
+#endif\r
+}\r
+\r
+\r
+\r
+// SPO2\r
+void spo2_algorithm_enable(void)\r
+{\r
+    if (_main.spo2_is_enabled)\r
+    {\r
+        return;\r
+    }\r
+\r
+\r
+    int version = SpO2_Version();\r
+    DEBUG_PRINT("PxiAlg_Version() = %d\n", version);\r
+        \r
+    uint32_t buffer_size = SpO2_OpenSize();\r
+    DEBUG_PRINT("SpO2_Open buffer_size = %d \n", buffer_size);\r
+\r
+    pBuffer = malloc(buffer_size);\r
+        \r
+    if (SpO2_Open(pBuffer) != SPO2_MSG_SUCCESS)\r
+    {\r
+        DEBUG_PRINT("SpO2_Open() failed. \n");\r
+        free(pBuffer);\r
+        return;\r
+    }\r
+    int8_t alg_ch[2]    = {0, 1};      \r
+\r
+    SpO2_SetChMapping(alg_ch, 2);\r
+    SpO2_SetInputRatioHighBound(94.0f);\r
+    SpO2_SetInputRatioLowBound(87.0f);\r
+    SpO2_SetInputModelScale(0.50f);\r
+\r
+    SpO2_SetInputCoefHigh0(-36877.85546875f);\r
+    SpO2_SetInputCoefHigh1(1135.91394042969f);\r
+    SpO2_SetInputCoefHigh2(-11.6429319381714f);\r
+    SpO2_SetInputCoefHigh3(0.0398150011897087f);\r
+\r
+    SpO2_SetInputCoefMid0(-1430.70520019531f);\r
+    SpO2_SetInputCoefMid1(50.1599006652832f);\r
+    SpO2_SetInputCoefMid2(-0.567422986030579f);\r
+    SpO2_SetInputCoefMid3(0.00219199992716312f);\r
+\r
+    SpO2_SetInputCoefLow0(-8.19796657562256f);\r
+    SpO2_SetInputCoefLow1(1.74200701713562f);\r
+    SpO2_SetInputCoefLow2(-0.0173850003629923f);\r
+    SpO2_SetInputCoefLow3(0.000105999999505002f);\r
+\r
+    SpO2_SetIIRFilterRatio(0.5f);\r
+    SpO2_SetInputCorrelationTh(0.850000078678131f);\r
+    SpO2_SetInputRatioLow(0.05f);        \r
+\r
+    SpO2_SetInputFlagCheckHr(1);\r
+    SpO2_SetMotionDetectionLevel(2.0f);\r
+    SpO2_Set_Update_Sec(1);\r
+\r
+    SpO2_Set_Init_Low_SpO2_Constrain(0.0);  \r
+    SpO2_SetOutputHighBound(100.0f);\r
+    SpO2_SetOutputLowBound(60.0f);\r
+    SpO2_Set_Keep_Init_SpO2_Bound(95.0f);    \r
+    SpO2_Set_Keep_Init_SpO2_Count_Th(18.0f);\r
+    SpO2_Set_SpO2_Bias_Value(0.5f);           \r
+    SpO2_Set_SpO2_Outlier_Smooth_Coef(5.5f);  \r
+    SpO2_Set_SpO2_Decrease_Coef(0.5f);        \r
+    SpO2_SetSkipDataLen(25);\r
+\r
+    SpO2_Set_Flag_Hold_Breathe_Mode(0);\r
+    SpO2_Set_Input_Correlation_Th2(0.85000f);\r
+    SpO2_Set_Correlation_Th2_Count(30.0f);\r
+    SpO2_Set_Init_Low_SpO2_Th(94.5f);\r
+    SpO2_Set_Motion_Rms_Th(3000.0f);\r
+    SpO2_Set_Motion_Rms_Th2(1500.0f);\r
+    SpO2_Set_Motion_MEMS_Th(0.0f); \r
+    SpO2_Set_T1(0.85f);\r
+    SpO2_Set_Spo2_Force_Output_Second(15.0f);\r
+\r
+    Spo2_Set_Force_Output_Value(97.50f);  // Good Signal Force SpO2\r
+    Spo2_Set_Force_Output_Value2(95.00f); // Bad  Signal Force SpO2\r
+\r
+    SpO2_Set_Init_Low_SpO2_Check_Sec(20);\r
+    Spo2_Set_SpO2_First_Smooth_Th(95.0f);\r
+    Spo2_Set_SpO2_First_Smooth_Sec(15);\r
+    Spo2_Set_SpO2_Correlation_Smooth_Th(0.85f);\r
+    SpO2_Set_Signal_Periodicity_Th(0.50f);\r
+       \r
+    // static  Hr-V301009\r
+    PxiAlg_Close();\r
+    version = PxiAlg_Version();\r
+    DEBUG_PRINT("HR_Version = %d \r\n", version);\r
+        \r
+    \r
+    uint32_t Query_Mem_Size = PxiAlg_Query_Mem_Size();\r
+    DEBUG_PRINT("HR_Mem_Size = %d \r\n", Query_Mem_Size);\r
+    \r
+    hr_pBuffer = malloc(Query_Mem_Size);\r
+        \r
+    \r
+    if(!PxiAlg_Open_Mem(hr_pBuffer))\r
+          DEBUG_PRINT("PxiAlg_Open_Mem fail \n");\r
+             \r
+            \r
+    PxiAlg_SetQualityThreshold(0.35f); \r
+    PxiAlg_SetHRSmoothWeight(0.9f); \r
+    PxiAlg_SetProcWindow(5.0f, 5.0f); \r
+    PxiAlg_SetTimeoutLength(30.0f);\r
+    PxiAlg_SetMemsScale(1);       //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetSkipSampleNum(10); \r
+    PxiAlg_SetMemsScaleBase(1, 0); //MEMS 2/4/8/16G : 0/1/2/3\r
+    PxiAlg_SetForceOutputLink(15, 90, 60, 1, 0.9f); \r
+    PxiAlg_SetNormalOutput(200, 40, 1); \r
+    PxiAlg_SetForceRipple(3, 1); \r
+    PxiAlg_SetPackage(0, 1);\r
+    \r
+    myHR                   = 0.0f;\r
+    mySpO2                 = 0.0f;\r
+    correlation            = 0.0f;\r
+    trust_flag             = 0.0f;\r
+    MEMS_RMS               = 0.0f;\r
+    mySPO2_ReadyFlag       = 0;\r
+    hr_grader              = 0.0f;\r
+    data_buf_count_spo2_alg=0;\r
+    no_value_reason = 0      ;\r
+    SignalPeriodicity=0.0f   ;\r
+    time_accu       = 0      ;\r
+    count           = 0 ;\r
+    memset(spo2_array, 0, sizeof(*spo2_array));\r
+    _main.spo2_is_enabled = true;\r
+}\r
+\r
+void spo2_algorithm_disable(void)\r
+{\r
+    if (!_main.spo2_is_enabled)\r
+        return;\r
+    PxiAlg_Close();\r
+    SpO2_Close();\r
+    free(pBuffer);\r
+    free(hr_pBuffer);\r
+    myHR                   = 0.0f;\r
+    mySpO2                 = 0.0f;\r
+    correlation            = 0.0f;\r
+    trust_flag             = 0.0f;\r
+    MEMS_RMS               = 0.0f;\r
+    mySPO2_ReadyFlag       = 0;\r
+    hr_grader              = 0.0f;\r
+    data_buf_count_spo2_alg=0;\r
+    \r
+    no_value_reason = 0      ;\r
+    SignalPeriodicity=0.0f   ;\r
+    time_accu       = 0      ;\r
+    \r
+    \r
+    _main.spo2_is_enabled = false;\r
+}\r
+\r
+void spo2_alg_task(void)\r
+{\r
+    if(Check_alg_enable())\r
+    {\r
+        if(Check_alg_enable()==MSG_ALG_ENABLE)\r
+        {\r
+            spo2_algorithm_enable();\r
+        }else if(Check_alg_enable()==MSG_ALG_DISABLE)\r
+        {\r
+            spo2_algorithm_disable();\r
+        }\r
+        Clear_alg_enable();\r
+    }\r
+\r
+    if(!isFIFOEmpty())\r
+    {\r
+        if(pah_pop(&ppg_mems_data_alg))    //Get data from FIFO\r
+        {\r
+            if(_main.spo2_is_enabled)\r
+            {\r
+                // 13Bytes format to hr lib;\r
+                    \r
+                int32_t  RAW_DATA[2]  ;\r
+                sRaw_Data_13Bytes hr_data;\r
+                 \r
+                memset(&hr_data, 0, sizeof(hr_data));\r
+                hr_data.loss = (uint8_t)ppg_mems_data_alg.ppg_data.overflow_num + 1;\r
+                hr_data.rawData = ppg_mems_data_alg.ppg_data.data[0];\r
+                hr_data.non_zero1 = 1;\r
+                hr_data.non_zero2 = 2;\r
+                hr_data.non_zero3 = 3;\r
+                hr_data.frame_count = ppg_mems_data_alg.ppg_frame_count;\r
+                hr_data.time = ppg_mems_data_alg.duration;\r
+                hr_data.rsv = 0;\r
+                hr_data.touch = (ppg_mems_data_alg.touch_flag > 0 ? 0x80 : 0x00);\r
+                hr_data.rsv2 = 0;\r
+           \r
+           \r
+                int32_t ret = PxiAlg_Process_Expo((uint8_t*)&hr_data, ppg_mems_data_alg.MEMS_Data, ppg_mems_data_alg.ppg_data.exposure_time[0]);\r
+               \r
+\r
+                \r
+\r
+                if(PxiAlg_GetHrUpdateFlag())\r
+                {\r
+                    PxiAlg_HrGet(&myHR);\r
+                    PxiAlg_GetSigGrade(&hr_grader);\r
+                }\r
+\r
+\r
+                int32_t spo2_raw_1=ppg_mems_data_alg.ppg_data.data[0];\r
+                int32_t spo2_raw_2=ppg_mems_data_alg.ppg_data.data[1];\r
+                \r
+                RAW_DATA[0]=spo2_raw_1;\r
+                RAW_DATA[1]=spo2_raw_2;\r
+\r
+                mems_data_raw[0].data[0]=ppg_mems_data_alg.MEMS_Data[0];\r
+                mems_data_raw[0].data[1]=ppg_mems_data_alg.MEMS_Data[1] ;\r
+                mems_data_raw[0].data[2]=ppg_mems_data_alg.MEMS_Data[2];            \r
+\r
+                // SPO2 fill data on pah8series structure\r
+                pxialg_data_spo2.touch_flag         =  ppg_mems_data_alg.touch_flag ;\r
+                pxialg_data_spo2.time               =  ppg_mems_data_alg.duration ;;\r
+                pxialg_data_spo2.ppg_data           =  (int32_t*)RAW_DATA;\r
+                pxialg_data_spo2.nf_ppg_channel     =  2;\r
+                pxialg_data_spo2.nf_ppg_per_channel =  1;\r
+                pxialg_data_spo2.frame_count        =  ppg_mems_data_alg.ppg_frame_count ;\r
+                pxialg_data_spo2.nf_mems            =  1;\r
+                pxialg_data_spo2.mems_data          = (int16_t*)mems_data_raw;\r
+\r
+\r
+\r
+                // DEBUG_PRINT("data_buf_count_spo2_alg = %d \r\n", data_buf_count_spo2_alg);\r
+\r
+\r
+                SpO2_SetHrValue(myHR);\r
+                SpO2_SetMems(mems_data_raw, 1);\r
+                //int  ret_value = SpO2_Process(ppg_mems_data_alg.touch_flag , 2, pxialg_data_spo2.ppg_data, 1);\r
+                int  ret_value = SpO2_Process(ppg_mems_data_alg.touch_flag , 2, pxialg_data_spo2.ppg_data, 1,pxialg_data_spo2.time );\r
+             \r
+                SpO2_GetSpO2(&mySpO2);\r
+                \r
+                // if(mySpO2 > 0)\r
+                    // printf("SpO2 : %f\n",mySpO2);\r
+#ifdef SUPPORT_PPG_SERVICE\r
+                time_cnt++;\r
+\r
+                ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
+\r
+                if(func != NULL && time_cnt >= 25)\r
+                {\r
+                    uint8_t data = (uint8_t)mySpO2;\r
+                    func(PPG_MSG_TYPE_SPO2_UPDATE, &data, 1);\r
+                    time_cnt = 0;\r
+                }\r
+#endif\r
+\r
+                SpO2_GetReadyFlag(&mySPO2_ReadyFlag);\r
+                SpO2_GetInfo(&_spo2_detect_item);\r
+                correlation =_spo2_detect_item.Noise;\r
+                trust_flag =_spo2_detect_item.Output[3];\r
+                no_value_reason=_spo2_detect_item.Output[4];\r
+                SpO2_GetPeriodicity(&SignalPeriodicity);\r
+                MEMS_RMS  =_spo2_detect_item.RMS;\r
+                \r
+\r
+                data_buf_count_spo2_alg++;\r
+                \r
+            #if defined(Optimize_SPO2_flow) \r
+                time_accu=time_accu+pxialg_data_spo2.time;\r
+            #endif\r
+                        \r
+                if( (ret_value == 0  ) && (data_buf_count_spo2_alg>=25) )\r
+                {   \r
+                       \r
+                #if defined(Optimize_SPO2_flow)\r
+                    //time_accu=time_accu+pxialg_data->time;\r
+                    DEBUG_PRINT("SPO2 Test Time = %d ,count =%d\n",time_accu,count);\r
+                    if(time_accu>=60000)\r
+                    {\r
+                        spo2_array[count]=mySpO2;\r
+                        count=count+1;\r
+                        \r
+                        LOG_PRINT("Over_30_sec_Stop_measurement\n");\r
+                        LOG_PRINT("This_meausrement_suggest_spo2_value is");\r
+                        \r
+                        bubblesort(spo2_array,count);\r
+                        \r
+                        if(count % 2 == 0)\r
+                        {\r
+                              //log_printf(" "LOG_FLOAT_MARKER" \n", LOG_FLOAT(spo2_array[count/2]));\r
+                              LOG_PRINT(" "LOG_FLOAT_MARKER" \n",LOG_FLOAT((spo2_array[(int)(count/2)] + spo2_array[(int)(count/2) - 1]) / 2.0f)); \r
+                        }\r
+                        else\r
+                        {\r
+                              LOG_PRINT(" "LOG_FLOAT_MARKER" \n", LOG_FLOAT(spo2_array[(int)(count/2)]*1.0f));\r
+                        }\r
+                        \r
+                        //log_pah8series_no_touch();\r
+                        spo2_algorithm_disable();\r
+                        pah_sensor_stop();\r
+                        count=0;\r
+                        //add sensor stop here              \r
+                    }\r
+                    else\r
+                    {\r
+                        if(mySpO2>0)\r
+                        {\r
+                           spo2_array[count]=mySpO2;\r
+                           count=count+1;                    \r
+                        }            \r
+                    }\r
+                #endif\r
+                    //report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, Opt_SpO2, drop_flag, ascend_flag,  mems_fla);\r
+                    report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, no_value_reason, SignalPeriodicity, time_accu);\r
+                    data_buf_count_spo2_alg = data_buf_count_spo2_alg -25;\r
+                }\r
+                else\r
+                {\r
+                    //report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg,  Opt_SpO2, drop_flag, ascend_flag,  mems_flag);\r
+                    report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, no_value_reason, SignalPeriodicity, time_accu);\r
+\r
+                    switch (ret_value)\r
+                    {\r
+                        case SPO2_MSG_ALG_NOT_OPEN:\r
+                            DEBUG_PRINT("Algorithm is not initialized. \n");\r
+                        break;\r
+                     \r
+                        case SPO2_MSG_ALG_REOPEN:\r
+                            DEBUG_PRINT("Algorithm is re initialized. \n");\r
+                        break;\r
+                     \r
+                        case SPO2_MSG_ALG_NOT_SUPPORT:\r
+                            DEBUG_PRINT("Algorithm is not support. \n");\r
+                        break;\r
+                    \r
+                        default:\r
+                            // DEBUG_PRINT("Algorithm unhandle error = %d \n", ret_value);\r
+                        break;\r
+                    }\r
+                    //return 1 ;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                report_ppg_data(&ppg_mems_data_alg);\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+// SPO2- ALG-  Task2\r
+void spo2_alg_task2(uint8_t ppg_num)\r
+{\r
+#ifdef PPG_MEMS_Synchronize\r
+    if(Check_alg_enable())\r
+    {\r
+        if(Check_alg_enable()==MSG_ALG_ENABLE)\r
+        {\r
+            spo2_algorithm_enable();\r
+        }else if(Check_alg_enable()==MSG_ALG_DISABLE)\r
+        {\r
+            spo2_algorithm_disable();\r
+        }\r
+        Clear_alg_enable();\r
+    }\r
+  \r
+    if(!isFIFOEmpty())\r
+    {\r
+        for (int k=0; k<ppg_num; k++)\r
+        {\r
+            if(pah_pop(&ppg_mems_data_alg))  //Get data from FIFO\r
+            {\r
+                if(_main.spo2_is_enabled)\r
+                {\r
+                    // 13Bytes format to hr lib;\r
+              \r
+\r
+                    ppg_mems_data_alg.MEMS_Data[0]=mems_int_data_out[3*k];\r
+                    ppg_mems_data_alg.MEMS_Data[1]=mems_int_data_out[3*k+1];\r
+                    ppg_mems_data_alg.MEMS_Data[2]=mems_int_data_out[3*k+2];\r
+          \r
+                    int32_t  RAW_DATA[2]={0}  ;\r
+                    sRaw_Data_13Bytes hr_data;\r
+                 \r
+                    memset(&hr_data, 0, sizeof(hr_data));\r
+                    hr_data.loss = (uint8_t)ppg_mems_data_alg.ppg_data.overflow_num + 1;\r
+                    hr_data.rawData = ppg_mems_data_alg.ppg_data.data[0];\r
+                    hr_data.non_zero1 = 1;\r
+                    hr_data.non_zero2 = 2;\r
+                    hr_data.non_zero3 = 3;\r
+                    hr_data.frame_count = ppg_mems_data_alg.ppg_frame_count;\r
+                    hr_data.time = ppg_mems_data_alg.duration;\r
+                    hr_data.rsv = 0;\r
+                    hr_data.touch = (ppg_mems_data_alg.touch_flag > 0 ? 0x80 : 0x00);\r
+                    hr_data.rsv2 = 0;\r
+          \r
+               \r
+                    int32_t ret = PxiAlg_Process_Expo((uint8_t*)&hr_data, ppg_mems_data_alg.MEMS_Data, ppg_mems_data_alg.ppg_data.exposure_time[0]);\r
+               \r
+\r
+                \r
+\r
+                if(PxiAlg_GetHrUpdateFlag())\r
+                {\r
+                    PxiAlg_HrGet(&myHR);\r
+                    PxiAlg_GetSigGrade(&hr_grader);\r
+                }\r
+          \r
+\r
+                    int32_t spo2_raw_1=ppg_mems_data_alg.ppg_data.data[0];\r
+                    int32_t spo2_raw_2=ppg_mems_data_alg.ppg_data.data[1];\r
+                \r
+                    RAW_DATA[0]=spo2_raw_1;\r
+                    RAW_DATA[1]=spo2_raw_2;\r
+          \r
+                    mems_data_raw[0].data[0]=ppg_mems_data_alg.MEMS_Data[0];\r
+                    mems_data_raw[0].data[1]=ppg_mems_data_alg.MEMS_Data[1] ;\r
+                    mems_data_raw[0].data[2]=ppg_mems_data_alg.MEMS_Data[2];            \r
+          \r
+                    // SPO2 fill data on pah8series structure\r
+                    pxialg_data_spo2.touch_flag         =  ppg_mems_data_alg.touch_flag ;\r
+                    pxialg_data_spo2.time               =  ppg_mems_data_alg.duration ;;\r
+                    pxialg_data_spo2.ppg_data           =  (int32_t*)RAW_DATA;\r
+                    pxialg_data_spo2.nf_ppg_channel     =  2;\r
+                    pxialg_data_spo2.nf_ppg_per_channel =  1;\r
+                    pxialg_data_spo2.frame_count        =  ppg_mems_data_alg.ppg_frame_count ;\r
+                    pxialg_data_spo2.nf_mems            =  1;\r
+                    pxialg_data_spo2.mems_data          = (int16_t*)mems_data_raw;\r
+           \r
+\r
+\r
+                    //DEBUG_PRINT("data_buf_count_spo2_alg = %d \r\n", data_buf_count_spo2_alg);\r
+                    \r
+\r
+                    SpO2_SetHrValue(myHR);\r
+                    SpO2_SetMems(mems_data_raw, 1);\r
+                    //int  ret_value = SpO2_Process(ppg_mems_data_alg.touch_flag , 2, pxialg_data_spo2.ppg_data, 1);\r
+                    int  ret_value = SpO2_Process(ppg_mems_data_alg.touch_flag , 2, pxialg_data_spo2.ppg_data, 1,pxialg_data_spo2.time );\r
+                   \r
+                    SpO2_GetSpO2(&mySpO2);\r
+                    SpO2_GetReadyFlag(&mySPO2_ReadyFlag);\r
+                    SpO2_GetInfo(&_spo2_detect_item);\r
+                    correlation =_spo2_detect_item.Noise;\r
+                    trust_flag  =_spo2_detect_item.Output[3];\r
+                    no_value_reason=_spo2_detect_item.Output[4];\r
+                    SpO2_GetPeriodicity(&SignalPeriodicity);\r
+                    MEMS_RMS    =_spo2_detect_item.RMS;\r
+          \r
+\r
+                    data_buf_count_spo2_alg++;\r
+                \r
+                #if defined(Optimize_SPO2_flow) \r
+                    time_accu=time_accu+pxialg_data_spo2.time;\r
+                #endif\r
+                    \r
+                    if( (ret_value == 0  ) && (data_buf_count_spo2_alg>=25) )\r
+                    {   \r
+                \r
+                        #if defined(Optimize_SPO2_flow)\r
+                        //time_accu=time_accu+pxialg_data->time;\r
+                        DEBUG_PRINT("SPO2 Test Time = %d ,count =%d\n",time_accu,count);\r
+                        if(time_accu>=31000)\r
+                        {\r
+                            spo2_array[count]=mySpO2;\r
+                            count=count+1;\r
+                                    \r
+                            LOG_PRINT("Over_30_sec_Stop_measurement\n");\r
+                            LOG_PRINT("This_meausrement_suggest_spo2_value is");\r
+                        \r
+                            bubblesort(spo2_array,count);\r
+                            \r
+                            if(count % 2 == 0)\r
+                            {\r
+                                //log_printf(" "LOG_FLOAT_MARKER" \n", LOG_FLOAT(spo2_array[count/2]));\r
+                                LOG_PRINT(" "LOG_FLOAT_MARKER" \n",LOG_FLOAT((spo2_array[(int)(count/2)] + spo2_array[(int)(count/2) - 1]) / 2.0f)); \r
+                            }\r
+                            else\r
+                            {\r
+                                LOG_PRINT(" "LOG_FLOAT_MARKER" \n", LOG_FLOAT(spo2_array[(int)(count/2)]*1.0f));\r
+                            }\r
+                            \r
+                            //log_pah8series_no_touch();\r
+                            spo2_algorithm_disable();\r
+                            pah_sensor_stop();\r
+                            count=0;\r
+                            //add sensor stop here              \r
+                        }\r
+                        else\r
+                        {        \r
+                            if(mySpO2>0)\r
+                            {\r
+                               spo2_array[count]=mySpO2;\r
+                               count=count+1;                    \r
+                            }\r
+                        }\r
+                        #endif\r
+                        //report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, Opt_SpO2, drop_flag, ascend_flag,  mems_fla);\r
+                        report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, no_value_reason, SignalPeriodicity, time_accu);\r
+                        data_buf_count_spo2_alg = data_buf_count_spo2_alg -25;\r
+                    }\r
+                    else\r
+                    {\r
+                        //report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg,  Opt_SpO2, drop_flag, ascend_flag,  mems_flag);\r
+                        report_spo2_data(&ppg_mems_data_alg, ret, mySpO2, myHR, correlation, trust_flag, MEMS_RMS,data_buf_count_spo2_alg, no_value_reason, SignalPeriodicity, time_accu);\r
+                  \r
+                        switch (ret_value)\r
+                        {\r
+                            case SPO2_MSG_ALG_NOT_OPEN:\r
+                                  DEBUG_PRINT("Algorithm is not initialized. \n");\r
+                            break;\r
+                           \r
+                            case SPO2_MSG_ALG_REOPEN:\r
+                                  DEBUG_PRINT("Algorithm is re initialized. \n");\r
+                            break;\r
+                           \r
+                            case SPO2_MSG_ALG_NOT_SUPPORT:\r
+                                  DEBUG_PRINT("Algorithm is not support. \n");\r
+                            break;\r
+                          \r
+                            default:\r
+                                DEBUG_PRINT("Algorithm unhandle error = %d \n", ret_value);\r
+                            break;\r
+                        }\r
+                        //return 1 ;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    report_ppg_data(&ppg_mems_data_alg);\r
+                }\r
+            }\r
+        }\r
+    }\r
+#endif\r
+}\r
+\r
+\r
+\r
+// Stress\r
+void stress_algorithm_enable(void)\r
+{\r
+    int buffer_size = 0;\r
+    if (_main.stress_is_enable)\r
+    {\r
+    return;\r
+    }\r
+\r
+    LOG_PRINT("HRVGetVersion() = %d \n", HRVGetVersion());\r
+    buffer_size = HRVGetMemorySize(HRV_ENABLE_LHR, HRV_COLLECTION_SECONDS, HRV_SAMPLING_RATE);\r
+    LOG_PRINT("HRVGetMemorySize(), open_size = %d \n", buffer_size);\r
+\r
+    if (!buffer_size)\r
+    {\r
+        LOG_PRINT("HRVGetMemorySize(), failed to get memory size \n");\r
+        return ;\r
+    }\r
+\r
+    stress_pBuffer = (uint8_t*)malloc(buffer_size);\r
+    if (!stress_pBuffer)\r
+    {\r
+        LOG_PRINT("Out of memory \n");\r
+        return ;\r
+    }\r
+\r
+    if (!HRVOpen(stress_pBuffer))\r
+    {\r
+        LOG_PRINT("HRVOpen() failed. \n");\r
+        return ;\r
+    }\r
+    duration_total=0;\r
+    _hrv_state.collect_duration = 0;\r
+ \r
+    _main.stress_is_enable = true;\r
+}\r
+\r
+void stress_algorithm_disable(void)\r
+{\r
+    if (!_main.stress_is_enable)\r
+        return;\r
+    HRVClose();\r
+    free(stress_pBuffer);\r
+    \r
+    duration_total            = 0;\r
+    SDNN_ReadyFlag            = 0;\r
+    Get_Stress                = 0;\r
+    Stress                    = 0.0f;\r
+    HRAvg                     = 0;\r
+    SQ_Stress                 = 0.0f;\r
+    AnomalyFlag               = 0;\r
+    Stress_ReadyFlag          = 0;\r
+    Weak_Flag                 = 0;                \r
+    _main.stress_is_enable    = false;\r
+}\r
+\r
+void stress_alg_task(int grade)\r
+{\r
+    if(Check_alg_enable())\r
+    {\r
+        if(Check_alg_enable()==MSG_ALG_ENABLE)\r
+        {\r
+            stress_algorithm_enable();\r
+        }else if(Check_alg_enable()==MSG_ALG_DISABLE)\r
+        {\r
+            stress_algorithm_disable();\r
+        }\r
+        Clear_alg_enable();\r
+    }\r
+\r
+    if(!isFIFOEmpty())\r
+    {\r
+        if(pah_pop(&ppg_mems_data_alg))    //Get data from FIFO\r
+        {\r
+            if(_main.stress_is_enable)\r
+            {\r
+                uint32_t raw_data = ppg_mems_data_alg.ppg_data.data[1];\r
+                uint8_t frame_count = ppg_mems_data_alg.ppg_frame_count;\r
+                uint8_t timeInterval = ppg_mems_data_alg.duration;\r
+                uint8_t touch_flag = ppg_mems_data_alg.touch_flag;\r
+\r
+                // If using Interrupt mode call this API\r
+                HRVSetDiffTime(timeInterval,1);\r
+  \r
+                HRVProcess(touch_flag, raw_data);\r
+\r
+                duration_total+=timeInterval;\r
+              \r
+              \r
+                if(Stress_ReadyFlag==0)\r
+                {\r
+                    Stress_ReadyFlag=HRVGetReadyFlag();\r
+                }\r
+            \r
+                if((duration_total>25000)&& Stress_ReadyFlag==0)\r
+                {\r
+                    LOG_PRINT("PPG Raw data is too Weak\r\n");\r
+                    LOG_PRINT("TEST Stop\r\n");\r
+                    stress_algorithm_disable();\r
+                    Weak_Flag=1;\r
+                    return  ;\r
+                }    \r
+                \r
+                if(Stress_ReadyFlag  == 1 || HRVGetReadyFlag())\r
+                {\r
+                    Stress_ReadyFlag=1;\r
+                    _hrv_state.collect_duration += timeInterval;\r
+  \r
+                    if(_hrv_state.collect_duration > (HRV_COLLECTION_SECONDS * 1000))\r
+                    {\r
+                        //int grade=100;\r
+                        HRAvg = HRVGetHRAvg();  \r
+                        Stress= HRVGetStress(grade);                                        \r
+                        SQ_Stress=HRVGetRRIQuality();                                        \r
+                        AnomalyFlag= HRVGetAnomalyFlag();\r
+                        LOG_PRINT("HRAvg = %d  Stress = %f  HRV_Quality = %f  AnomalyFlag= %d \n", HRAvg ,Stress,SQ_Stress,AnomalyFlag);\r
+\r
+                        if(SQ_Stress>0.4f)\r
+                        {\r
+                            LOG_PRINT("HRV_Quality Good\n");\r
+                        }\r
+                        else\r
+                        {\r
+                            LOG_PRINT("HRV_Quality Weak\n");\r
+                        }\r
+                        \r
+                        \r
+                        if(Stress >=80 &&  Stress<=100)\r
+                        {\r
+                            LOG_PRINT("Stress_Level High\n");\r
+                        }\r
+                        else if(Stress >=60 &&  Stress<80)\r
+                        {\r
+                            LOG_PRINT("Stress_Level Medium\n");\r
+                        }\r
+                        else if(Stress >=30 &&  Stress<60)\r
+                        {\r
+                            LOG_PRINT("Stress_Level Normal\n");\r
+                        }\r
+                        else\r
+                        {\r
+                            LOG_PRINT("Stress_Level Relaxed\n");\r
+                        }                                    \r
+        \r
+                        stress_algorithm_disable();\r
+                        _hrv_state.has_got_sdnn = 1;\r
+                        Get_Stress=1;\r
+                        return ;\r
+                    }\r
+                }    \r
+                report_stress_data(&ppg_mems_data_alg,Stress_ReadyFlag, duration_total, _hrv_state.collect_duration );\r
+            }\r
+            else\r
+            {\r
+                report_ppg_data(&ppg_mems_data_alg);\r
+                LOG_PRINT("Stress_Level Normal\n");\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+//============================================================================\r
+// Private function\r
+//============================================================================\r
+static bool sensor_basic_verification(void)\r
+{\r
+    uint16_t product_id = 0;\r
+    pah_800x_get_product_id(&product_id);\r
+    if (product_id != PAH_800x_PRODUCT_ID)\r
+    {\r
+        pah_800x_power_toggle(&_main.pah_800x, true);\r
+        pah_800x_get_product_id( &product_id);\r
+    }\r
+\r
+    DEBUG_PRINT("product_id = 0x%04X\n", product_id);\r
+    if (product_id != PAH_800x_PRODUCT_ID)\r
+    {\r
+        DEBUG_PRINT("Failed to verify product_id\n");\r
+        return false;\r
+    }\r
+    \r
+    return true;\r
+}\r
+\r
+static void process(uint64_t timestamp)\r
+{\r
+    float mems_data[3] = { 0.0f, 0.0f, 0.0f };\r
+\r
+    // Task\r
+    pah_ret ret = pah_800x_task(&_main.pah_800x);\r
+    if (PAH_FAILED(ret))\r
+    {\r
+        DEBUG_PRINT("pah_800x_task() failed, ret = %d\n", ret);\r
+        return;\r
+    }\r
+\r
+    int8_t touch_flag = -1;\r
+    pah_800x_get_touch_flag(&_main.pah_800x, &touch_flag);\r
+\r
+    // PRINT("touch_flag : %d\n",touch_flag);\r
+\r
+#ifdef SUPPORT_PPG_SERVICE\r
+    // ppg_msg_callback_t func =  ppg_get_send_msg_callback_func();\r
+\r
+    // if(func != NULL)\r
+    // {\r
+    //     uint8_t data = (uint8_t)touch_flag;\r
+    //     cywee_wear_status = data;\r
+    //     func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &data, 1);\r
+    // }\r
+#endif\r
+\r
+    if (_main.ppg_is_enabled)\r
+    {\r
+        pah_800x_ppg_data ppg_data;\r
+        pah_800x_ppg_get_data(&_main.pah_800x, &ppg_data);\r
+\r
+        if (ppg_data.has_data)\r
+        {\r
+            // LOG_PRINT("ppg data %d %d %d %d %d %d %d %d\n",ppg_data.has_data,ppg_data.overflow_num,ppg_data.data[0],ppg_data.data[1],ppg_data.data[2],\r
+            // ppg_data.exposure_time[0],ppg_data.exposure_time[1],ppg_data.exposure_time[2]);\r
+            // LOG_PRINT("ppg data %d %d %d %d %d %d\n",ppg_data.frame_period[0],ppg_data.frame_period[1],ppg_data.frame_period[2]\r
+            // ,ppg_data.adc[0],ppg_data.adc[1],ppg_data.adc[2]);\r
+\r
+            // PRINT("ppg data : %d %d %d\n",ppg_data.data[0],ppg_data.data[1],ppg_data.data[2]);\r
+\r
+            factory_data = ppg_data.data[0];\r
+\r
+            uint64_t duration = timestamp - _main.ppg_prev_report_timestamp;\r
+\r
+            if (!_main.ppg_has_prev_report_timestamp)\r
+            {\r
+                _main.ppg_has_prev_report_timestamp = true;\r
+                duration = 50;\r
+            }\r
+            _main.ppg_prev_report_timestamp = timestamp;\r
+\r
+            if (duration > UINT8_MAX)\r
+            {\r
+                // DEBUG_PRINT("duration > UINT8_MAX !!!:%llu\n",duration);\r
+                PRINT("duration > UINT8_MAX !!!:%llu\n",duration);\r
+                return;\r
+            }\r
+            \r
+            ppg_mems_data_t ppg_mems_data;\r
+\r
+            /***********************G sensor explanation start***********************************/\r
+            //If no G sensor, please set ppg_mems_data.MEMS_Data[3] = {0};\r
+            //Please set G sensor default range = ±2G.\r
+            //If G sensor output data format is not 16bit, please change to 16bit format.\r
+            //For example: G sensor is 12bit\r
+            //ReadGSensor(&mems_data[0],&mems_data[1],&mems_data[2])\r
+            //MEMS_SensorX() absolute data must be largest when let hand down at static state.\r
+            //MEMS_SensorZ() absolute data must be largest when let hand horizontal on the table at static state.\r
+            /***********************G sensor explanation end***********************************/\r
+\r
+            ppg_mems_data.MEMS_Data[0] = mems_data[0];//ReadGSensorX();\r
+            ppg_mems_data.MEMS_Data[1] = mems_data[1];//ReadGSensorY();\r
+            ppg_mems_data.MEMS_Data[2] = mems_data[2];//ReadGSensorZ();\r
+            ppg_mems_data.duration = duration;\r
+            \r
+            ppg_mems_data.ppg_data = ppg_data ;\r
+            ppg_mems_data.touch_flag = touch_flag ;\r
+            ppg_mems_data.ppg_frame_count = _main.ppg_frame_count;    //SD-revise-20200320\r
+                                        \r
+            pah_push(&ppg_mems_data);\r
+\r
+#ifdef PPG_MEMS_Synchronize          \r
+            time_temp+=duration;\r
+            mems_data_polling_ready=0;\r
+            if(time_temp>=Time_Interval)\r
+            {\r
+              mems_data_polling_ready=1;\r
+              time_temp =0;\r
+            }\r
+            ppg_data_num++;\r
+#endif            \r
+            ++_main.ppg_frame_count;\r
+            \r
+            //report_ppg_data(&ppg_mems_data);\r
+\r
+        }\r
+    }\r
+    \r
+    if (_main.is_Auto_mode || _main.touch_is_enabled)//SD-reivse-20191205\r
+    {\r
+        if ( _main.touch_last_is_touched != touch_flag)\r
+        {\r
+            _main.touch_last_is_touched = touch_flag;   \r
+                \r
+            report_touch_data(timestamp, &touch_flag);\r
+                \r
+            bool is_touched = (touch_flag >= 1);\r
+\r
+            if (_main.is_Auto_mode && is_touched)//SD-revise-20191205\r
+            {             \r
+                //touch_sensor_disable(); \r
+                ppg_sensor_enable();\r
+                _main.alg_is_enabled = MSG_ALG_ENABLE;\r
+            }\r
+            else if (_main.is_Auto_mode && !is_touched)\r
+            {\r
+                // pah8009_unwearstatus_update();\r
+                ppg_sensor_disable();  \r
+                pah_800x_update_touch_setting(&_main.pah_800x);\r
+                //touch_sensor_enable();\r
+                _main.alg_is_enabled = MSG_ALG_DISABLE;  \r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+static void ppg_sensor_enable(void)\r
+{\r
+    if (_main.ppg_is_enabled)\r
+        return;\r
+    \r
+    pah_800x_ppg_toggle(&_main.pah_800x, true);\r
+\r
+    _main.debug_print_header = true;\r
+    _main.ppg_has_prev_report_timestamp = false;\r
+    _main.ppg_prev_report_timestamp = pah_get_tick_count();\r
+    _main.ppg_frame_count = 0;\r
+    \r
+    _main.ppg_is_enabled = true;\r
+    \r
+    _read_index = 0 ;\r
+    _write_index = 0 ;\r
+#ifdef PPG_MEMS_Synchronize\r
+    ppg_data_num = 0 ;\r
+#endif    \r
+    //LOG_PRINT("ppg_sensor_enable\n");\r
+}\r
+\r
+static void ppg_sensor_disable(void)\r
+{\r
+    if (!_main.ppg_is_enabled)\r
+        return;\r
+    \r
+    pah_800x_ppg_toggle(&_main.pah_800x, false);\r
+\r
+    _main.ppg_is_enabled = false;\r
+}\r
+\r
+static void touch_sensor_enable(void)\r
+{\r
+    if (_main.touch_is_enabled)\r
+        return;\r
+    \r
+    pah_800x_touch_toggle(&_main.pah_800x, true);\r
+\r
+    _main.touch_last_is_touched = 0;//default no touch => touch mode\r
+    \r
+    _main.touch_is_enabled = true;\r
+}\r
+\r
+static void touch_sensor_disable(void)\r
+{\r
+    if (!_main.touch_is_enabled)\r
+        return;\r
+    \r
+    pah_800x_touch_toggle(&_main.pah_800x, false);\r
+\r
+    _main.touch_is_enabled = false;\r
+}\r
+\r
+static void report_touch_data(uint64_t timestamp, const int8_t *touch_flag)\r
+{\r
+    LOG_PRINT("TOUCH: time = { %llu }, touch_flag = { %d } \n", timestamp, *touch_flag );\r
+}\r
+\r
+static void report_ppg_data(const ppg_mems_data_t *ppg_mems_data_alg)\r
+{\r
+    if (_main.debug_print_header == true)\r
+    {\r
+        LOG_PRINT("Frame, Time, Touch_Flag, Data_Ready, Overflow_Flag, Overflow_Num, ppg0, ppg1, ppg2, Expo_A, Expo_B, Expo_C, MEMS_X, MEMS_Y, MEMS_Z\n");\r
+        _main.debug_print_header = false;\r
+    }\r
+\r
+    LOG_PRINT("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",\r
+                ppg_mems_data_alg->ppg_frame_count, ppg_mems_data_alg->duration, ppg_mems_data_alg->touch_flag,\r
+                ppg_mems_data_alg->ppg_data.has_data, ppg_mems_data_alg->ppg_data.has_overflow, ppg_mems_data_alg->ppg_data.overflow_num,\r
+                ppg_mems_data_alg->ppg_data.data[0], ppg_mems_data_alg->ppg_data.data[1], ppg_mems_data_alg->ppg_data.data[2],\r
+                ppg_mems_data_alg->ppg_data.exposure_time[0], ppg_mems_data_alg->ppg_data.exposure_time[1], ppg_mems_data_alg->ppg_data.exposure_time[2],\r
+                (int)(ppg_mems_data_alg->MEMS_Data[0]), (int)(ppg_mems_data_alg->MEMS_Data[1]), (int)(ppg_mems_data_alg->MEMS_Data[2]));\r
+}\r
+\r
+static void report_hr_data(const ppg_mems_data_t *ppg_mems_data_alg, int32_t ret, float hr, float hr_grader)\r
+{\r
+    if (_main.debug_print_header == true)\r
+    {\r
+        LOG_PRINT("Frame, Time, Touch_Flag, Data_Ready, Overflow_Flag, Overflow_Num, PPG0, PPG1, PPG2, Expo_A, Expo_B, Expo_C, MEMS_X, MEMS_Y, MEMS_Z, ret, hr, hr_grade\n");\r
+\r
+        _main.debug_print_header = false;\r
+    }\r
+  \r
+    LOG_PRINT("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %f, %f\n",\r
+                ppg_mems_data_alg->ppg_frame_count, ppg_mems_data_alg->duration, ppg_mems_data_alg->touch_flag,\r
+                ppg_mems_data_alg->ppg_data.has_data, ppg_mems_data_alg->ppg_data.has_overflow, ppg_mems_data_alg->ppg_data.overflow_num,\r
+                ppg_mems_data_alg->ppg_data.data[0], ppg_mems_data_alg->ppg_data.data[1], ppg_mems_data_alg->ppg_data.data[2],\r
+                ppg_mems_data_alg->ppg_data.exposure_time[0], ppg_mems_data_alg->ppg_data.exposure_time[1], ppg_mems_data_alg->ppg_data.exposure_time[2],\r
+                (int)(ppg_mems_data_alg->MEMS_Data[0]), (int)(ppg_mems_data_alg->MEMS_Data[1]), (int)(ppg_mems_data_alg->MEMS_Data[2]), ret, hr,  hr_grader);\r
+\r
+}\r
+\r
+//static void report_spo2_data(const ppg_mems_data_t *ppg_mems_data_alg, int32_t ret, float mySpO2,  float myHR, float correlation, float trust_flag, float MEMS_RMS, int data_buf_count_spo2_alg, , float Opt_SpO2,  int drop_flag,  int ascend_flag,  int mems_flag)\r
+static void report_spo2_data(const ppg_mems_data_t *ppg_mems_data_alg, int32_t ret, float myHR, float mySpO2,  float correlation, float trust_flag, float MEMS_RMS, int data_buf_count_spo2_alg, uint8_t no_value_reason,  float   SignalPeriodicity,  int     time_accu )\r
+{\r
+    if (_main.debug_print_header == true)\r
+    {\r
+        \r
+         LOG_PRINT("Frame, Time, Touch_Flag, Data_Ready, Overflow_Flag, Overflow_Num, PPG0, PPG1, PPG2, Expo_A, Expo_B, Expo_C, MEMS_X, MEMS_Y, MEMS_Z, ret, spo2, myHR, hr_grader, correlation, MEMS_RMS, trust, no_value_reason, SignalPeriodicity, time_accu \n");       \r
+        _main.debug_print_header = false;\r
+    }\r
+\r
+  if(data_buf_count_spo2_alg>=25)\r
+    {\r
+                LOG_PRINT("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %f, %f, %f, %f, %f, %f, %d, %f, %d\n",\r
+                ppg_mems_data_alg->ppg_frame_count, ppg_mems_data_alg->duration, ppg_mems_data_alg->touch_flag,\r
+                ppg_mems_data_alg->ppg_data.has_data, ppg_mems_data_alg->ppg_data.has_overflow, ppg_mems_data_alg->ppg_data.overflow_num,\r
+                ppg_mems_data_alg->ppg_data.data[0], ppg_mems_data_alg->ppg_data.data[1], ppg_mems_data_alg->ppg_data.data[2],\r
+                ppg_mems_data_alg->ppg_data.exposure_time[0], ppg_mems_data_alg->ppg_data.exposure_time[1], ppg_mems_data_alg->ppg_data.exposure_time[2],\r
+                (int)(ppg_mems_data_alg->MEMS_Data[0]), (int)(ppg_mems_data_alg->MEMS_Data[1]), (int)(ppg_mems_data_alg->MEMS_Data[2]), ret, mySpO2,myHR,hr_grader,correlation, MEMS_RMS,trust_flag,no_value_reason,SignalPeriodicity, time_accu);\r
+    }\r
+    else\r
+    {\r
+                LOG_PRINT("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",\r
+                ppg_mems_data_alg->ppg_frame_count, ppg_mems_data_alg->duration, ppg_mems_data_alg->touch_flag,\r
+                ppg_mems_data_alg->ppg_data.has_data, ppg_mems_data_alg->ppg_data.has_overflow, ppg_mems_data_alg->ppg_data.overflow_num,\r
+                ppg_mems_data_alg->ppg_data.data[0], ppg_mems_data_alg->ppg_data.data[1], ppg_mems_data_alg->ppg_data.data[2],\r
+                ppg_mems_data_alg->ppg_data.exposure_time[0], ppg_mems_data_alg->ppg_data.exposure_time[1], ppg_mems_data_alg->ppg_data.exposure_time[2],\r
+                (int)(ppg_mems_data_alg->MEMS_Data[0]), (int)(ppg_mems_data_alg->MEMS_Data[1]), (int)(ppg_mems_data_alg->MEMS_Data[2]), ret);\r
+\r
+        \r
+    }\r
+}\r
+\r
+\r
+static void report_stress_data(const ppg_mems_data_t *ppg_mems_data_alg, uint8_t Stress_ReadyFlag, uint32_t measuretime, float collect_time)\r
+{\r
+    if (_main.debug_print_header == true)\r
+    {\r
+        LOG_PRINT("Frame, Time, Touch_Flag, Data_Ready, Overflow_Flag, Overflow_Num, PPG0, PPG1, PPG2, Expo_A, Expo_B, Expo_C, MEMS_X, MEMS_Y, MEMS_Z, Stress_Ready, measure_time, collect_time\n");\r
+\r
+        _main.debug_print_header = false;\r
+    }\r
+  \r
+    LOG_PRINT("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %f\n",\r
+                ppg_mems_data_alg->ppg_frame_count, ppg_mems_data_alg->duration, ppg_mems_data_alg->touch_flag,\r
+                ppg_mems_data_alg->ppg_data.has_data, ppg_mems_data_alg->ppg_data.has_overflow, ppg_mems_data_alg->ppg_data.overflow_num,\r
+                ppg_mems_data_alg->ppg_data.data[0], ppg_mems_data_alg->ppg_data.data[1], ppg_mems_data_alg->ppg_data.data[2],\r
+                ppg_mems_data_alg->ppg_data.exposure_time[0], ppg_mems_data_alg->ppg_data.exposure_time[1], ppg_mems_data_alg->ppg_data.exposure_time[2],\r
+                (int)(ppg_mems_data_alg->MEMS_Data[0]), (int)(ppg_mems_data_alg->MEMS_Data[1]), (int)(ppg_mems_data_alg->MEMS_Data[2]), Stress_ReadyFlag,duration_total, _hrv_state.collect_duration  );\r
+\r
+}\r
+#ifdef PPG_MEMS_Synchronize \r
+uint8_t  get_ppg_data_num(void)\r
+{\r
+    return ppg_data_num;\r
+}\r
+void  clear_ppg_data_num(void)\r
+{\r
+    ppg_data_num = 0;\r
+}\r
+\r
+void mems_interpolation(int16_t *mems_int_data_in,uint8_t mems_num,uint8_t ppg_num)\r
+{\r
+  \r
+    // Customer Define MEMS-input X, Y, Z\r
+    // Put data in mems_int_data_in ,and mems_count\r
+    // Then call the PXI_MEMS_interp to do interpolation \r
+    \r
+    PXI_MEMS_interp(mems_int_data_in, mems_num, mems_int_data_out, ppg_num);\r
+  \r
+}\r
+#endif\r
+\r
+static void error_handle(void)\r
+{\r
+    while (true)\r
+    {\r
+    }\r
+}\r
+\r
+\r
+\r
+uint16_t pah8009_get_chip_id(void)\r
+{\r
+    uint16_t product_id = 0;\r
+    pah_800x_get_product_id(&product_id);\r
+    return product_id;\r
+}\r
+\r
+uint32_t pah8009_get_factory_data(void)\r
+{\r
+    uint32_t data = factory_data;\r
+    factory_data = 0;\r
+    return data;\r
+}\r
+\r
+void pah8009_int_handler(void)\r
+{\r
+    ppg_interrupt_handle();\r
+    ppg_sensor_task_interrupt();\r
+    \r
+    if(work_mode == 1)\r
+    {\r
+        // PRINT("hr_alg_task \n");\r
+        hr_alg_task();\r
+    }    \r
+    else if(work_mode == 2)\r
+    {\r
+        // PRINT("spo2_alg_task \n");\r
+        spo2_alg_task();\r
+    }\r
+\r
+}\r
+\r
+void pah8009_timer_handler(void)\r
+{\r
+    ppg_sensor_task_polling();\r
+    \r
+    if(work_mode == 1)\r
+    {\r
+        // PRINT("hr_alg_task \n");\r
+        hr_alg_task();\r
+    }    \r
+    else if(work_mode == 2)\r
+    {\r
+        // PRINT("spo2_alg_task \n");\r
+        spo2_alg_task();\r
+    }\r
+\r
+}\r
+\r
+static void pah8009_timer_callback(void)\r
+{\r
+#ifdef SUPPORT_PPG_SERVICE\r
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_HRS_TIMER_CALLBACK);\r
+#endif\r
+}\r
+\r
+static void pah8009_timer_init(void)\r
+{\r
+    if(g_pah8009_timer == NULL)\r
+        g_pah8009_timer = osTimerNew((osTimerFunc_t)pah8009_timer_callback, osTimerPeriodic, NULL, NULL);\r
+}\r
+\r
+\r
+void pah8009_control(char *mode,uint8_t enable)\r
+{\r
+    // printf("mode : %s ,enable : %d\n",mode,enable);\r
+    if(!enable)\r
+    {\r
+#if POLLING_MODE\r
+        if(g_pah8009_timer != NULL)\r
+            osTimerStop(g_pah8009_timer);\r
+#endif\r
+        pah_sensor_stop();\r
+        if(uapi_dev_runtime_get_sleep_monitoring_status() && uapi_dev_runtime_get_hrs_passivity_flag())//处于睡眠监测 且在心率周期检测期间 上报活体佩戴 \r
+        {\r
+            pah8009_wearstatus_update();   \r
+            uapi_dev_runtime_set_hrs_passivity(0);//清除被动检测runtime     \r
+        }\r
+    }\r
+    else\r
+    {\r
+#if POLLING_MODE\r
+        pah8009_timer_init();\r
+#endif\r
+\r
+        time_cnt = 0;\r
+\r
+        if (strcmp(mode, "hrs") == 0) {\r
+            pah_sensor_init(diw_4mm_g_ir_hrd);\r
+            // auto_mode_sensor_start();\r
+            work_mode = 1;\r
+            // touch_only_sensor_start();\r
+            ppg_only_sensor_start();\r
+        } else if (strcmp(mode, "hrv") == 0) {\r
+            // md = HRV_MODE;\r
+        } else if (strcmp(mode, "spo2") == 0) {\r
+            // md = SPO2_MODE;\r
+            pah_sensor_init(diw_4mm_ir_r_ir_spo2);\r
+            auto_mode_sensor_start();\r
+            work_mode = 2;\r
+        } else if (strcmp(mode, "leaklight") == 0) {\r
+            // md = FT_LEAK_LIGHT_MODE;\r
+            factory_test_mode(factory_test_leak_light_target_sample, 0, 0, 0, 0);\r
+        } else if (strcmp(mode, "wear") == 0) {\r
+            pah_sensor_init(diw_4mm_g_ir_hrd);\r
+            touch_only_sensor_start();\r
+        }\r
+#if POLLING_MODE\r
+        if(g_pah8009_timer != NULL)\r
+            osTimerStart(g_pah8009_timer,40);\r
+#endif\r
+    }\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.h
new file mode 100644 (file)
index 0000000..2e51b95
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef __pah_800x_main_h__\r
+#define __pah_800x_main_h__\r
+\r
+// pah\r
+#include "pah_800x.h"\r
+#include "pah_unit.h"\r
+#include "pah_800x_config.h"\r
+\r
+\r
+\r
+//static hr algotirhm\r
+// #include "pxialg.h"\r
+\r
+// spo2 algorithm\r
+// #include "pxialg_spo2.h"\r
+\r
+// Stress algorithm\r
+// #include "pxialg_hrv.h"\r
+#ifdef PPG_MEMS_Synchronize\r
+//MEMS-INT\r
+#include "pxi_interp.h"\r
+#endif\r
+//============================================================================\r
+// Functions\r
+//============================================================================\r
+#ifdef __cplusplus\r
+extern  "C" {\r
+#endif \r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+#ifdef PPG_MEMS_Synchronize\r
+#define FIFO_SIZE 50  //FIFO Size is dependent on the CPU performance\r
+#else\r
+#define FIFO_SIZE 8  //FIFO Size is dependent on the CPU performance\r
+#endif\r
+\r
+//============================================================================\r
+// Type Definition\r
+//============================================================================\r
+#pragma pack(1)\r
+typedef struct raw_data_13bytes_t\r
+{\r
+    uint8_t loss;\r
+    uint32_t rawData;\r
+    uint8_t non_zero1;\r
+    uint8_t non_zero2;\r
+    uint8_t non_zero3;\r
+    uint8_t frame_count;\r
+    uint8_t time;\r
+    uint8_t rsv;\r
+    uint8_t touch;\r
+    uint8_t rsv2;\r
+} sRaw_Data_13Bytes;\r
+\r
+typedef enum {\r
+    MSG_ALG_NOCHANGE = 0,\r
+    MSG_ALG_ENABLE,\r
+    MSG_ALG_DISABLE,\r
+} alg_msg_code_t;\r
+#pragma pack()\r
+\r
+typedef enum\r
+{\r
+    pc_4mm_2g_ir_hrd,           // PC 4.25mm for HRD          wear\r
+    diw_4mm_g_ir_hrd,           // DI+WALL 4.25mm for HRD     hrs\r
+    diw_4mm_ir_r_ir_spo2,       // DI+WALL 4.25mm for SPO2    spo2\r
+    pc_22mm_2g_ir_hrd,          // PC 2.2mm for HRD\r
+    di_18mm_g_g_hrd,            // DI 1.8mm for HRD\r
+\r
+} reg_config_type;\r
+\r
+typedef struct {\r
+    \r
+    volatile bool       has_interrupt;\r
+    volatile uint64_t   interrupt_timestamp;\r
+    \r
+    // pah\r
+    pah_800x            pah_800x;\r
+    \r
+    bool                is_Auto_mode;\r
+    // ppg\r
+    bool                ppg_is_enabled;\r
+    //bool                ppg_only_is_enabled;\r
+    bool                ppg_has_prev_report_timestamp;\r
+    uint64_t            ppg_prev_report_timestamp;\r
+    uint8_t             ppg_frame_count;\r
+\r
+    // touch\r
+    bool                touch_is_enabled;\r
+    //bool                touch_only_is_enabled;\r
+    int                 touch_last_is_touched;\r
+    \r
+    // alg\r
+    uint8_t             alg_is_enabled;\r
+    bool                hr_is_enabled;\r
+    bool                spo2_is_enabled;\r
+    bool                stress_is_enable;\r
+    // debug\r
+    bool                debug_print_header;\r
+    uint8_t             debug_frame_count;\r
+    \r
+} main_state;\r
+\r
+typedef struct {    \r
+    float                 MEMS_Data[3] ;\r
+    pah_800x_ppg_data     ppg_data;\r
+    uint8_t               touch_flag;\r
+    uint8_t               duration;\r
+    uint8_t               ppg_frame_count;\r
+    //pah_800x_touch_data touch_data;\r
+} ppg_mems_data_t;\r
+\r
+\r
+\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+void pah_sensor_init(reg_config_type type);\r
+void touch_only_sensor_start(void);\r
+void ppg_only_sensor_start(void);\r
+void auto_mode_sensor_start(void);\r
+void pah_sensor_stop(void);\r
+void ppg_interrupt_handle(void);\r
+void ppg_sensor_task_interrupt(void);\r
+void ppg_sensor_task_polling(void);\r
+\r
+\r
+bool isFIFOEmpty(void);\r
+bool pah_push(ppg_mems_data_t *data);\r
+bool pah_pop(ppg_mems_data_t *data);\r
+\r
+\r
+uint8_t Check_alg_enable(void);\r
+void Clear_alg_enable(void);\r
+\r
+//HRD\r
+void hr_algorithm_enable(void);\r
+void hr_algorithm_disable(void);\r
+void hr_alg_task(void);\r
+void hr_alg_task2(uint8_t ppg_num);\r
+\r
+//SPO2\r
+void spo2_algorithm_enable(void);\r
+void spo2_algorithm_disable(void);\r
+void spo2_alg_task(void);\r
+void spo2_alg_task2(uint8_t ppg_num);\r
+\r
+//Stress\r
+void stress_algorithm_enable(void);\r
+void stress_algorithm_disable(void);\r
+//void stress_alg_task(void);\r
+void stress_alg_task(int grade);\r
+\r
+uint16_t pah8009_get_chip_id(void);\r
+void pah8009_control(char *mode,uint8_t enable);\r
+uint32_t pah8009_get_factory_data(void);\r
+void pah8009_int_handler(void);\r
+\r
+/**\r
+ * @brief Macro to be used in a formatted string to a pass float number to the log.\r
+ *\r
+ * Macro should be used in formatted string instead of the %f specifier together with\r
+ * @ref LOG_FLOAT macro.\r
+ * Example: LOG_INFO("My float number" LOG_FLOAT_MARKER "\r\n", LOG_FLOAT(f)))\r
+ */\r
+#define LOG_FLOAT_MARKER "%c%d.%05d"\r
+\r
+/**\r
+ * @brief Macro for dissecting a float number into two numbers (integer and residuum).\r
+ */\r
+#define LOG_FLOAT(val) ((val >= 0.0f)?32:45),(int32_t)((val >= 0.0f)?val:val*-1) , (int32_t)(((val > 0) ? (val) - (int32_t)(val): (int32_t)(val) - (val))*100000)                       \r
+\r
+\r
+\r
+#ifdef PPG_MEMS_Synchronize\r
+//MEMS  Interpolation\r
+//void mems_interpolation(uint8_t ppg_num);\r
+void mems_interpolation(int16_t *mems_int_data_in,uint8_t mems_count,uint8_t ppg_num);\r
+uint8_t  get_ppg_data_num(void);\r
+void  clear_ppg_data_num(void);\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h
new file mode 100644 (file)
index 0000000..abf28f2
--- /dev/null
@@ -0,0 +1,484 @@
+#ifndef __pah_8009_reg_arr_default_h__\r
+#define __pah_8009_reg_arr_default_h__\r
+\r
+// c\r
+#include <stdint.h>\r
+\r
+//pah\r
+#include "pah_800x_config.h"\r
+\r
+\r
+static const uint8_t PAH8009_REG_DEVICE_INIT[][2] = {\r
+//  { 0xEE,0x07 }, //SW RESET\r
+    { 0xD1,0xD0 },//{R_GPIO_0_IEB, R_GPIO_1_IEB, R_GPIO_0_OEB, R_GPIO_1_OEB, R_GPIO_0_PULLL_EnH, R_GPIO_1_PULLL_EnH, R_GPIO_0_PULLH_EnH, R_GPIO_1_PULLH_EnH};\r
+       { 0xD2,0x00+R_GPIO_SLEW+R_GPIO_0_OD_EnH },//R_GPIO_0_Open_Drain_EnH(0xD2[5]), 1(0x20):GPIO default open-drain mode, 0(0x00):GPIO debug mode\r
+    { 0xD3,0x20 },//GPIO debug select\r
+    { 0xD6,0x00+R_I2C_SLEW },//{Dummy, R_I2C_SLEW, Dummy[5:0]}\r
+#if (INT_OD_EXTERNAL_PULLH)\r
+    { 0xD1,0xD0 },//{R_GPIO_0_IEB, R_GPIO_1_IEB, R_GPIO_0_OEB, R_GPIO_1_OEB, R_GPIO_0_PULLL_EnH, R_GPIO_1_PULLL_EnH, R_GPIO_0_PULLH_EnH, R_GPIO_1_PULLH_EnH};\r
+       { 0xD2,0x20+R_GPIO_SLEW },//R_GPIO_0_Open_Drain_EnH(0xD2[5]), 1(0x20):GPIO default open-drain mode, 0(0x00):GPIO debug mode\r
+    { 0xD3,0x00 },//GPIO debug select\r
+    { 0xD6,0x00+R_I2C_SLEW },//{Dummy, R_I2C_SLEW, Dummy[5:0]}\r
+#endif\r
+#if (INT_OD_INTERNAL_PULLH)\r
+    { 0xD1,0xD2 },//{R_GPIO_0_IEB, R_GPIO_1_IEB, R_GPIO_0_OEB, R_GPIO_1_OEB, R_GPIO_0_PULLL_EnH, R_GPIO_1_PULLL_EnH, R_GPIO_0_PULLH_EnH, R_GPIO_1_PULLH_EnH};\r
+       { 0xD2,0x20+R_GPIO_SLEW },//R_GPIO_0_Open_Drain_EnH(0xD2[5]), 1(0x20):GPIO default open-drain mode, 0(0x00):GPIO debug mode\r
+    { 0xD3,0x00 },//GPIO debug select\r
+    { 0xD6,0x00+R_I2C_SLEW },//{Dummy, R_I2C_SLEW, Dummy[5:0]}\r
+#endif\r
+#if (INT_PUP_WITHOUT_PULLH)\r
+    { 0xD1,0xD0 },//{R_GPIO_0_IEB, R_GPIO_1_IEB, R_GPIO_0_OEB, R_GPIO_1_OEB, R_GPIO_0_PULLL_EnH, R_GPIO_1_PULLL_EnH, R_GPIO_0_PULLH_EnH, R_GPIO_1_PULLH_EnH};\r
+       { 0xD2,0x00+R_GPIO_SLEW },//R_GPIO_0_Open_Drain_EnH(0xD2[5]), 1(0x20):GPIO default open-drain mode, 0(0x00):GPIO debug mode\r
+    { 0xD3,0x00 },//GPIO debug select\r
+       { 0xD6,0x00+R_I2C_SLEW },//{Dummy, R_I2C_SLEW, Dummy[5:0]}\r
+#endif\r
+//    { 0xD6,0x30 },//{Dummy, R_I2C_SLEW, R_I2C_DRV[1:0], Dummy[3:0]}\r
+//    { 0xD5,0x44 },//IO-level(I2C), 44:3.3V, 00:1.8V\r
+//    { 0xB2,0x25 },\r
+    { 0x55,0x24 },//Soft Reset:04 Hard Reset:24\r
+    { 0x52,0x12 },//VDDAY=1.63V\r
+//    { 0xA6,0xF7 },//Cmd_vdday_pwrsv_sel_EnH=0\r
+    { 0xAE,0x3F },//R_LPO_Cali_mode=1\r
+    { 0x20,0x05 },//Clear INT\r
+};\r
+#ifndef LED_SUPPLIER_NEW\r
+#ifdef DI_WALL_4mm\r
+#define PPG_SETTING_VERSION 0x01\r
+#endif\r
+#if (DIW_4MM_G_IR_HRD==1)\r
+static const uint8_t PAH8009_REG_DIW_4MM_G_IR_PPG[][2] = {\r
+    //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0xE8 },//A period\r
+    { 0x09,0x03 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x04 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x08 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x76 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x04 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x92 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x58 },//RDB_expo_A[7:0]\r
+    { 0x18,0x02 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x01 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x2F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+static const uint8_t PAH8009_REG_DIW_4MM_G_IR_TOUCH[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0x92 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+#endif\r
+#if (DIW_4MM_IR_R_IR_SPO2==1)\r
+static const uint8_t PAH8009_REG_DIW_4MM_IR_R_IR_PPG[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x00 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x05 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0x00 },//A period\r
+    { 0x09,0x01 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x01 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x40 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x40 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x77 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x52 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x44 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x84 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x40 },//RDB_expo_A[7:0]\r
+    { 0x18,0x00 },//RDB_expo_A[15:8]\r
+    { 0x19,0x40 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x00 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x4F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+\r
+static const uint8_t PAH8009_REG_DIW_4MM_IR_R_IR_TOUCH[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x00 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x05 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0x92 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+#endif\r
+\r
+#if (PC_4MM_2G_IR_HRD==1)\r
+#ifdef PC_4mm\r
+#define PPG_SETTING_VERSION 0x11\r
+#endif\r
+static const uint8_t PAH8009_REG_PC_4MM_2G_IR_PPG[][2] = {\r
+    //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0xE8 },//A period\r
+    { 0x09,0x03 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x04 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x08 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x76 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x44 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0xC4 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x58 },//RDB_expo_A[7:0]\r
+    { 0x18,0x02 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x01 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x28 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x6F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH  \r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+static const uint8_t PAH8009_REG_PC_4MM_2G_IR_TOUCH[][2] = {\r
+    //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0xD2 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x28 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH  \r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+#endif\r
+\r
+\r
+#else\r
+#ifdef DI_WALL_4mm\r
+#define PPG_SETTING_VERSION 0x21\r
+#endif\r
+#if (DIW_4MM_G_IR_HRD==1)\r
+static const uint8_t PAH8009_REG_DIW_4MM_G_IR_PPG[][2] = {\r
+       //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0xE8 },//A period\r
+    { 0x09,0x03 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x04 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x08 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x76 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x04 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x12 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x58 },//RDB_expo_A[7:0]\r
+    { 0x18,0x02 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x01 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x2F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+static const uint8_t PAH8009_REG_DIW_4MM_G_IR_TOUCH[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0x12 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+#endif\r
+\r
+#if (DIW_4MM_IR_R_IR_SPO2==1)\r
+static const uint8_t PAH8009_REG_DIW_4MM_IR_R_IR_PPG[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x00 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x05 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0x00 },//A period\r
+    { 0x09,0x01 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x01 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x40 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x40 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x77 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x04 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x04 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x40 },//RDB_expo_A[7:0]\r
+    { 0x18,0x00 },//RDB_expo_A[15:8]\r
+    { 0x19,0x40 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x00 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x4F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+static const uint8_t PAH8009_REG_DIW_4MM_IR_R_IR_TOUCH[][2] = {\r
+  //{ 0xEE,0x07 },\r
+    { 0x03,0x00 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x05 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0x12 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x20 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH\r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+#endif\r
+\r
+//China LED\r
+\r
+#if (PC_4MM_2G_IR_HRD==1)\r
+#ifdef PC_4mm\r
+#define PPG_SETTING_VERSION 0x31\r
+#endif\r
+static const uint8_t PAH8009_REG_PC_4MM_2G_IR_PPG[][2] = {\r
+    //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x08,0xE8 },//A period\r
+    { 0x09,0x03 },//A period\r
+    { 0x0A,0x00 },//B period\r
+    { 0x0B,0x08 },//B period\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x0E,0x04 },//RDB_FrameNum_A[6:0]\r
+    { 0x0F,0x08 },//RDB_FrameNum_B[6:0]\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x76 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x14,0x12 },//{RDB_ChA_congain_sel[1:0], Dummy[0], R_LEDDAC_code0[4:0]}\r
+    { 0x15,0x44 },//{RDB_ChB_congain_sel[1:0], Dummy[0], R_LEDDAC_code1[4:0]}\r
+    { 0x16,0x04 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x17,0x58 },//RDB_expo_A[7:0]\r
+    { 0x18,0x02 },//RDB_expo_A[15:8]\r
+    { 0x19,0x00 },//RDB_expo_B[7:0]\r
+    { 0x1A,0x01 },//RDB_expo_B[15:8]\r
+    { 0x1B,0x28 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1D,0x1F },//{R_ChA_LED_EnH[2:0], R_ChA_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1E,0x6F },//{R_ChB_LED_EnH[2:0], R_ChB_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0xF7 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH  \r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+\r
+static const uint8_t PAH8009_REG_PC_4MM_2G_IR_TOUCH[][2] = {\r
+    //{ 0xEE,0x07 },\r
+    { 0x03,0x40 },//Golden report period[7:0] (1T=31.25us)\r
+    { 0x04,0x06 },//Golden report period[15:8]\r
+    { 0x05,0x00 },//Golden report period[19:16]\r
+    { 0x12,0x01 },//ChC_report_divider[7:0]\r
+    { 0x13,0x00 },//ChC_report_divider[9:8]\r
+    { 0x0C,0x00 },//C period\r
+    { 0x0D,0x01 },//C period\r
+    { 0x10,0x01 },//RDB_FrameNum_C[6:0]\r
+    { 0x11,0x44 },//{R_OnOff_mode_C_EnH, R_OnOff_mode_B_EnH, R_OnOff_mode_A_EnH, R_ChC_EnH, R_ChB_EnH, R_ChA_EnH}\r
+    { 0x16,0x12 },//{RDB_ChC_congain_sel[1:0], Dummy[0], R_LEDDAC_code2[4:0]}\r
+    { 0x1B,0x28 },//RDB_expo_C[7:0]\r
+    { 0x1C,0x00 },//RDB_expo_C[15:8]\r
+    { 0x1F,0x1F },//{R_ChC_LED_EnH[2:0], R_ChC_Pixel_EnH[3:0]}, [3]:pixel3, [2]:pixel2, [1]:pixel1, [0]:pixel0, enable high\r
+    { 0x22,0x04 },//RDB_Int_En[7:0], [2]:touch flag [1]:overflow [0]:data ready\r
+    { 0x26,0x20 },//{R_ADCdata_C_Sel[1:0], R_ADCdata_B_Sel[1:0], R_ADCdata_A_Sel[1:0]}, 0:on, 1:off(需開On-Off), 2:on-off(需開On-Off)\r
+    { 0x49,0x11 },//RDB_Touch_EnH  \r
+    { 0x4A,0x00 },//R_TouchDetection_Th_Hi[7:0]\r
+    { 0x4B,0x07 },//R_TouchDetection_Th_Hi[13:8]\r
+    { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]\r
+    { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+    { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
+    { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+    { 0xEB,0x80 },//update_flag\r
+};\r
+#endif\r
+\r
+#endif\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.c b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.c
new file mode 100644 (file)
index 0000000..da77ddb
--- /dev/null
@@ -0,0 +1,833 @@
+// pah\r
+#include "pah_800x.h"\r
+\r
+\r
+//============================================================================\r
+// Private function\r
+//============================================================================\r
+static bool sensor_has_enabled(pah_800x *state);\r
+\r
+static pah_ret ppg_convergence_toggle(pah_800x *state, bool enable, uint8_t ch_num);\r
+\r
+static pah_ret ppg_reset_exposure(pah_800x *state, uint8_t ch_num);\r
+\r
+//static pah_ret touch_process(pah_800x *state, uint8_t *touch_flag);\r
+static pah_ret ppg_process(pah_800x *state, pah_800x_ppg_data *ppg_result);\r
+static pah_ret clear_interrupt(pah_800x *state, bool has_ppg_interrupt, bool has_overflow);\r
+\r
+static pah_ret ppg_converging(pah_800x *state, uint32_t ppg_value, uint8_t ch_num);\r
+static uint16_t select_new_ppg_exposure(pah_800x *state, uint16_t old_ppg_exposure, uint16_t ppg_value, uint8_t ch_num);\r
+\r
+static bool is_touched(pah_800x *state);\r
+static bool is_not_touched(pah_800x *state);\r
+\r
+static bool ppg_value_is_out_of_outer_bounds(pah_800x *state, uint32_t ppg_data, uint8_t ch_num);\r
+static bool ppg_value_is_out_of_inner_bounds(pah_800x *state, uint16_t ppg_data, uint8_t ch_num);\r
+\r
+static pah_ret pah_800x_sw_reset(pah_800x *state);\r
+/////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+//// comm\r
+\r
+static pah_ret pah_800x_hal_comm_write(uint8_t addr, const uint8_t *data, size_t write_size);\r
+static pah_ret pah_800x_hal_comm_read(uint8_t addr, uint8_t *data, size_t read_size);\r
+\r
+    \r
+//// write\r
+static pah_ret pah_800x_hal_write_reg_arr(const pah_reg_arr *reg_arr);\r
+static pah_ret pah_800x_hal_write_reg_array(const uint8_t reg_array[][2], size_t length);\r
+static pah_ret pah_800x_hal_write_suspend_state(bool suspend);\r
+static pah_ret pah_800x_hal_write_interrupt_clear(void);\r
+static pah_ret pah_800x_hal_write_interrupt_clear_v2(bool int_status_DR_FLAG_b);\r
+static pah_ret pah_800x_hal_write_ppg_overflow_clear(void);\r
+static pah_ret pah_800x_hal_write_exposure(uint16_t exposure, uint8_t ch_num);\r
+static pah_ret pah_800x_hal_tg_toggle(bool enable);\r
+static pah_ret pah_800x_hal_update_flag(void);\r
+static pah_ret pah_800x_hal_write_sw_reset(void);\r
+static pah_ret pah_800x_hal_reset_gpio_state(void);\r
+//// read\r
+static pah_ret pah_800x_hal_read_product_id(uint16_t *product_id);\r
+static pah_ret pah_800x_hal_read_ppg_interrupt(uint8_t *ppg_interrupt);\r
+static pah_ret pah_800x_hal_read_ppg_sync(uint32_t *ppg_data, uint8_t ch_num);\r
+static pah_ret pah_800x_hal_read_ppg_overflow(uint8_t *ppg_overflow, uint8_t *overflow_num);\r
+static pah_ret pah_800x_hal_read_ppg_exposure(uint16_t *als_exposure, uint8_t ch_num);\r
+static pah_ret pah_800x_hal_touch_get_touch_flag(int8_t *touch_flag);\r
+static pah_ret pah_800x_hal_touch_get_touch_info(int8_t *touch_flag,uint16_t *touch_value);\r
+\r
+\r
+static pah_ret pah_800x_hal_check_enable_channel(pah_800x *state, const pah_reg_arr *reg_arr);\r
+static pah_ret comm_write(uint8_t addr, uint8_t data);\r
+static pah_ret pah_800x_hal_read_ppg_adc(uint16_t *ppg_adc, uint8_t ch_num);\r
+static pah_ret pah_800x_hal_read_ppg_frame_period(uint16_t *ppg_frame_period, uint8_t ch_num);\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+uint16_t pah_800x_get_i2c_default_slave_addr(void)\r
+{\r
+    return PAH_800x_DEFAULT_I2C_SLAVE_ID_1;\r
+}\r
+\r
+void pah_800x_get_default_config(pah_800x_config *config)\r
+{\r
+    memset(config, 0, sizeof(*config));    \r
+\r
+    config->enable_ppg_convergence[0] = PAH_800x_DEFAULT_ENABLE_PPG_CONVERGENCE;\r
+    config->enable_ppg_convergence[1] = PAH_800x_DEFAULT_ENABLE_PPG_CONVERGENCE;\r
+    config->enable_ppg_convergence[2] = false;\r
+\r
+    config->enable_ppg_reconvergence_if_out_of_bounds[0] = PAH_800x_DEFAULT_ENABLE_PPG_RECONVERGENCE_IF_OUT_OF_BOUNDS;\r
+    config->enable_ppg_reconvergence_if_out_of_bounds[1] = PAH_800x_DEFAULT_ENABLE_PPG_RECONVERGENCE_IF_OUT_OF_BOUNDS;\r
+    config->enable_ppg_reconvergence_if_out_of_bounds[2] = false;\r
+    \r
+    for(int ch=0;ch<PAH_800x_MAX_CH_NUM;ch++)\r
+    {\r
+        config->ppg_convergence[ch].t_weight_normal_mode = PAH_800x_DEFAULT_PPG_CONVERGENCE_T_WEIGHT_NORMAL_MODE;\r
+        config->ppg_convergence[ch].t_weight_fast_mode = PAH_800x_DEFAULT_PPG_CONVERGENCE_T_WEIGHT_FAST_MODE;\r
+        config->ppg_convergence[ch].t_min = PAH_800x_DEFAULT_PPG_CONVERGENCE_T_MIN;\r
+        config->ppg_convergence[ch].t_max = PAH_800x_DEFAULT_PPG_CONVERGENCE_T_MAX;\r
+        config->ppg_convergence[ch].raw_outer_high_bound = PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_OUTER_HIGH_BOUND;\r
+        config->ppg_convergence[ch].raw_inner_high_target = PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_INNER_HIGH_TARGET;\r
+        config->ppg_convergence[ch].raw_inner_low_target = PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_INNER_LOW_TARGET;\r
+        config->ppg_convergence[ch].raw_outer_low_bound = PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_OUTER_LOW_BOUND;\r
+        config->ppg_convergence[ch].convergence_count = PAH_800x_DEFAULT_PPG_CONVERGENCE_COUNT;\r
+        config->ppg_initial_exposure[ch] = PAH_800x_DEFAULT_PPG_INITIAL_EXPOSURE;\r
+    }   \r
+\r
+}\r
+\r
+pah_ret pah_800x_get_product_id(uint16_t *product_id)\r
+{\r
+    return pah_800x_hal_read_product_id(product_id);\r
+}\r
+\r
+pah_ret pah_800x_init(pah_800x *state, const pah_800x_config *config)\r
+{\r
+    memset(state, 0, sizeof(*state));\r
+    \r
+   // state->plat     = *plat;\r
+    state->config   = *config;\r
+    for(int ch=0;ch<PAH_800x_MAX_CH_NUM;ch++)\r
+    {\r
+        DEBUG_PRINT("enable_ppg_convergence_ch[%d] = %d\n", ch, config->enable_ppg_convergence[ch]);\r
+        if (config->enable_ppg_convergence[ch])\r
+        {\r
+            DEBUG_PRINT("(t_weight_normal_mode, t_weight_fast_mode) = (%d, %d)\n",\r
+                        config->ppg_convergence[ch].t_weight_normal_mode,\r
+                        config->ppg_convergence[ch].t_weight_fast_mode);\r
+            DEBUG_PRINT("(t_min, t_max) = (%d, %d)\n",\r
+                        config->ppg_convergence[ch].t_min,\r
+                        config->ppg_convergence[ch].t_max);\r
+            DEBUG_PRINT("(raw_outer_high_bound, raw_inner_high_target) = (%d, %d)\n",\r
+                        config->ppg_convergence[ch].raw_outer_high_bound,\r
+                        config->ppg_convergence[ch].raw_inner_high_target);\r
+            DEBUG_PRINT("(raw_inner_low_target, raw_outer_low_bound) = (%d, %d)\n",\r
+                        config->ppg_convergence[ch].raw_inner_low_target,\r
+                        config->ppg_convergence[ch].raw_outer_low_bound);\r
+        }\r
+    }\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_deinit(pah_800x *state)\r
+{\r
+    pah_800x_ppg_toggle(state, false);\r
+    pah_800x_touch_toggle(state, false);\r
+    pah_800x_power_toggle(state, false);\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_device_init(pah_800x *state, const pah_800x_reg_setting *reg_setting)\r
+{\r
+    DEBUG_PRINT("%s\n", __func__);\r
+\r
+    //uint16_t *product_id;\r
+    uint16_t product_id;\r
+    state->reg_setting = *reg_setting;\r
+\r
+    pah_800x_hal_write_suspend_state(false);\r
+    pah_800x_hal_write_sw_reset();\r
+    pah_delay_ms(2);\r
+    pah_800x_power_toggle(state, true);\r
+    \r
+    // read id, delay for reg bank reset\r
+    //pah_800x_hal_read_product_id(product_id);\r
+    pah_800x_hal_read_product_id(&product_id);\r
+    pah_800x_hal_write_reg_arr(&state->reg_setting.startup_init);\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_power_toggle(pah_800x *state, bool enable)\r
+{\r
+    DEBUG_PRINT("%s(%d, %d)\n", __func__, state->is_powered, enable);\r
+\r
+    \r
+    if (enable)\r
+    {\r
+        if (state->is_powered == enable)\r
+        {\r
+            return PAH_RET_SUCCESS;\r
+        }\r
+        pah_800x_hal_write_suspend_state(false);\r
+    }\r
+    else\r
+    {\r
+        state->ppg_state.is_enabled = false;\r
+        state->touch_state.is_enabled = false;\r
+        \r
+        pah_800x_hal_write_suspend_state(false);\r
+        //pah_800x_hal_write_sw_reset();\r
+        pah_delay_ms(2);\r
+        pah_800x_hal_write_suspend_state(true);\r
+        pah_800x_hal_reset_gpio_state();\r
+    }\r
+\r
+    state->is_powered = enable;\r
+    state->touch_state.touch_flag = TOUCH_TRALSE_VALUE;\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_verify_product_id(pah_800x *state, uint16_t *product_id)\r
+{\r
+    return pah_800x_hal_read_product_id(product_id);\r
+}\r
+\r
+pah_ret pah_800x_ppg_toggle(pah_800x *state, bool enable)\r
+{\r
+    DEBUG_PRINT("%s(%d, %d)\n", __func__, state->ppg_state.is_enabled, enable);\r
+    if (state->ppg_state.is_enabled == enable)\r
+        return PAH_RET_SUCCESS;\r
+    //pah_800x_hal_write_als_toggle( enable);\r
+    if (enable)\r
+    {\r
+        //load ppg setting\r
+        //comm_write(0xEB,0x80);\r
+//        for(uint8_t ch_num=0;ch_num < PAH_800x_MAX_CH_NUM;ch_num++)\r
+//        {\r
+//            ppg_reset_exposure(state,ch_num);\r
+//            pah_800x_hal_update_flag();\r
+//        }\r
+       \r
+        pah_800x_hal_write_reg_arr(&state->reg_setting.ppg_enable);\r
+\r
+        pah_800x_hal_check_enable_channel(state, &state->reg_setting.ppg_enable);\r
+        //DEBUG_PRINT("ch enable %d %d %d \n",state->ppg_state.ppg_ch_enabled[0],state->ppg_state.ppg_ch_enabled[1],state->ppg_state.ppg_ch_enabled[2]);\r
+        pah_800x_hal_update_flag();              \r
+\r
+        pah_800x_hal_write_interrupt_clear();\r
+        if(!state->touch_state.is_enabled)\r
+            pah_800x_hal_tg_toggle(true);\r
+    }\r
+    else\r
+    {\r
+        if(!state->touch_state.is_enabled)\r
+            pah_800x_hal_tg_toggle(false);\r
+    }\r
+    \r
+    \r
+    for(uint8_t ch_num=0;ch_num < PAH_800x_MAX_CH_NUM;ch_num++)\r
+    {\r
+        state->ppg_state.is_converging[ch_num] = enable;\r
+        state->ppg_state.cur_converging_count[ch_num] = 0;\r
+    }\r
+    \r
+    state->ppg_state.is_enabled = enable;\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_ppg_get_data(pah_800x *state, pah_800x_ppg_data *ppg_data)\r
+{\r
+    *ppg_data = state->ppg_result;\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_update_touch_setting(pah_800x *state)\r
+{\r
+    pah_800x_hal_write_reg_arr(&state->reg_setting.touch_enable);\r
+    pah_800x_hal_update_flag();\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_touch_toggle(pah_800x *state, bool enable)\r
+{\r
+    DEBUG_PRINT("%s(%d, %d)\n", __func__, state->touch_state.is_enabled, enable);\r
+    if (state->touch_state.is_enabled == enable)\r
+        return PAH_RET_SUCCESS;\r
+\r
+    if (enable)\r
+    {\r
+        //load touch setting\r
+        pah_800x_hal_write_reg_arr(&state->reg_setting.touch_enable);\r
+        pah_800x_hal_update_flag();\r
+        pah_800x_hal_tg_toggle(true);\r
+    }\r
+    else\r
+        pah_800x_hal_tg_toggle(false);\r
+    state->touch_state.is_enabled = enable;\r
+        \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+pah_ret pah_800x_get_touch_flag(pah_800x *state, int8_t *touch_flag)\r
+{\r
+    *touch_flag = state->touch_flag;\r
+    return PAH_RET_SUCCESS;\r
+}\r
+pah_ret pah_800x_get_touch_value(pah_800x *state, uint16_t *touch_value)\r
+{\r
+    *touch_value = state->touch_value;\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+\r
+pah_ret pah_800x_task(pah_800x *state)\r
+{\r
+    uint8_t ppg_interrupt = 0;\r
+    bool has_ppg_interrupt = false;\r
+    memset(&state->ppg_result, 0, sizeof(state->ppg_result));\r
+    state->touch_flag = -1;\r
+    //memset(&state->touch_result, 0, sizeof(state->touch_result));\r
+    \r
+    //touch_process(state, &state->touch_flag);\r
+    pah_800x_hal_touch_get_touch_flag( &state->touch_flag);\r
+    //pah_800x_hal_touch_get_touch_info( &state->touch_flag,&state->touch_value);\r
+\r
+    pah_800x_hal_read_ppg_interrupt(&ppg_interrupt);\r
+    \r
+    has_ppg_interrupt = (ppg_interrupt > 0);\r
+    //DEBUG_PRINT("%s(%d)(%d)\n", __func__, ppg_interrupt,state->touch_flag);\r
+    if (has_ppg_interrupt > 0)\r
+    {\r
+        ppg_process(state, &state->ppg_result);\r
+    }\r
+\r
+    clear_interrupt(state, has_ppg_interrupt, state->ppg_result.has_overflow);\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+\r
+//============================================================================\r
+// Private function\r
+//============================================================================\r
+static bool sensor_has_enabled(pah_800x *state)\r
+{\r
+    return state->ppg_state.is_enabled\r
+        || state->touch_state.is_enabled;\r
+}\r
+\r
+static pah_ret ppg_convergence_toggle(pah_800x *state, bool enable, uint8_t ch_num)\r
+{\r
+    //DEBUG_PRINT("%s(%d, %d, %d)\n", __func__, state->config.enable_ppg_convergence[ch_num], enable, ch_num);\r
+\r
+    if (ch_num >= PAH_800x_MAX_CH_NUM)\r
+        return PAH_RET_INVALID_ARGUMENT;\r
+\r
+    if (!state->config.enable_ppg_convergence[ch_num])\r
+        return PAH_RET_SUCCESS;\r
+   \r
+    if (enable && state->ppg_state.cur_converging_count[ch_num] < state->config.ppg_convergence[ch_num].convergence_count)\r
+    {\r
+        state->ppg_state.cur_converging_count[ch_num]++;\r
+        return PAH_RET_SUCCESS;\r
+    }\r
+    else\r
+       {\r
+         state->ppg_state.cur_converging_count[ch_num] = 0;\r
+       }\r
+    state->ppg_state.is_converging[ch_num] = enable;\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret ppg_reset_exposure(pah_800x *state, uint8_t ch_num)\r
+{\r
+    //DEBUG_PRINT("%s(%d)\n", __func__, state->config.ppg_initial_exposure[ch_num]);\r
+    if (!state->config.enable_ppg_convergence[ch_num])\r
+        return PAH_RET_SUCCESS;\r
+\r
+    return pah_800x_hal_write_exposure( state->config.ppg_initial_exposure[ch_num],ch_num);\r
+}\r
+/*static pah_ret touch_process(pah_800x *state, uint8_t *touch_flag)\r
+{\r
+\r
+    pah_800x_touch_get_touch_flag( touch_flag);\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}*/\r
+\r
+\r
+static pah_ret ppg_process(pah_800x *state, pah_800x_ppg_data *ppg_result)\r
+{\r
+    uint32_t ppg_value[PAH_800x_MAX_CH_NUM] = {0};\r
+    uint8_t ppg_overflow = 0;\r
+    uint8_t overflow_num = 0;\r
+    uint16_t ppg_exposure = 0;\r
+    uint16_t ppg_adc = 0;\r
+    uint16_t ppg_frame_period = 0;\r
+    if (!state->ppg_state.is_enabled)\r
+        return PAH_RET_SUCCESS;\r
+\r
+    for(uint8_t ch_num=0; ch_num < PAH_800x_MAX_CH_NUM; ch_num++)\r
+    {\r
+        if(state->ppg_state.ppg_ch_enabled[ch_num])\r
+        {\r
+            pah_800x_hal_read_ppg_sync(&ppg_value[ch_num], ch_num);\r
+            pah_800x_hal_read_ppg_exposure(&ppg_exposure, ch_num);\r
+            pah_800x_hal_read_ppg_frame_period(&ppg_frame_period,ch_num);\r
+            pah_800x_hal_read_ppg_adc(&ppg_adc,ch_num);\r
+            ppg_converging(state, ppg_adc, ch_num);//SD-revise-20191205\r
+            \r
+            ppg_result->data[ch_num] = ppg_value[ch_num];\r
+            ppg_result->exposure_time[ch_num] = ppg_exposure;\r
+            ppg_result->frame_period[ch_num] = ppg_frame_period;\r
+            ppg_result->adc[ch_num] = ppg_adc;\r
+        }        \r
+    }    \r
+    pah_800x_hal_read_ppg_overflow(&ppg_overflow,&overflow_num);\r
+    ppg_result->has_data = true;   \r
+    ppg_result->has_overflow = (ppg_overflow > 0);   \r
+    ppg_result->overflow_num = overflow_num;\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret clear_interrupt(pah_800x *state, bool has_ppg_interrupt, bool has_overflow)\r
+{\r
+\r
+    //pah_800x_hal_write_interrupt_clear();            \r
+    pah_800x_hal_write_interrupt_clear_v2(has_ppg_interrupt); \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret ppg_converging(pah_800x *state, uint32_t ppg_adc, uint8_t ch_num)\r
+{\r
+    if (ch_num >= PAH_800x_MAX_CH_NUM)\r
+        return PAH_RET_INVALID_ARGUMENT;\r
+\r
+    if (!state->config.enable_ppg_convergence[ch_num])\r
+        return PAH_RET_SUCCESS;\r
+\r
+    if (state->config.enable_ppg_reconvergence_if_out_of_bounds[ch_num]\r
+        && !state->ppg_state.is_converging[ch_num]\r
+        && is_touched(state)\r
+        && ppg_value_is_out_of_outer_bounds(state, ppg_adc, ch_num))\r
+    {\r
+        ppg_convergence_toggle(state, true, ch_num);\r
+    }\r
+    else\r
+    {\r
+       state->ppg_state.cur_converging_count[ch_num] = 0;\r
+    }\r
+\r
+    if (!state->ppg_state.is_converging[ch_num])\r
+        return PAH_RET_SUCCESS;\r
+   \r
+    if (ppg_value_is_out_of_inner_bounds(state, ppg_adc, ch_num))\r
+    {\r
+        uint16_t ppg_exposure = 0;\r
+        uint16_t new_ppg_exposure = 0;\r
+\r
+        pah_800x_hal_read_ppg_exposure(&ppg_exposure, ch_num);\r
+        //DEBUG_PRINT("ppg converging[%d] exposure time %d ppg_value %d \n",ch_num, ppg_exposure,ppg_value);\r
+        new_ppg_exposure = select_new_ppg_exposure(state, ppg_exposure, ppg_adc, ch_num);\r
+        if(new_ppg_exposure==ppg_exposure)\r
+        {\r
+            return PAH_RET_SUCCESS;\r
+        }\r
+\r
+        if (new_ppg_exposure > state->config.ppg_convergence[ch_num].t_max)\r
+        {\r
+            new_ppg_exposure = state->config.ppg_convergence[ch_num].t_max;\r
+            ppg_convergence_toggle(state, false, ch_num);\r
+            \r
+            DEBUG_PRINT("ppg converging complete: (exposure, t_max) = (%d)\n", new_ppg_exposure, state->config.ppg_convergence[ch_num].t_max);\r
+        }\r
+        else if (new_ppg_exposure < state->config.ppg_convergence[ch_num].t_min)\r
+        {\r
+            new_ppg_exposure = state->config.ppg_convergence[ch_num].t_min;\r
+            ppg_convergence_toggle(state, false, ch_num);\r
+            \r
+            DEBUG_PRINT("ppg converging complete: (exposure, t_min) = (%d)\n", new_ppg_exposure, state->config.ppg_convergence[ch_num].t_min);\r
+        }\r
+\r
+        pah_800x_hal_write_exposure(new_ppg_exposure, ch_num);\r
+        pah_800x_hal_update_flag();      \r
+        \r
+    }\r
+    else\r
+    {\r
+        ppg_convergence_toggle(state, false, ch_num);\r
+        \r
+        DEBUG_PRINT("ppg converging complete: (low_target, als_lux_sync, high_target) = (%d, %d, %d)\n",\r
+                    state->config.ppg_convergence[ch_num].raw_inner_low_target, ppg_adc,\r
+                    state->config.ppg_convergence[ch_num].raw_inner_high_target);\r
+    }\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static uint16_t select_new_ppg_exposure(pah_800x *state, uint16_t old_ppg_exposure, uint16_t ppg_value, uint8_t ch_num)\r
+{\r
+    int32_t new_ppg_exposure = (int32_t)old_ppg_exposure;\r
+\r
+    if (ppg_value < state->config.ppg_convergence[ch_num].raw_outer_low_bound)\r
+        new_ppg_exposure += state->config.ppg_convergence[ch_num].t_weight_fast_mode;\r
+    else if (ppg_value < state->config.ppg_convergence[ch_num].raw_inner_low_target)\r
+        new_ppg_exposure += state->config.ppg_convergence[ch_num].t_weight_normal_mode;\r
+    else if (ppg_value > state->config.ppg_convergence[ch_num].raw_outer_high_bound)\r
+    {\r
+        if(new_ppg_exposure==state->config.ppg_convergence[ch_num].t_min)\r
+        {\r
+            return new_ppg_exposure;\r
+        }            \r
+        new_ppg_exposure -= state->config.ppg_convergence[ch_num].t_weight_fast_mode;\r
+    \r
+    }else if (ppg_value > state->config.ppg_convergence[ch_num].raw_inner_high_target)\r
+        new_ppg_exposure -= state->config.ppg_convergence[ch_num].t_weight_normal_mode;\r
+\r
+    return new_ppg_exposure;\r
+}\r
+\r
+static bool is_touched(pah_800x *state)\r
+{\r
+    return  state->touch_flag == 1;\r
+}\r
+\r
+static bool is_not_touched(pah_800x *state)\r
+{\r
+    return state->touch_flag == 0;\r
+}\r
+\r
+static bool ppg_value_is_out_of_outer_bounds(pah_800x *state, uint32_t ppg_data, uint8_t ch_num)\r
+{\r
+    return (ppg_data < state->config.ppg_convergence[ch_num].raw_outer_low_bound)\r
+        || (ppg_data > state->config.ppg_convergence[ch_num].raw_outer_high_bound);\r
+}\r
+\r
+static bool ppg_value_is_out_of_inner_bounds(pah_800x *state, uint16_t ppg_data, uint8_t ch_num)\r
+{\r
+    return (ppg_data < state->config.ppg_convergence[ch_num].raw_inner_low_target)\r
+        || (ppg_data > state->config.ppg_convergence[ch_num].raw_inner_high_target);\r
+}\r
+\r
+static pah_ret pah_800x_sw_reset(pah_800x *state)\r
+{\r
+    //set sw reset should not in suspend mode\r
+    if (state->is_powered == false)\r
+        return PAH_RET_FAILED;\r
+\r
+    return pah_800x_hal_write_sw_reset();\r
+}\r
+////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+//===========================================================================\r
+// Private function\r
+//===========================================================================\r
+static pah_ret pah_800x_hal_comm_write(uint8_t addr, const uint8_t *data, size_t write_size)\r
+{\r
+    //return plat->comm.write(&plat->comm, addr, data, write_size);\r
+    //return plat->comm.write(addr, data, write_size);\r
+    return pah_comm_i2c_write(addr, data, write_size);\r
+}\r
+\r
+static pah_ret pah_800x_hal_comm_read(uint8_t addr, uint8_t *data, size_t read_size)\r
+{\r
+\r
+    //return plat->comm.read(&plat->comm, addr, data, read_size);\r
+    return pah_comm_i2c_read(addr, data, read_size);\r
+}\r
+\r
+static pah_ret comm_write(uint8_t addr, uint8_t data)\r
+{\r
+    //return pah_800x_hal_comm_write( addr, &data, 1);\r
+    return pah_800x_hal_comm_write(addr, &data, 1);\r
+}\r
+#define comm_read(addr, data)                     pah_800x_hal_comm_read(addr, data, 1)\r
+#define comm_burst_read(addr, data, read_size)    pah_800x_hal_comm_read(addr, data, read_size)\r
+\r
+\r
+//===========================================================================\r
+// Private function (HAL)\r
+//===========================================================================\r
+static pah_ret pah_800x_hal_write_reg_arr(const pah_reg_arr *reg_arr)\r
+{\r
+    return pah_800x_hal_write_reg_array(reg_arr->reg_arr, reg_arr->reg_arr_len);\r
+}\r
+\r
+static pah_ret pah_800x_hal_write_reg_array(const uint8_t reg_array[][2], size_t length)\r
+{\r
+    size_t i = 0;\r
+    uint8_t reg_value = 0;\r
+    for (i = 0; i < length; ++i)\r
+    {\r
+        //for trim bit\r
+        if (reg_array[i][0] == 0x14)\r
+        {\r
+            comm_read(0x14, &reg_value);\r
+            reg_value = (reg_value & 0x1F) | (reg_array[i][1] & 0xE0);\r
+            comm_write(reg_array[i][0], reg_value);\r
+        }\r
+        else\r
+            comm_write(reg_array[i][0], reg_array[i][1]);\r
+    }\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_write_suspend_state(bool suspend)\r
+{\r
+    uint8_t data = 0;\r
+    DEBUG_PRINT("%s(%d)\n", __func__, suspend);\r
+    if (suspend)\r
+    {\r
+        pah_800x_hal_write_interrupt_clear();\r
+        comm_read(PAH_800x_ADDR_E8, &data);\r
+        PAH_SET_BIT(data, PAH_800x_ADDR_E8_CMD_SUSPEND_MODE_BIT);\r
+        comm_write(PAH_800x_ADDR_E8, data);\r
+    }\r
+    else\r
+    {\r
+        comm_read(PAH_800x_ADDR_E8, &data);\r
+        PAH_CLEAR_BIT(data, PAH_800x_ADDR_E8_CMD_SUSPEND_MODE_BIT);\r
+        comm_write(PAH_800x_ADDR_E8, data);\r
+\r
+    }\r
+    DEBUG_PRINT("%s(%d) end\n", __func__, suspend);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_write_interrupt_clear(void)\r
+{\r
+    uint8_t data = 0;\r
+    // DR interrupt\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+    //PAH_CLEAR_BIT(data, PAH_800x_ADDR_20_BIT_DR_FLAG);\r
+    comm_write(PAH_800x_ADDR_20, (data|0x04));    //SD-revise-20191205\r
+    return PAH_RET_SUCCESS;\r
+}\r
+static pah_ret pah_800x_hal_write_interrupt_clear_v2(bool int_status_DR_FLAG_b)\r
+{\r
+    uint8_t data = 0;\r
+    bool int_status_DR_FLAG = 0;\r
+    // DR interrupt\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+    int_status_DR_FLAG = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_DR_FLAG) ;\r
+    \r
+    if(int_status_DR_FLAG_b==int_status_DR_FLAG)\r
+    {\r
+        comm_write(PAH_800x_ADDR_20, (data|0x04));     //SD-revise-20191205\r
+    }else if((int_status_DR_FLAG_b)==0 &&(int_status_DR_FLAG==1))\r
+    {\r
+        comm_write(PAH_800x_ADDR_20, ((data|0x04)&0xFE));      //SD-revise-20191205\r
+    }\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+\r
+static pah_ret pah_800x_hal_write_ppg_overflow_clear(void)\r
+{\r
+    uint8_t data = 0;\r
+    // Clear ppg_overflow flag\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+    PAH_SET_BIT(data, PAH_800x_ADDR_20_BIT_OVERFLOW_FLAG);\r
+    comm_write( PAH_800x_ADDR_20, data);\r
+    // Recover\r
+    PAH_CLEAR_BIT(data, PAH_800x_ADDR_20_BIT_OVERFLOW_FLAG);\r
+    comm_write(PAH_800x_ADDR_20, data);\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_write_exposure(uint16_t exposure, uint8_t ch_num)\r
+{\r
+    //uint8_t data = 0;\r
+    uint8_t exposure_low = PAH_UINT16_LOW(exposure);\r
+    uint8_t exposure_high = PAH_UINT16_HIGH(exposure);\r
+\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+    {\r
+        comm_write(PAH_800x_ADDR_17, exposure_low);\r
+        comm_write(PAH_800x_ADDR_18, exposure_high);\r
+    }\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+    {\r
+        comm_write(PAH_800x_ADDR_19, exposure_low);\r
+        comm_write(PAH_800x_ADDR_1A, exposure_high);\r
+    }\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+    {\r
+        comm_write(PAH_800x_ADDR_1B, exposure_low);\r
+        comm_write(PAH_800x_ADDR_1C, exposure_high);\r
+    }\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_product_id(uint16_t *product_id)\r
+{\r
+    return comm_burst_read(PAH_800x_ADDR_00_PRODUCT_ID, (uint8_t *)product_id,2);\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_interrupt(uint8_t *ppg_interrupt)\r
+{\r
+    uint8_t data = 0;\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+    if (ppg_interrupt)\r
+        *ppg_interrupt = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_DR_FLAG);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_sync(uint32_t *ppg_data, uint8_t ch_num)\r
+{\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+         comm_burst_read(PAH_800x_ADDR_27_RAWDATA_A_SYNC, (uint8_t*)ppg_data, 3);\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+         comm_burst_read(PAH_800x_ADDR_32_RAWDATA_B_SYNC, (uint8_t*)ppg_data, 3);\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+         comm_burst_read(PAH_800x_ADDR_3D_RAWDATA_C_SYNC, (uint8_t*)ppg_data, 3);\r
+    return PAH_RET_SUCCESS; \r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_overflow(uint8_t *ppg_overflow, uint8_t *overflow_num)\r
+{\r
+    uint8_t data = 0;\r
+    comm_read( PAH_800x_ADDR_20, &data);\r
+    if (ppg_overflow)\r
+    {\r
+        *ppg_overflow = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_OVERFLOW_FLAG);\r
+        *overflow_num = (data&0x70)>>4;\r
+    }\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_exposure(uint16_t *ppg_exposure, uint8_t ch_num)\r
+{\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+        comm_burst_read(PAH_800x_ADDR_2A, (uint8_t*)ppg_exposure, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+        comm_burst_read(PAH_800x_ADDR_35, (uint8_t*)ppg_exposure, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+        comm_burst_read(PAH_800x_ADDR_40, (uint8_t*)ppg_exposure, 2);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_frame_period( uint16_t *ppg_frame_period, uint8_t ch_num)\r
+{\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+        comm_burst_read(PAH_800x_ADDR_2C, (uint8_t*)ppg_frame_period, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+        comm_burst_read(PAH_800x_ADDR_37, (uint8_t*)ppg_frame_period, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+        comm_burst_read(PAH_800x_ADDR_42, (uint8_t*)ppg_frame_period, 2);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_read_ppg_adc(uint16_t *ppg_adc, uint8_t ch_num)\r
+{\r
+    uint16_t data = 0;\r
+\r
+    if(ch_num == PAH_800x_CH_NUM_A)\r
+        comm_burst_read(PAH_800x_ADDR_2E, (uint8_t*)&data, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_B)\r
+        comm_burst_read(PAH_800x_ADDR_39, (uint8_t*)&data, 2);\r
+    else if(ch_num == PAH_800x_CH_NUM_C)\r
+        comm_burst_read(PAH_800x_ADDR_44, (uint8_t*)&data, 2);\r
+    \r
+    //*ppg_adc = data >> 2;\r
+    *ppg_adc = data >> 2;\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_touch_get_touch_flag(int8_t *touch_flag)\r
+{\r
+    uint8_t     data = 0;\r
+    uint16_t    data1 = 0;\r
+//    comm_read(PAH_800x_ADDR_20, &data);\r
+    comm_burst_read(PAH_800x_ADDR_44, (uint8_t*)&data1, 2);\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+    // printf("data : %d, data1 : %d\n",data,data1);\r
+     if (touch_flag)\r
+        *touch_flag = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_TOUCH_FLAG);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+static pah_ret pah_800x_hal_touch_get_touch_info(int8_t *touch_flag,uint16_t *touch_value)\r
+{\r
+    uint8_t    data = 0;\r
+    uint16_t   data1 = 0;\r
+//    comm_read(PAH_800x_ADDR_20, &data);\r
+    comm_burst_read(PAH_800x_ADDR_44, (uint8_t*)&data1, 2);\r
+    *touch_value =data1>>2;\r
+    comm_read(PAH_800x_ADDR_20, &data);\r
+     if (touch_flag)\r
+        *touch_flag = PAH_CHECK_BIT(data, PAH_800x_ADDR_20_BIT_TOUCH_FLAG);\r
+\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_tg_toggle(bool enable)\r
+{\r
+    uint8_t data = 0;\r
+    comm_read( PAH_800x_ADDR_07_TG, &data);\r
+    if(enable)\r
+        PAH_SET_BIT(data, PAH_800x_ADDR_07_TG_BIT_EN);\r
+    else\r
+        PAH_CLEAR_BIT(data, PAH_800x_ADDR_07_TG_BIT_EN);\r
+    comm_write(PAH_800x_ADDR_07_TG, data);\r
+    \r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_update_flag(void)\r
+{   \r
+     comm_write(PAH_800x_ADDR_EB, PAH_800x_ADDR_E8_UPDATE_FLAG);\r
+\r
+     return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_write_sw_reset(void)\r
+{\r
+    comm_write(PAH_800x_ADDR_EE, PAH_800x_ADDR_EE_SW_RESET);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
+\r
+static pah_ret pah_800x_hal_check_enable_channel(pah_800x *state, const pah_reg_arr *reg_arr)\r
+{\r
+    for(int i=0;i<reg_arr->reg_arr_len;i++)\r
+    {\r
+        if(reg_arr->reg_arr[i][0] == PAH_800x_ADDR_11_EnCh)\r
+        {\r
+            uint8_t data = reg_arr->reg_arr[i][1];\r
+            state->ppg_state.ppg_ch_enabled[0] = PAH_CHECK_BIT(data, 0); // CH A\r
+            state->ppg_state.ppg_ch_enabled[1] = PAH_CHECK_BIT(data, 1); // CH B\r
+            state->ppg_state.ppg_ch_enabled[2] = PAH_CHECK_BIT(data, 2); // CH C\r
+        }\r
+    }\r
+        \r
+        return PAH_RET_SUCCESS;\r
+}\r
+\r
+\r
+static pah_ret pah_800x_hal_reset_gpio_state(void)\r
+{\r
+    uint8_t data = 0;\r
+\r
+    comm_read(PAH_800x_ADDR_D2, &data);\r
+    PAH_SET_BIT(data, PAH_800x_ADDR_D2_OD_EnH);\r
+    comm_write(PAH_800x_ADDR_D2, data);\r
+\r
+    return PAH_RET_SUCCESS;\r
+}\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x.h
new file mode 100644 (file)
index 0000000..2500dc6
--- /dev/null
@@ -0,0 +1,158 @@
+#ifndef __pah_800x_h__\r
+#define __pah_800x_h__\r
+\r
+// pah\r
+#include "pah_unit.h"\r
+#include "pah_800x_config.h"\r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+#define TOUCH_TRALSE_VALUE      (-1)\r
+\r
+\r
+//============================================================================\r
+// Type Definition\r
+//============================================================================\r
+typedef struct\r
+{\r
+    uint16_t    t_weight_normal_mode;\r
+    uint16_t    t_weight_fast_mode;\r
+    uint16_t    t_min;\r
+    uint16_t    t_max;\r
+\r
+    uint16_t    raw_outer_high_bound;\r
+    uint16_t    raw_inner_high_target;\r
+    uint16_t    raw_inner_low_target;\r
+    uint16_t    raw_outer_low_bound;\r
+\r
+    uint16_t    convergence_count;\r
+} pah_800x_ppg_convergence;\r
+\r
+typedef struct\r
+{\r
+    uint16_t                    ppg_initial_exposure[PAH_800x_MAX_CH_NUM];\r
+\r
+    bool                        enable_ppg_convergence[PAH_800x_MAX_CH_NUM];\r
+    pah_800x_ppg_convergence    ppg_convergence[PAH_800x_MAX_CH_NUM];\r
+    bool                        enable_ppg_reconvergence_if_out_of_bounds[PAH_800x_MAX_CH_NUM];\r
+\r
+} pah_800x_config;\r
+\r
+typedef struct\r
+{\r
+    bool        is_enabled;\r
+\r
+    bool        is_converging[PAH_800x_MAX_CH_NUM];\r
+    \r
+    bool        ppg_ch_enabled[PAH_800x_MAX_CH_NUM];\r
+    uint16_t    cur_converging_count[PAH_800x_MAX_CH_NUM];\r
+} pah_800x_ppg_state;\r
+\r
+typedef struct\r
+{\r
+    bool        has_data;\r
+    uint32_t    data[PAH_800x_MAX_CH_NUM];\r
+\r
+\r
+    // Avaiable only if has_data is true\r
+    bool        has_overflow;\r
+\r
+    uint8_t     overflow_num;\r
+\r
+    // Avaiable only if has_data is true\r
+    uint16_t    exposure_time[PAH_800x_MAX_CH_NUM];\r
+    uint16_t    adc[PAH_800x_MAX_CH_NUM];\r
+    uint16_t    frame_period[PAH_800x_MAX_CH_NUM];\r
+\r
+} pah_800x_ppg_data;\r
+\r
+typedef struct\r
+{\r
+    bool        is_enabled;  \r
+    \r
+    int8_t        touch_flag;\r
+\r
+} pah_800x_touch_state;\r
+\r
+typedef struct\r
+{\r
+    pah_reg_arr     startup_init;\r
+    pah_reg_arr     ppg_enable;\r
+    pah_reg_arr     touch_enable;\r
+    \r
+} pah_800x_reg_setting;\r
+\r
+typedef struct\r
+{\r
+    // Config\r
+    //pah_plat            plat;\r
+    pah_800x_config         config;\r
+\r
+    // Power state\r
+    bool                    is_powered;\r
+\r
+    // PPG state\r
+    pah_800x_ppg_state      ppg_state;\r
+    pah_800x_ppg_data       ppg_result;\r
+\r
+    // TOUCH state\r
+    pah_800x_touch_state    touch_state;\r
+    int8_t                  touch_flag;\r
+    uint16_t                           touch_value;\r
+    // Other\r
+    pah_800x_reg_setting    reg_setting;\r
+\r
+} pah_800x;\r
+\r
+\r
+//============================================================================\r
+// Public function\r
+//============================================================================\r
+#ifdef __cplusplus\r
+extern  "C" {\r
+#endif \r
+\r
+\r
+// Info\r
+uint16_t    pah_800x_get_i2c_default_slave_addr(void);\r
+void        pah_800x_get_default_config(pah_800x_config *config);\r
+pah_ret     pah_800x_get_product_id( uint16_t *product_id);    \r
+\r
+// Init\r
+pah_ret     pah_800x_init(pah_800x *state, const pah_800x_config *config);\r
+pah_ret     pah_800x_deinit(pah_800x *state);\r
+\r
+// Device init\r
+pah_ret     pah_800x_device_init(pah_800x *state, const pah_800x_reg_setting *reg_setting);\r
+\r
+// Config\r
+//pah_ret     pah_800x_set_ppg_convergence(pah_800x *state,uint8_t ch_num, const pah_800x_ppg_convergence *ppg_convergence);\r
+\r
+// Power\r
+pah_ret     pah_800x_power_toggle(pah_800x *state, bool enable);\r
+\r
+// Basic verification\r
+pah_ret     pah_800x_verify_product_id(pah_800x *state, uint16_t *product_id);\r
+\r
+// PPG\r
+pah_ret     pah_800x_ppg_toggle(pah_800x *state, bool enable);\r
+pah_ret     pah_800x_ppg_get_data(pah_800x *state, pah_800x_ppg_data *ppg_data);\r
+\r
+// TOUCH\r
+pah_ret     pah_800x_touch_toggle(pah_800x *state, bool enable);\r
+pah_ret     pah_800x_get_touch_flag(pah_800x *state, int8_t *touch_flag);\r
+pah_ret     pah_800x_get_touch_value(pah_800x *state, uint16_t *touch_value);\r
+pah_ret     pah_800x_update_touch_setting(pah_800x *state);\r
+\r
+// Task\r
+pah_ret     pah_800x_task(pah_800x *state);\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h
new file mode 100644 (file)
index 0000000..0e3d853
--- /dev/null
@@ -0,0 +1,163 @@
+#ifndef __pah_800x_config_h__\r
+#define __pah_800x_config_h__\r
+\r
+// pah\r
+#include "pah800x_bsp.h"\r
+#include "debug_print.h"\r
+\r
+/*\r
+ * Select LED Supplier\r
+ * If Use new Supplier LED , Need to define LED_SUPPLIER_NEW\r
+*/\r
+//#define LED_SUPPLIER_NEW\r
+\r
+\r
+/*\r
+ * Select Cover Type\r
+*/\r
+#define  DI_WALL_4mm\r
+//#define  PC_4mm\r
+\r
+/*\r
+ * Select HW and ALG configuration\r
+ * PC_4MM_2G_IR_HRD : Printing Cover with 4mm 2 Green and 1 IR LED for HRD algorithm use (PAH8009ES)\r
+ * DIW_4MM_G_IR_HRD : DI+Wall Cover with 4mm 1 Green and 1 IR LED for HRD algorithm use (PAH8009ES)\r
+ * DIW_4MM_IR_R_IR_SPO2 : DI+Wall Cover with 4mm 1 IR LED and 1 RED for SpO2 algorithm use (PAH8009ES)\r
+ * This definition will enable the PPG register setting corresponding to different HW and ALG configuration\r
+ */\r
+\r
+#define PC_4MM_2G_IR_HRD    1\r
+#define DIW_4MM_G_IR_HRD          1\r
+#define DIW_4MM_IR_R_IR_SPO2    1\r
+\r
+//#endif\r
+\r
+//============================================================================\r
+// Debug Option\r
+//============================================================================\r
+#define ENABLE_AE 1\r
+#define ENABLE_AE_RECONVERGENCE 1\r
+\r
+\r
+// #define PAH_800x_ENABLE_DEBUG_PRINT\r
+// #define PAH_800x_ENABLE_LOG_PRINT\r
+\r
+#ifdef PAH_800x_ENABLE_LOG_PRINT\r
+#define LOG_PRINT(fmt, ...)                    \\r
+    do {                                      \\r
+        PRINT(fmt" ", ##__VA_ARGS__);     \\r
+    } while (0)\r
+#else\r
+#define LOG_PRINT(...) do {} while (0)\r
+#endif\r
+#ifdef PAH_800x_ENABLE_DEBUG_PRINT\r
+#define DEBUG_PRINT(fmt, ...)                    \\r
+    do {                                      \\r
+        PRINT(fmt" ", ##__VA_ARGS__);     \\r
+    } while (0) \r
+#else\r
+#define DEBUG_PRINT(...) do {} while (0)\r
+#endif\r
+\r
+/*\r
+ * Select Interrupt or Polling Mode\r
+ * This definition will enable the corresponding demo functionin main.c\r
+ * If select INT mode, then slect following INT configuration type\r
+ */\r
+#define INTERRUPT_MODE      1\r
+#define POLLING_MODE        0\r
+#define Test_pattern_mode   0\r
+\r
+/*\r
+ * Select INT HW configuration type\r
+ * INT_OD_EXTERNAL_PULLH : INT open-drain type with external pull-high resistor\r
+ * INT_OD_INTERNAL_PULLH : INT open-drain type with internal pull-high resistor\r
+ * INT_PUP_WITHOUT_PULLH : INT push-pull type without any pull-high resistor\r
+ * If user select POLLING_MODE, all define need to set 0\r
+ * This definition will enable the GPIO register setting corresponding to different INT HW configuration\r
+ */\r
+#define INT_OD_EXTERNAL_PULLH   1\r
+#define INT_OD_INTERNAL_PULLH   0\r
+#define INT_PUP_WITHOUT_PULLH   0\r
+\r
+\r
+/*\r
+* Configure VBUS Type\r
+ * Define VBUS_18V=1, compatible with VBUS=1.8V or 3.3V (default)\r
+ * Define VBUS_18V=0, only support VBUS=3.3V\r
+ * If user want to define VBUS_18V=0, or VBUS not 1.8V/3.3V, please contact with PixArt for evaluation\r
+ */\r
+#define VBUS_18V    1\r
+#if (VBUS_18V)\r
+    #define R_GPIO_0_OD_EnH        (0x20)\r
+    #define R_GPIO_SLEW            (0x01)\r
+    #define R_I2C_SLEW             (0x40)\r
+    #define R_SCL_Sel            (0x00)\r
+    #define R_SDA_Sel            (0x00)\r
+#else\r
+    #define R_GPIO_0_OD_EnH        (0x20)\r
+    #define R_GPIO_SLEW             0\r
+    #define R_I2C_SLEW              0\r
+    #define R_SCL_Sel            (0x40)\r
+    #define R_SDA_Sel            (0x04)\r
+#endif\r
+\r
+#define Time_Interval             400\r
+/*\r
+If Customer platform use G-Sensor with FIFO,they can refer this flow to run pxi alg to get alg output\r
+*/\r
+//#define PPG_MEMS_Synchronize\r
+#define Optimize_SPO2_flow\r
+\r
+//****** Demo 800X mode Select ******//\r
+//============HRD-INT================//\r
+//#define touch_only_hrd_en\r
+//#define ppg_only_hrd_en\r
+#define auto_hrd_en\r
+\r
+//============HRD-Polling================//\r
+//#define touch_only_polling_hrd_en\r
+//#define ppg_only_polling_hrd_en\r
+//#define auto_polling_hrd_en\r
+\r
+\r
+//============SPO2-INT================//\r
+//#define touch_only_spo2_en\r
+//#define ppg_only_spo2_en\r
+//#define auto_spo2_en\r
+\r
+//============SPO2-Polling================//\r
+//#define touch_only_polling_spo2_en\r
+//#define ppg_only_polling_spo2_en\r
+//#define auto_polling_spo2_en\r
+\r
+\r
+//============Stress-INT================//\r
+//#define touch_only_stress_en\r
+//#define ppg_only_stress_en\r
+//#define auto_stress_en\r
+\r
+//============Stress-Polling================//\r
+//#define touch_only_polling_stress_en\r
+//#define ppg_only_polling_stress_en\r
+//#define auto_polling_stress_en\r
+\r
+//=========== Test_pattern======== //\r
+//#define hrd_testpattern_en\r
+//#define spo2_testpattern_en\r
+\r
+//=========== Factory _Test=========//\r
+//#define factory_test_en\r
+\r
+\r
+//============HRD-INT====PC Cover============//\r
+//#define touch_only_hrd_en_pc\r
+//#define ppg_only_hrd_en_pc\r
+//#define auto_hrd_en_pc\r
+\r
+//============HRD-Polling======PC Cover==========//\r
+//#define touch_only_polling_hrd_en_pc\r
+//#define ppg_only_polling_hrd_en_pc\r
+//#define auto_polling_hrd_en_pc\r
+\r
+#endif  // header guard\r
diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_unit.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_unit.h
new file mode 100644 (file)
index 0000000..64a1a7e
--- /dev/null
@@ -0,0 +1,340 @@
+#ifndef __pah_unit_h__\r
+#define __pah_unit_h__\r
+\r
+// c\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+#include <stddef.h>\r
+#include <string.h>\r
+#include <stdarg.h>\r
+#include <stdlib.h>\r
+\r
+\r
+//============================================================================\r
+// Default\r
+//============================================================================\r
+#define PAH_800x_DEFAULT_PPG_INITIAL_EXPOSURE       (400)\r
+\r
+#define PAH_800x_DEFAULT_ENABLE_PPG_CONVERGENCE     true\r
+\r
+\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_COUNT                                 (0)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_T_WEIGHT_NORMAL_MODE   (8)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_T_WEIGHT_FAST_MODE     (16)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_T_MIN                  (10)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_T_MAX                  (1792)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_OUTER_HIGH_BOUND   (12288)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_INNER_HIGH_TARGET  (10240)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_INNER_LOW_TARGET   (8192)\r
+#define PAH_800x_DEFAULT_PPG_CONVERGENCE_RAW_OUTER_LOW_BOUND    (6144)\r
+\r
+#define PAH_800x_DEFAULT_ENABLE_PPG_RECONVERGENCE_IF_OUT_OF_BOUNDS  true\r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+\r
+// I2C 7-bit ID\r
+#define PAH_800x_DEFAULT_I2C_SLAVE_ID_1  (0x40)\r
+#define PAH_800x_DEFAULT_I2C_SLAVE_ID_2  (0x10)\r
+\r
+#define  PAH_800x_PRODUCT_ID        (0x8008)\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/**\r
+ * @file pah_ret.h\r
+ *\r
+ * Copyright (c) 2016-2018 PixArt Imaging Inc.\r
+ * All Rights Reserved.\r
+ * Confidential and Proprietary - PixArt Imaging Inc.\r
+ **/\r
+\r
+typedef enum {\r
+\r
+    PAH_RET_SUCCESS = 0,            // Success\r
+    \r
+    PAH_RET_PENDING,\r
+\r
+    PAH_RET_FAILED,                 // Unknown error, generally there exists bug in this driver\r
+\r
+    PAH_RET_PLAT_FAILED,            // Platform API failed\r
+    PAH_RET_VERIFY_FAILED,          // Verify device failed\r
+\r
+    PAH_RET_NOT_IMPLEMENTED,        // This API is not supported or is not implemented\r
+\r
+    PAH_RET_INVALID_ARGUMENT,       // Invalid argument to API\r
+    PAH_RET_INVALID_OPERATION,      // This operation is not available at this time\r
+\r
+    PAH_RET_FIFO_CKS_FAILED,        // Failed to compare check sum with fifo data\r
+    PAH_RET_FIFO_OVERFLOW,          // Fifo in device is overflow\r
+\r
+    PAH_RET_ASYNC_PENDING,\r
+\r
+} pah_ret;\r
+\r
+typedef enum {\r
+    PAH_800x_CH_NUM_A = 0,\r
+    PAH_800x_CH_NUM_B,\r
+    PAH_800x_CH_NUM_C,\r
+    PAH_800x_MAX_CH_NUM,\r
+} pah_800x_ch_num;\r
+\r
+#define PAH_SUCCEEDED(ret)              (ret == PAH_RET_SUCCESS)\r
+#define PAH_FAILED(ret)                 (!PAH_SUCCEEDED(ret))\r
+\r
+\r
+#define PAH_CHECK_RET(ret) \\r
+    if (PAH_FAILED(ret)) { \\r
+        return ret; \\r
+    }\r
+\r
+#define PAH_CHECK_NULL(p) \\r
+    if (!p) { \\r
+        return PAH_RET_INVALID_ARGUMENT; \\r
+    }\r
+\r
+\r
+\r
+/**\r
+ * @file pah_plat.h\r
+ *\r
+ * Copyright (c) 2016-2018 PixArt Imaging Inc.\r
+ * All Rights Reserved.\r
+ * Confidential and Proprietary - PixArt Imaging Inc.\r
+ **/\r
+\r
+\r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+\r
+//============================================================================\r
+// Macro\r
+//============================================================================\r
+#ifndef __FILENAME__\r
+#   define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)\r
+#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+/**\r
+ * @file pah_util.h\r
+ *\r
+ * Copyright (c) 2016-2018 PixArt Imaging Inc.\r
+ * All Rights Reserved.\r
+ * Confidential and Proprietary - PixArt Imaging Inc.\r
+ **/\r
+\r
+\r
+\r
+#define PAH_ARRAY_SIZE(arr)         (sizeof(arr) / sizeof(arr[0]))\r
+\r
+#define PAH_SET_BIT(var,pos)        do { ((var) |= (1 << (pos))); } while(0)\r
+#define PAH_CLEAR_BIT(var,pos)      do { ((var) &= ~(1 << (pos))); } while(0)\r
+#define PAH_CHECK_BIT(var,pos)      (((var) >> (pos)) & 1)\r
+\r
+//\r
+// PAH_SET_BITSLICE\r
+//\r
+// ex1:\r
+//      // var    = 0x00 : 00000000\r
+//      // pos    = 2    :      ^\r
+//      // mask   = 0x3C : 00111100\r
+//      // value  = 0x0D :   1101\r
+//      // ret    = 0x34 : 00110100\r
+//      uint8_t data = 0x00;\r
+//      uint8_t ret = PAH_SET_BITSLICE(data, 2, 0x3C, 0x0D);\r
+//\r
+// ex2:\r
+//      // var    = 0x6D : 01101101\r
+//      // pos    = 6    :  ^\r
+//      // mask   = 0xC0 : 11000000\r
+//      // value  = 0x02 : 10\r
+//      // ret    = 0xAD : 10101101\r
+//      uint8_t data = 0x6D;\r
+//      uint8_t ret = PAH_SET_BITSLICE(data, 6, 0xC0, 0x02);\r
+//\r
+#define PAH_SET_BITSLICE(var, pos, mask, value) \\r
+    ((var & ~mask) | ((value << pos) & mask))\r
+\r
+//\r
+// PAH_GET_BITSLICE\r
+//\r
+// ex1:\r
+//      // var    = 0x5D : 01011101\r
+//      // pos    = 2    :      ^\r
+//      // mask   = 0x3C : 00111100\r
+//      // ret    = 0x07 :   0111\r
+//      uint8_t ret = PAH_GET_BITSLICE(0x5D, 2, 0x3C);\r
+//\r
+// ex2:\r
+//      // var    = 0xA6 : 10100110\r
+//      // pos    = 5    :   ^\r
+//      // mask   = 0xE0 : 11100000\r
+//      // ret    = 0x05 : 101\r
+//      uint8_t ret = PAH_GET_BITSLICE(0xA6, 5, 0xE0);\r
+//\r
+#define PAH_GET_BITSLICE(var, pos, mask) \\r
+    ((var & mask) >> pos)\r
+\r
+#define PAH_UINT64_HIGH(var)        ((uint32_t)(var >> 32))\r
+#define PAH_UINT64_LOW(var)         ((uint32_t)(var & UINT32_MAX))\r
+\r
+#define PAH_UINT16_HIGH(var)        ((uint8_t)(var >> 8))\r
+#define PAH_UINT16_LOW(var)         ((uint8_t)(var & UINT8_MAX))\r
+\r
+#define PAH_UNUSED_VAR(var)         (void)(var)\r
+#define UNUSED_VAR(var)         (void)(var)\r
+  \r
+#ifndef __FILENAME__\r
+#   define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)\r
+#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/**\r
+ * @file pah_reg.h\r
+ *\r
+ * Copyright (c) 2016-2018 PixArt Imaging Inc.\r
+ * All Rights Reserved.\r
+ * Confidential and Proprietary - PixArt Imaging Inc.\r
+ **/\r
+\r
+\r
+\r
+\r
+//============================================================================\r
+// Definition\r
+//============================================================================\r
+typedef const uint8_t (pah_reg)[2];\r
+\r
+\r
+typedef struct {\r
+\r
+    pah_reg     *reg_arr;\r
+    uint32_t     reg_arr_len;\r
+    \r
+} pah_reg_arr;\r
+\r
+\r
+#define PAH_REG_ARR_SETUP(pah_reg_arr, reg_array) \\r
+    do { \\r
+        pah_reg_arr.reg_arr     = (pah_reg*)reg_array; \\r
+        pah_reg_arr.reg_arr_len = PAH_ARRAY_SIZE(reg_array); \\r
+    } while(0)\r
+\r
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//============================================================================\r
+// Register address\r
+//============================================================================\r
+\r
+/*#define PAH_800x_ADDR_00_PRODUCT_ID                     (0x00)\r
+#define PAH_800x_ADDR_03                              (0x03)\r
+#define PAH_800x_ADDR_03_BIT_R_PS_EN                    (0)\r
+#define PAH_800x_ADDR_03_BIT_R_ALS_EN                   (1)\r
+#define PAH_800x_ADDR_03_BIT_SW_SUSPEND                 (5)\r
+\r
+#define PAH_800x_ADDR_04                                (0x04)\r
+#define PAH_800x_ADDR_04_BIT_ALS_OVERFLOW_ECO           (7)\r
+\r
+#define PAH_800x_ADDR_09                                (0x09)\r
+#define PAH_800x_ADDR_09_BIT_ALS_INTERRUPT              (2)\r
+#define PAH_800x_ADDR_09_BIT_PS_INTERRUPT               (5)\r
+#define PAH_800x_ADDR_09_BIT_PS_APPROACH                (6)\r
+\r
+#define PAH_800x_ADDR_10_PS_ONOFF_SYNC                  (0x10)\r
+\r
+#define PAH_800x_ADDR_11                                (0x11)\r
+#define PAH_800x_ADDR_11_BIT_R_LED_CONTROL_OUT_EN       (4)\r
+#define PAH_800x_ADDR_11_BIT_R_PS_INTERRUPT_EN          (7)\r
+\r
+#define PAH_800x_ADDR_0E_ALS_LUX_SYNC                   (0x0E)\r
+\r
+#define PAH_800x_ADDR_34                                (0x34)\r
+#define PAH_800x_ADDR_34_BIT_R_EXPOSURE_ALS_F0          (0)\r
+\r
+#define PAH_800x_ADDR_35                                (0x35)\r
+#define PAH_800x_ADDR_35_BIT_R_EXPOSURE_ALS_F0          (0)\r
+\r
+#define PAH_800x_ADDR_38                                (0x38)\r
+#define PAH_800x_ADDR_38_BIT_0_LOCK_EXPOTIME            (0)\r
+#define PAH_800x_ADDR_38_BIT_1_CLEAR_ALS_OVERFLOW_ECO   (1)\r
+\r
+#define PAH_800x_ADDR_EC                                (0xEC)\r
+#define PAH_800x_ADDR_EC_BIT_7_R_CLK_MANUAL             (7)*/\r
+\r
+#define PAH_800x_ADDR_00_PRODUCT_ID                     (0x00)\r
+\r
+#define PAH_800x_ADDR_07_TG                             (0X07)\r
+#define PAH_800x_ADDR_07_TG_BIT_EN                      (0)\r
+\r
+#define PAH_800x_ADDR_20                                (0x20)\r
+#define PAH_800x_ADDR_20_BIT_DR_FLAG                    (0)\r
+#define PAH_800x_ADDR_20_BIT_OVERFLOW_FLAG              (1)\r
+#define PAH_800x_ADDR_20_BIT_TOUCH_FLAG                 (2)\r
+\r
+//expo A Sync\r
+#define PAH_800x_ADDR_2A                                (0x2A)\r
+#define PAH_800x_ADDR_2B                                (0x2B)\r
+\r
+#define PAH_800x_ADDR_35                                (0x35)\r
+#define PAH_800x_ADDR_36                                (0x36)\r
+\r
+#define PAH_800x_ADDR_40                                (0x40)\r
+#define PAH_800x_ADDR_41                                (0x41)\r
+\r
+#define PAH_800x_ADDR_11_EnCh                           (0x11)\r
+\r
+//expo A write\r
+#define PAH_800x_ADDR_17                                (0x17)\r
+#define PAH_800x_ADDR_18                                (0x18)\r
+\r
+#define PAH_800x_ADDR_19                                (0x19)\r
+#define PAH_800x_ADDR_1A                                (0x1A)\r
+\r
+#define PAH_800x_ADDR_1B                                (0x1B)\r
+#define PAH_800x_ADDR_1C                                (0x1C)\r
+\r
+//frame period\r
+\r
+#define PAH_800x_ADDR_2C                                (0x2C)\r
+#define PAH_800x_ADDR_2D                                (0x2D)\r
+\r
+#define PAH_800x_ADDR_37                                (0x37)\r
+#define PAH_800x_ADDR_38                                (0x38)\r
+\r
+#define PAH_800x_ADDR_42                                (0x42)\r
+#define PAH_800x_ADDR_43                                (0x43)\r
+\r
+//adc\r
+\r
+#define PAH_800x_ADDR_2E                                (0x2E)\r
+#define PAH_800x_ADDR_2F                                (0x2F)\r
+\r
+#define PAH_800x_ADDR_39                                (0x39)\r
+#define PAH_800x_ADDR_3A                                (0x3A)\r
+\r
+#define PAH_800x_ADDR_44                                (0x44)\r
+#define PAH_800x_ADDR_45                                (0x45)\r
+\r
+#define PAH_800x_ADDR_27_RAWDATA_A_SYNC                 (0x27)\r
+#define PAH_800x_ADDR_32_RAWDATA_B_SYNC                 (0x32)\r
+#define PAH_800x_ADDR_3D_RAWDATA_C_SYNC                 (0x3D)\r
+\r
+#define PAH_800x_ADDR_E8                                (0xE8)\r
+#define PAH_800x_ADDR_E8_CMD_SUSPEND_MODE_BIT           (0)\r
+\r
+#define PAH_800x_ADDR_EB                                (0xEB)\r
+#define PAH_800x_ADDR_E8_UPDATE_FLAG                    (0x80)\r
+\r
+#define PAH_800x_ADDR_EE                                (0xEE)\r
+#define PAH_800x_ADDR_EE_SW_RESET                       (0x1F)//(0x07)\r
+#define PAH_800x_ADDR_D2                                (0xD2)\r
+#define PAH_800x_ADDR_D2_OD_EnH                        (5)\r
+\r
+#endif  // header guard\r
index 939918e..9b47c20 100644 (file)
@@ -41,15 +41,26 @@ extern "C" {
 #include "cmsis_os2.h"
 #include "ppg_service.h"
 #include "los_printf.h"
-
-
-#include "hx3695_hal.h"
+#include "thread_init.h"
 #include "custom_utils.h"
-#include "cywee_hal.h"
-#include "cywee_service.h"
-#include "custom_runtime.h"
 #include "custom_save_runtime.h"
-#include "hx3695_factory_test.h"
+#include "ppg_hal.h"
+
+#ifdef PPG_HX3695
+#include "hx3695.h"
+#endif
+
+#if defined(PPG_VC9202)
+#include "vc9202_hal.h"
+#include "vc9202_user.h"
+#elif  defined(PPG_VC921X)
+#include "vc921x_hal.h"
+#include "vc921x_user_app.h"
+#elif  defined(PPG_GH3X2X)
+#include "gh3x2x_hal.h"
+#include "gh3x2x_afe_drv.h"
+#else
+#endif
 
 static bool g_ppg_service_initialled = false;
 
@@ -79,36 +90,6 @@ void set_keep_in_wear_det_mode(uint8_t mod)
     keep_in_wear_det_mod = mod;
 }
 
-//漏光测试
-errcode_t update_leaklight_event_notify(uint8_t *data)
-{
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "send lightdata to ui %s",data);
-    CustomEventPublish(TOPIC_EVENT_LEAKLIGHT_UPDATA,(uint8_t*)data,strlen((char*)data));
-    return 0;
-}
-errcode_t update_leaklight_event_sendmsg_toUI(uint8_t *data)
-{
-    /**通过UI事件发送Notify*/
-    GraphicService::GetInstance()->PostGraphicEvent(std::bind(update_leaklight_event_notify, data));
-    return ERRCODE_SUCC;
-}
-
-
-//灰卡测试
-errcode_t update_graycard_event_notify(uint8_t *data)
-{
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "send carddata to ui %s",data);
-    CustomEventPublish(TOPIC_EVENT_GRAYCARD_UPDATA,(uint8_t*)data,strlen((char*)data));
-    return 0;
-}
-errcode_t update_graycard_event_sendmsg_toUI(uint8_t *data)
-{
-    /**通过UI事件发送Notify*/
-    GraphicService::GetInstance()->PostGraphicEvent(std::bind(update_graycard_event_notify, data));
-    return ERRCODE_SUCC;
-}
-
-
 //血氧
 errcode_t update_spo2_event_notify(uint8_t spo2)
 {
@@ -162,58 +143,33 @@ errcode_t update_static_hrs_event_sendmsg_toUI(int32_t hrs)
     return ERRCODE_SUCC;
 }
 
-#include "hx3695_hal.h"
-#include "hx3695.h"
-void hx3695_msg_callback(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen)
+void ppg_msg_callback(uint8_t msg_type, uint8_t *msg_data, int32_t msg_datalen)
 {
-    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "hx3695_msg_callback");
-    FT_CUSTOM_RESULTS_t sensor_data; // 使用更通用的名称 sensor_data
-#if 1
-    if (msg_datalen < sizeof(FT_CUSTOM_RESULTS_t)) {
-        // 数据长度不足以填充整个结构体
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Invalid data length for SPO2 update");
-        //return;
-    }
-#endif
-    memcpy(&sensor_data, msg_data, sizeof(FT_CUSTOM_RESULTS_t));
+    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "ppg_msg_callback");
+
+    if(msg_datalen > 1 || msg_data == NULL)
+        return;
+
     switch(msg_type)
     {
-        case HX3695_MSG_TYPE_HRS_UPDATE:
+        case PPG_MSG_TYPE_HRS_UPDATE:
            //每秒心率
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_HRS_UPDATE = %d", sensor_data.lastesthrs);
-            update_hrs_event_sendmsg_toUI(sensor_data.lastesthrs);
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_HRS_UPDATE = %d", *msg_data);
+            update_hrs_event_sendmsg_toUI(*msg_data);
             break;
-        case HX3695_MSG_TYPE_HRV_UPDATE:
+        case PPG_MSG_TYPE_HRV_UPDATE:
             break;
-        case HX3695_MSG_TYPE_SPO2_UPDATE:
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_SPO2_UPDATE = %d", sensor_data.lastestspo2);
-            update_spo2_event_sendmsg_toUI(sensor_data.lastestspo2);
+        case PPG_MSG_TYPE_SPO2_UPDATE:
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_SPO2_UPDATE = %d", *msg_data);
+            update_spo2_event_sendmsg_toUI(*msg_data);
             break;
-        case HX3695_MSG_TYPE_LEAKLIGHT_UPDATE:
-            memset_s(light_databuf,64,0,64);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "LEAKLIGHT_UPDATE");
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_leak_green_UPDATE = %d", sensor_data.leak_green);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_leak_red_UPDATE = %d", sensor_data.leak_red);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_leak_ir_UPDATE = %d", sensor_data.leak_ir);
-            sprintf((char *)light_databuf,"%d,%d,%d",sensor_data.leak_green,sensor_data.leak_red,sensor_data.leak_ir);
-            update_leaklight_event_sendmsg_toUI(light_databuf);
+        case PPG_MSG_TYPE_WEARSTAT_UPDATE:
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_WEARSTATUS_UPDATE = %d", *msg_data);
+            update_wearstatus_event_sendmsg_toUI(*msg_data);
             break;
-        case HX3695_MSG_TYPE_GRAYCARD_UPDATE:
-            memset_s(card_databuf,64,0,64);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "GRAYCARD_UPDATE");
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_card_green_UPDATE = %d", sensor_data.card_green);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_card_red_UPDATE = %d", sensor_data.card_red);
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_card_ir_UPDATE = %d", sensor_data.card_ir);
-            sprintf((char *)card_databuf,"%d,%d,%d",sensor_data.card_green,sensor_data.card_red,sensor_data.card_ir);
-            update_graycard_event_sendmsg_toUI(card_databuf);
-            break;
-        case HX3695_MSG_TYPE_WEARSTAT_UPDATE:
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_WEARSTATUS_UPDATE = %d", sensor_data.wearstatus);
-            update_wearstatus_event_sendmsg_toUI(sensor_data.wearstatus);
-            break;
-        case HX3695_MSG_TYPE_STATIC_HRS_UPDATE:
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_STATIC_HRS_UPDATE = %d", sensor_data.lastesthrs);
-            update_static_hrs_event_sendmsg_toUI(sensor_data.lastesthrs);
+        case PPG_MSG_TYPE_STATIC_HRS_UPDATE:
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "HX3695_MSG_TYPE_STATIC_HRS_UPDATE = %d", *msg_data);
+            update_static_hrs_event_sendmsg_toUI(*msg_data);
             break;
         default:
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Unknown sensor message type");
@@ -244,6 +200,8 @@ errcode_t send_ppg_cmd_msg(int cmd)
         return OSAL_FAILURE;
     }
 
+    // PRINT("cmd : 0x%x\n",cmd);
+
     PPG_CMD_TYPE_T mail = 0;
     mail = cmd;
     ret = osal_msg_queue_write_copy(g_app_queue, (void *)&mail,
@@ -278,14 +236,25 @@ static void ppg_service_check_task(void  *arg)
         }
         char* cmd = "hrs";
         int enable = 1;
-        if (mail == PPG_SERVICE_CMD_TYPE_DO_PPG_320TIMER_CALLBACK){
-            heart_rate_meas_timeout_handler(NULL);
+        if (mail == PPG_SERVICE_CMD_TYPE_DO_PPG_HRS_TIMER_CALLBACK){
+// #ifdef PPG_HX3695
+//         heart_rate_meas_timeout_handler(NULL);
+// #endif
+            // ppg_hrs_timer_handler();
+            ppg_timer_handler(HRS_TIMER_MODE);
             continue;
-        }else if (mail == PPG_SERVICE_CMD_TYPE_DO_PPG_40TIMER_CALLBACK){
-            agc_timeout_handler(NULL);
+        }else if (mail == PPG_SERVICE_CMD_TYPE_DO_PPG_AGC_TIMER_CALLBACK){
+// #ifdef PPG_HX3695
+//             agc_timeout_handler(NULL);
+// #endif
+            ppg_timer_handler(AGC_TIMER_MODE);
             continue;
-        }else if(mail == PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_5000TIMER_CALLBACK){
-            wear_mode_timeout_handler(NULL);
+        }else if(mail == PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_TIMER_CALLBACK){
+// #ifdef PPG_HX3695
+//             wear_mode_timeout_handler(NULL);
+// #endif
+            // ppg_wear_timer_handler();
+            ppg_timer_handler(WEAR_TIMER_MODE);
             continue;
         }else if (mail == PPG_SERVICE_CMD_TYPE_DO_PPG_TEST){
             //do_cywee_service_check_msg(CYWEE_SERVICE_CMD_OPEN_GET_ACC,NULL);
@@ -311,7 +280,7 @@ static void ppg_service_check_task(void  *arg)
             cmd = "graycard";
             enable = 1;
         }else if (mail == PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_TEST){
-            if (keep_in_wear_det_mod == 0) continue;;
+            if (keep_in_wear_det_mod == 0) continue;
             uapi_save_runtime_log(RUNTIME_LOG_WEAR_MIN_START);
             cmd = "wear";
             enable = 1;
@@ -343,13 +312,45 @@ static void ppg_service_check_task(void  *arg)
         }
         else if (mail == PPG_SERVICE_CMD_TYPE_OPEN_HRS_BLE)
         {
+#ifdef PPG_HX3695
             hx3695_set_hrs_ble_swtich(1);
+#endif
             continue ;
         }
         else if (mail == PPG_SERVICE_CMD_TYPE_CLOSE_HRS_BLE)
         {
+#ifdef PPG_HX3695
             hx3695_set_hrs_ble_swtich(0);
+#endif
             continue ;
+        }else if (mail == PPG_SERVICE_CMD_TYPE_INT_HANDLER){
+// #ifdef PPG_VC9202
+//             vc9202_usr_interrupt_handler(SPORT_TYPE_NORMAL,0);
+// #elif defined PPG_VC921X
+//             cmd = "int";
+//             enable = 1;
+//             ppg_send_cmd_to_vc921x_driver(cmd,enable);
+// #elif defined PPG_GH3X2X
+//             hal_gh3x2x_afe_int_handler_call_back();
+//             GH3X2X_AFE_ChipPro();
+// #elif defined PPG_PAH8009
+//             hal_gh3x2x_afe_int_handler_call_back();
+//             GH3X2X_AFE_ChipPro();
+// #endif
+            ppg_int_handler();
+            continue;
+        }
+        else if (mail == PPG_SERVICE_CMD_TYPE_FPC_TEST){
+#ifdef PPG_VC9202
+            cmd = "fpc";
+            enable = 1;
+#endif
+        }
+        else if (mail == PPG_SERVICE_CMD_TYPE_FACTORY_TEST){
+#ifdef PPG_VC9202
+            cmd = "factory";
+            enable = 1;
+#endif
         }
         if (ppg_service_running_stat == true && enable ==1 )
         {
@@ -360,8 +361,9 @@ static void ppg_service_check_task(void  *arg)
             PRINT_ERR("ppg service already stopped! \r\n");
             continue ;
         }
-#ifdef PPG_HX3695
-       ppg_send_cmd_to_driver(cmd,enable);
+
+    ppg_send_cmd_to_driver(cmd,enable);
+
     if(enable == 1)
         ppg_service_running_stat = true;
     else
@@ -376,9 +378,6 @@ static void ppg_service_check_task(void  *arg)
             ppg_service_running_stat = true;
         }
     }
-#endif
-
-        
     }
 }
 void create_ppg_queue(void)
@@ -390,39 +389,37 @@ void create_ppg_queue(void)
 }
 errcode_t uapi_ppg_service_init(void)
 {
-   
-
     PRINT("uapi_ppg_service_init !\r\n");
 
+    ppg_power_on();
 
-
-#ifdef PPG_HX3695
-    tyhx_poweron();
-    if ( hx3695_chip_check() == false)
+    if (ppg_get_chip_id() != PPG_CHIP_ID)
     {
-        tyhx_poweroff();
+        ppg_power_off();
         LOS_Mdelay(10);
-        tyhx_poweron();
-        if ( hx3695_chip_check() == false)
+        ppg_power_on();
+
+        if (ppg_get_chip_id() != PPG_CHIP_ID)
         {
-            //TODO 没找到3695,退出线程
-            PRINT("3695 not exist!\r\n");
-            tyhx_poweroff();
+            PRINT("ppg not exist!\r\n");
+            ppg_power_off();
             return ERRCODE_FAIL;
         }
     }
-    tyhx_poweroff();
-    hx3695_register_msg_callback(hx3695_msg_callback);//注册驱动回调
+    ppg_power_off();
+    ppg_register_msg_callback(ppg_msg_callback);//注册驱动回调
     // ppg_send_cmd_to_driver("wear",0);
 
     ppg_sensor_exist = true;
-#endif
-
 
     app_task_definition_t taskcfg={0};
     taskcfg.create_queue_handle = create_ppg_queue;
     taskcfg.attr.name="ppg_service";
+#ifdef BOARD_FD230
     taskcfg.attr.priority = osPriorityBelowNormal4;
+#else
+    taskcfg.attr.priority = osPriorityAboveNormal3;
+#endif
     taskcfg.attr.stack_size = PPG_SERVICE_TASK_SIZE;
     taskcfg.func = ppg_service_check_task;
     taskcfg.use_mem = USE_EXTEND_MEM;
@@ -437,6 +434,14 @@ errcode_t uapi_ppg_service_init(void)
     return ERRCODE_SUCC;
 }
 
+void ppg_int_callback(pin_t pin, uintptr_t param)
+{
+    uapi_gpio_clear_interrupt(pin);
+    // uint32_t tm;
+    // uapi_get_timestampe_ms(&tm);
+    // PRINT("ppg_int_callback %d 0x%X   tm : %d \n",pin,param,tm);
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_INT_HANDLER);
+}
 // void ppg_service_service_resume(void)
 // {
 //     DEBUG_PRINTF("ppg_service_service resume!\r\n");
index 35d2563..094718d 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-03-27 09:07:00
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2024-12-21 11:00:33
+ * @LastEditTime: 2025-06-05 14:24:03
  * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/service/ppg_service.h
  * @Description: 
  * 
@@ -29,9 +29,10 @@ extern "C" {
 #include "stdint.h"
 #include "errcode.h"
 
-#define PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_5000TIMER_CALLBACK 0x09
-#define PPG_SERVICE_CMD_TYPE_DO_PPG_40TIMER_CALLBACK 0x0A
-#define PPG_SERVICE_CMD_TYPE_DO_PPG_320TIMER_CALLBACK 0x10
+#define PPG_SERVICE_CMD_TYPE_INT_HANDLER 0x08
+#define PPG_SERVICE_CMD_TYPE_DO_WEAR_MODE_TIMER_CALLBACK 0x09
+#define PPG_SERVICE_CMD_TYPE_DO_PPG_AGC_TIMER_CALLBACK 0x0A
+#define PPG_SERVICE_CMD_TYPE_DO_PPG_HRS_TIMER_CALLBACK 0x10
 #define PPG_SERVICE_CMD_TYPE_DO_PPG_TEST 0x11
 #define PPG_SERVICE_CMD_TYPE_DO_HRV_TEST 0x12
 #define PPG_SERVICE_CMD_TYPE_DO_SPO2_TEST 0x13
@@ -45,6 +46,8 @@ extern "C" {
 #define PPG_SERVICE_CMD_TYPE_DO_SINGLE_CHECK_MODE_TEST 0x23
 #define PPG_SERVICE_CMD_TYPE_OPEN_HRS_BLE 0x24
 #define PPG_SERVICE_CMD_TYPE_CLOSE_HRS_BLE 0x25
+#define PPG_SERVICE_CMD_TYPE_FPC_TEST 0x27
+#define PPG_SERVICE_CMD_TYPE_FACTORY_TEST 0x28
 
 errcode_t uapi_ppg_service_init(void);
 void uapi_ppg_service_deinit(void);
index ff6488d..0ce893f 100644 (file)
@@ -16,6 +16,20 @@ set(PUBLIC_HEADER
 set(PUBLIC_DEFINES
 SUPPORT_AT_HX3507
 )
+elseif("ROTARYENCODER_MIXO" IN_LIST DEFINES)
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo/mixo_ots_driver.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo/mixo_ots_access.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo/mixo_at_cmd.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo/mixo_hal.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo/mixo_service.c
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/mixo
+)
+set(PUBLIC_DEFINES
+SUPPORT_AT_MIXO
+)
 else()
 set(SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/hx3507/hx3507.c
index 491dac3..02c3f14 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-01-08 10:24:58
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-06 18:14:09
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/rotary_encoder/hx3507/hx3507_hal.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
 
 // #include "hx3507.h"
 
@@ -126,12 +134,12 @@ encoder_peripheral_api g_hx3507_api = {
 };
 
 
-void *rotary_encoder_get_api(void)
+void *rotary_encoder_get_hx3507_api(void)
 {
     return ((void *)&g_hx3507_api);
 }
 
-void *rotary_encoder_get_peri_attr(void)
+void *rotary_encoder_get_hx3507_peri_attr(void)
 {
     return ((void *)NULL);
 }
\ No newline at end of file
index f4e6b5f..926b006 100644 (file)
@@ -20,8 +20,8 @@ extern "C" {
 #endif /* __cplusplus */
 #endif /* __cplusplus */
 
-void *rotary_encoder_get_api(void);
-void *rotary_encoder_get_peri_attr(void);
+void *rotary_encoder_get_hx3507_api(void);
+void *rotary_encoder_get_hx3507_peri_attr(void);
 
 #ifdef __cplusplus
 #if __cplusplus
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.c
new file mode 100644 (file)
index 0000000..95cf9be
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-18 10:23:22
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-14 16:30:48
+ * @FilePath: /sdk615/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+// #include "mixo.h"
+
+
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "debug_print.h"
+#include "mixo_ots_driver.h"
+#include "custom_utils.h"
+#include "mixo_service.h"
+
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define MIXO_MAX_ARGC            8
+#define MIXO_MAX_ARGV_LEN        64
+
+#define MIXO_SUCCESS             0
+#define MIXO_FAILED              (-1)
+
+static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
+        uint8_t argv[MIXO_MAX_ARGC][MIXO_MAX_ARGV_LEN], uint32_t* argc)
+{
+    uint32_t pos = 0;
+    *argc = 0;
+
+    for (uint32_t i = 0; i < paraLen; i++) {
+        if ((para[i] == ' ' || para[i] == '\n') && pos != 0) {
+            argv[*argc][pos] = '\0';
+            *argc += 1;
+            pos = 0;
+            if (*argc >= MIXO_MAX_ARGC) {
+                return MIXO_FAILED;
+            }
+        } else {
+            argv[*argc][pos] = para[i];
+            pos++;
+            if (pos >= MIXO_MAX_ARGV_LEN) {
+                return MIXO_FAILED;
+            }
+        }
+    }
+    if (pos != 0) {
+        *argc += 1;
+    }
+
+    return MIXO_SUCCESS;
+}
+
+static uint8_t g_mixo_test_started = 0;
+static uint32_t mixo_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[MIXO_MAX_ARGC][MIXO_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != MIXO_SUCCESS) {
+        PRINT("MIXOTEST ATCMD Convert Command Failed\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (argc != 1) {
+        PRINT("MIXOTEST ATCMD Set Parameter Failed argc %d\n",argc);
+        return ERRCODE_FAIL;
+    }
+    uint8_t start = (uint8_t)atoi((char*)argv[0]);
+    if (start == 1)
+    {
+        // if (g_mixo_test_started == 1) 
+        // {
+        //     PRINT("SKIP mixotest start, already started\r\n");
+        //     return 0;
+        // }
+        mixo_start();
+        // mixo_start();
+        g_mixo_test_started = 1;
+    }else if (start == 2){
+        if (g_mixo_test_started == 0) 
+        {
+            PRINT("SKIP mixotest stop, already stopped\r\n");
+            return 0;
+        }
+        mixo_stop();
+        g_mixo_test_started = 0 ;
+    }
+    return ERRCODE_SUCC;
+}
+static const at_cmd_table_t g_mixo_cmd[] = {
+    { (char *)"AT^MIXOTEST",      mixo_test, (char *)"1" },
+};
+
+at_cmd_table_t *get_mixo_cmd_table(uint32_t *cmd_count)
+{
+    *cmd_count = ARRAY_COUNT(g_mixo_cmd);
+    return (at_cmd_table_t *)g_mixo_cmd;
+}
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_at_cmd.h
new file mode 100644 (file)
index 0000000..e882445
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-01-02 19:52:36
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-04 11:27:51
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/rotary_encoder/crown/crown_at_cmd.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef MIXO_AT_PROCESS_H
+#define MIXO_AT_PROCESS_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+at_cmd_table_t *get_mixo_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.c
new file mode 100644 (file)
index 0000000..551e98e
--- /dev/null
@@ -0,0 +1,151 @@
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "rotary_encoder_def.h"
+#include "debug_print.h"
+#include "mixo_ots_driver.h"
+#include "custom_utils.h"
+#include "pinctrl_porting.h"
+#include "mixo_service.h"
+
+#define MIXO_INT_PIN S_AGPIO_L0
+#define INT_MODE 1
+#define TIMER_MODE 0
+
+static uint8_t g_mixo_test_started = 0;
+encoder_callback g_encoder_callback = NULL;
+
+void mixo_int_callback(pin_t pin, uintptr_t param)
+{
+    PRINT("mixo_int_callback %d 0x%X\n",pin,param);
+    uapi_gpio_clear_interrupt(pin);
+    // uapi_pin_set_ie(MIXO_INT_PIN,HAL_PIO_IE_DISABLE);
+    mixo_start();           // 启动定时器
+}
+
+void mixo_check(void)
+{
+    if(mixo_get_check_mode() == TIMER_MODE)
+        mixo_ots_timer_callback();
+    // else if(mixo_get_check_mode() == INT_MODE)
+    // {
+    //     mixo_stop();           // 关闭定时器
+    //     // uapi_pin_set_ie(MIXO_INT_PIN,HAL_PIO_IE_ENBALE);
+    // }
+}
+
+
+void mixo_suspend(void)
+{
+    mixo_ots_enter_suspend_mode(1);
+}
+
+void mixo_resume(void)
+{
+    mixo_ots_enter_suspend_mode(0);
+}
+
+
+uint32_t mixo_init(void)
+{
+    if(mixo_ots_init() != ERRCODE_SUCC)
+        return ERRCODE_FAIL;
+
+    return ERRCODE_SUCC;
+}
+
+static ext_errno mixo_encoder_init(void *attr)
+{
+    re_print("mixo_encoder_init\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_deinit(void)
+{
+    re_print("mixo_encoder_deinit\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_get_encoderinfo(uint8_t *data, uint8_t data_len)
+{;
+    if (data_len != sizeof(re_input_event_info))
+        return EXT_ERR_NOT_SUPPORT;
+    re_input_event_info *encoder_info = (re_input_event_info*)data;
+    int16_t diff = mixo_get_crown_result();
+    int16_t stand_still = mixo_get_stand_still();
+    // re_print("mixo_encoder_get_encoderinfo diff %d stand_still %d\n",diff,stand_still);
+    if (stand_still == 1 )
+    {
+        encoder_info->re_event = MC_RE_COVER;
+    }else {
+        encoder_info->re_event = MC_RE_MOVE;
+    }
+    encoder_info->re_event_info.x_axis[0] = diff;
+    encoder_info->re_event_info.y_axis[0] = diff;
+    encoder_info->re_event_info.z_axis[0] = diff;
+    encoder_info->finger_id = 0 ;
+    encoder_info->point_num = 0 ;
+    encoder_info->tv_usec = (uint32_t)uapi_tcxo_get_ms();
+    //re_print("mixo_encoder_get_encoderinfo  %s rotate %d\r\n",encoder_info->re_event == MC_RE_SLIDE_UP?"MC_RE_SLIDE_UP":"MC_RE_SLIDE_DOWN",diff);
+
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_suspend(void)
+{
+    re_print("mixo_encoder_suspend\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_resume(void)
+{
+    re_print("mixo_encoder_resume\r\n");
+    mixo_start();
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_sleep(void)
+{
+    re_print("mixo_encoder_sleep\r\n");
+    mixo_stop();
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_reset(void)
+{
+    re_print("mixo_encoder_reset\r\n");
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_encoder_bus_init(void *private_data)
+{
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_register_callback(void *peri_data, encoder_callback func)
+{
+    re_print("mixo_register_callback\r\n");
+    g_encoder_callback = func;
+    return EXT_ERR_SUCCESS;
+}
+static ext_errno mixo_unregister_callback(void *peri_data)
+{
+    re_print("mixo_unregister_callback\r\n");
+    g_encoder_callback = NULL;
+    return EXT_ERR_SUCCESS;
+}
+
+encoder_peripheral_api g_mixo_api = {
+    .encoder_init = mixo_encoder_init,
+    .encoder_deinit = mixo_encoder_deinit,
+    .encoder_get_encoderinfo = mixo_encoder_get_encoderinfo,
+    .encoder_suspend = mixo_encoder_suspend,
+    .encoder_resume = mixo_encoder_resume,
+    .encoder_sleep = mixo_encoder_sleep,
+    .encoder_reset = mixo_encoder_reset,
+    .encoder_bus_init = mixo_encoder_bus_init,
+    .register_callback = mixo_register_callback,
+    .unregister_callback = mixo_unregister_callback,
+};
+
+
+void *rotary_encoder_get_mixo_api(void)
+{
+    return ((void *)&g_mixo_api);
+}
+
+void *rotary_encoder_get_mixo_peri_attr(void)
+{
+    return ((void *)NULL);
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_hal.h
new file mode 100644 (file)
index 0000000..7b677ad
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-23 15:11:25
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-14 16:37:32
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/rotary_encoder/hx3508/hx3508_hal.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE;
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef MIXO_HAL_H
+#define MIXO_HAL_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "rotary_encoder_def.h"
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+void *rotary_encoder_get_mixo_api(void);
+void *rotary_encoder_get_mixo_peri_attr(void);
+
+uint32_t mixo_init(void);
+
+void mixo_check(void);
+
+void mixo_suspend(void);
+void mixo_resume(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.c
new file mode 100644 (file)
index 0000000..6078260
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-01-04 10:53:54
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-04 16:38:46
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/rotary_encoder/mixo/src/mixo_ots_access.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/*
+ * Copyright (c) 2022 MixoSense Technology Ltd <contact@mixosense.com>.
+ *
+ * All rights are reserved.
+ * Proprietary and confidential.
+ * Unauthorized copying of this file, via any medium is strictly prohibited.
+ * Any use is subject to an appropriate license granted by MixoSense Technology
+ * Ltd.
+ *
+ */
+
+/*-----------------------------------------------------------------------------
+ * HEADER FILES
+ *---------------------------------------------------------------------------*/
+#include "mixo_ots_access.h"
+#include "custom_utils.h"
+
+
+static uint8_t slave_addr = 0x74;
+
+#define MIXO_OTS_I2C_BUS I2C_BUS_2
+
+void mixo_ots_set_slave_id(uint8_t slave_id)
+{
+    slave_addr = slave_id;
+}
+int mixo_ots_reg_read(uint8_t regAddr, uint8_t* regData)
+{
+    *regData = 0x00;  // 清空数据
+    // printf("<-%02X,%02X,%02X\r\n",slave_addr,regAddr,*regData);
+    // return mixo_gpio_i2c_write_read(slave_addr, &regAddr, 1, regData, 1);
+    return custom_i2c_read_regs(slave_addr, regAddr, 1, regData, 1,MIXO_OTS_I2C_BUS);
+}
+
+int mixo_ots_reg_consecutive_read(uint8_t regStartAddr,int len,uint8_t* regData)
+{
+    int rc = 0;
+    // rc = mixo_gpio_i2c_write_read(slave_addr, &regStartAddr, 1, regData, len);
+    rc = custom_i2c_read_regs(slave_addr, regStartAddr, 1, regData, len,MIXO_OTS_I2C_BUS);
+    // for(int i=0;i<len;i++)
+    // {
+    //     printf("<-%02X,%02X,%02X\r\n",slave_addr,regStartAddr+i,regData[i]);
+    // }
+    return rc;
+}
+
+int mixo_ots_reg_write(uint8_t regAddr, uint8_t regData)
+{
+    // uint8_t tmp[2] = {regAddr, regData};
+    // printf("->%02X,%02X,%02X\r\n",slave_addr,regAddr,regData);
+    // return mixo_gpio_i2c_write_read(slave_addr, tmp, 2, NULL, 0);
+    return custom_i2c_write_reg(slave_addr, regAddr, 1, &regData, 1,MIXO_OTS_I2C_BUS);
+}
+
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_access.h
new file mode 100644 (file)
index 0000000..4c2e504
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2022 MixoSense Technology Ltd <contact@mixosense.com>.
+ *
+ * All rights are reserved.
+ * Proprietary and confidential.
+ * Unauthorized copying of this file, via any medium is strictly prohibited.
+ * Any use is subject to an appropriate license granted by MixoSense Technology
+ * Ltd.
+ *
+ */
+
+#ifndef _MXS_REG_ACCESS_H_
+#define _MXS_REG_ACCESS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------------------------
+ * HEADER FILES
+ *---------------------------------------------------------------------------*/
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/*-----------------------------------------------------------------------------
+ * MACRO DEFINITION
+ *---------------------------------------------------------------------------*/
+#ifdef _WIN32
+#ifdef MXS_DLL_EXPORTS
+#define MXS_API __declspec(dllexport)
+#else
+#define MXS_API
+#endif
+#else
+#define MXS_API
+#endif
+
+/*-----------------------------------------------------------------------------
+ * FUNCTIONS DEFINITION
+ *---------------------------------------------------------------------------*/
+
+/**
+ * @brief mxs配置I2C从设备地址
+ *
+ * @param {uint8_t} slave_id
+ *
+ * @return {*}
+ */
+void mixo_ots_set_slave_id(uint8_t slave_id);
+
+/**
+ * @brief mxs寄存器写入接口
+ *
+ * @param {uint8_t} regAddr
+ * @param {uint8_t} regData
+ *
+ * @return {*}
+ */
+int mixo_ots_reg_write(uint8_t regAddr, uint8_t regData);
+
+/**
+ * @brief mxs寄存器读取接口
+ *
+ * @param {uint8_t} regAddr
+ * @param {uint8_t} *regData
+ *
+ * @return {*}
+ */
+int mixo_ots_reg_read(uint8_t regAddr, uint8_t* regData);
+int mixo_ots_reg_consecutive_read(uint8_t regStartAddr,
+                                  int len,
+                                  uint8_t* regData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //_MXS_REG_ACCESS_H_
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.c
new file mode 100644 (file)
index 0000000..be7f699
--- /dev/null
@@ -0,0 +1,346 @@
+#include "mixo_ots_driver.h"
+#include <stdlib.h>
+#include <string.h>
+#include "mixo_ots_access.h"
+#include "cmsis_os2.h"
+#include "debug_print.h"
+#include "mixo_hal.h"
+
+#ifndef ABS
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+#endif
+
+// macro definitions about reigster data
+#define REG_PROTECT_ID_HIGH 0x58
+#define REG_PROTECT_ID_LOW  0x5B
+
+static int dx_sum = 0;
+
+static uint16_t timer_cnt = 0;
+
+static int16_t ots_result = 0;//ots结果
+static int16_t stand_still = 1; //静止标志 1 静止,0 转动
+
+static uint8_t int_mode = 0;
+
+extern encoder_callback g_encoder_callback;
+
+
+static void put_crown_result(int16_t x)
+{
+    if(abs(x)<=1 )
+    {   
+        return;
+    }
+    if(abs(x)>=16 )
+    {
+        ots_result += x/16; //大于4的值除以4, 代表角度, 单位0.5°
+    }
+    else
+    {
+        if(x>0)
+        {
+            ots_result+=1; //2~4 默认一个单位, 0.5°
+        }
+        else
+        {
+            ots_result-=1; //2~4 默认一个单位, 0.5°
+        }
+    }
+
+   if (g_encoder_callback != NULL)
+        g_encoder_callback();
+}
+
+
+void mixo_ots_timer_callback(void)
+{
+    uint8_t mot_status = 0x00;
+    mixo_ots_get_mot_status(&mot_status);
+
+    if ((mot_status & 0x80) == 0x80)
+    {
+        timer_cnt = 0;
+        int_mode = 0;
+        // Get raw datas
+        raw_data_t raw_data;
+        mixo_ots_get_raw_data(&raw_data);
+        dx_sum += raw_data.dx;
+
+        // Output raw data
+        // printf("%ld,%d,%d,%d,%d\r\n", timestamp, raw_data.dx, raw_data.dy, mot_status, dx_sum);
+        // PRINT("%d,%d,%d,%d\r\n",raw_data.dx, raw_data.dy, mot_status, dx_sum);
+
+        put_crown_result(raw_data.dx);
+        stand_still = 0;
+
+        if (g_encoder_callback != NULL)
+            g_encoder_callback();
+
+    }
+    else
+    {
+        // timer_cnt++;
+        // if (timer_cnt == 20)  // 20*10 = // 200ms:200ms内sensor没有检测到表冠转动就会关闭定时器重新开启中断响应
+        // {
+        //     printf("mixo enter int mode\n");
+        //     /**
+        //      * 此处注意 mixo_ots_forced_clear_int
+        //      * 必须放在 external_int_init 之前去做
+        //      * 否则可能造成功耗异常的问题
+        //      */
+        //     mixo_ots_forced_clear_int();  // 强制拉高MOT脚
+        //     int_mode = 1;
+        // }
+        stand_still = 1;
+    }
+}
+
+
+/**
+ * @brief 接收1byte数据
+ * @param[in] original_dx   低8bit的dx数据
+ * @param[in] original_dy   低8bit的dy数据
+ * @param[in] high_bit      高4bit的dx/dy数据
+ * @param[out] dx           合成后的dx数据
+ * @param[out] dx           合成后的dy数据
+ * */
+static void data_synthesis(uint8_t original_dx,
+                           uint8_t original_dy,
+                           uint8_t high_bit,
+                           int16_t* dx,
+                           int16_t* dy)
+{
+    // move high 4 bits to bit 11 ~ bit 8
+    int16_t dx_high = (high_bit << 4) & 0x0F00;
+    int16_t dy_high = (high_bit << 8) & 0x0F00;
+
+    // sign extension
+    if (dx_high & 0x0800)
+    {
+        dx_high |= 0xF000;
+    }
+    if (dy_high & 0x0800)
+    {
+        dy_high |= 0xF000;
+    }
+
+    // move low 8 bits to bit 7 ~ bit 0
+    *dx = dx_high | (int16_t)original_dx;
+    *dy = dy_high | (int16_t)original_dy;
+
+    // overflow of 12-bit data
+    *dx = (*dx == 2048) ? 0 : *dx;
+    *dy = (*dy == 2048) ? 0 : *dy;
+}
+
+int mixo_ots_get_mot_status(uint8_t* mot_status)
+{
+    int ret                = 0;
+    uint8_t tmp_mot_status = 0x00;
+    ret                    = mixo_ots_reg_read(0x02, &tmp_mot_status);  // get MOTION STATUS
+    if (ret != 0) goto Exit;
+    *mot_status = tmp_mot_status;
+
+Exit:
+    return ret;
+}
+
+int mixo_ots_get_raw_data(raw_data_t* raw_data)
+{
+    int ret = 0;
+    uint8_t tmp = 0x00;
+
+    uint8_t tmp_dx          = 0x00;
+    uint8_t tmp_dy          = 0x00;
+    uint8_t tmp_dx_dy_hight = 0x00;
+
+    if (raw_data == NULL)
+    {
+        printf("null `raw_data`!");
+        ret = -1;
+        goto Exit;
+    }
+
+    ret = mixo_ots_reg_read(0x12, &tmp_dx_dy_hight);  // get DELTA XY HIGH
+    if (ret != 0) goto Exit;
+    ret = mixo_ots_reg_read(0x03, &tmp_dx);  // get DELTA X
+    if (ret != 0) goto Exit;
+    ret = mixo_ots_reg_read(0x04, &tmp_dy);  // get DELTA Y
+    if (ret != 0) goto Exit;
+
+    data_synthesis(
+        tmp_dx, tmp_dy, tmp_dx_dy_hight, &(raw_data->dx), &(raw_data->dy));
+
+    // If overflowed, clear out the data
+    if ((ABS(raw_data->dx) == 2047) || (ABS(raw_data->dy) == 2047))
+    {
+        // printf("dy/dx overflowed.");
+        mixo_ots_reg_read(0x02, &tmp);
+
+        mixo_ots_reg_read(0x02, &tmp);
+    }
+
+Exit:
+    return ret;
+}
+
+/* 强制清除MOT的中断信号 */
+void mixo_ots_forced_clear_int(void)
+{
+    uint8_t tmp = 0x00;
+    mixo_ots_reg_read(0x02, &tmp);
+    mixo_ots_reg_read(0x02, &tmp);
+}
+
+/* 进入/退出Suspend模式 */
+void mixo_ots_enter_suspend_mode(uint8_t true_or_false)
+{
+    uint8_t tmp = 0;
+    // 将数据从寄存器中读出后进行位操作,再重新写回
+    if (true_or_false)
+    {
+        // bit 3 写 1, 进入Suspend
+        mixo_ots_reg_read(0x06, &tmp);
+        mixo_ots_reg_write(0x06, (tmp | 0x08));
+    }
+    else
+    {
+        // bit 3 写 0, 退出Suspend
+        mixo_ots_reg_read(0x06, &tmp);
+        mixo_ots_reg_write(0x06, (tmp & 0xF7));
+    }
+}
+
+
+int callisto_2x_init(void)
+{
+    int ret         = 0;
+    int read_id_ok  = 0;
+    uint8_t id_high = 0x00;
+    uint8_t id_low  = 0x00;
+    uint8_t tmp_read      = 0x00;
+    uint8_t sensor_option = 0x04;  // sensor_option default is 0x04
+
+    printf("CONFIG_CALLISTO_2X\n");
+    mixo_ots_reg_write(0x09, 0x5A);     // write_protect, WO, Disable write protect
+    mixo_ots_reg_write(0x3C, 0xAC);     // bank_switch, WO, Banck switch
+    mixo_ots_reg_write(0x09, 0xA5);     // write_protect, WO, Disable write protect
+    mixo_ots_reg_write(0x6D, 0x39);     // read_protect, WO, Disable read protect
+    mixo_ots_reg_read(0x00, &id_high);  // Read chip-id high byte
+    mixo_ots_reg_read(0x01, &id_low);   // Read chip-id low byte
+    if (id_high == REG_PROTECT_ID_HIGH && id_low == REG_PROTECT_ID_LOW)
+    {
+        read_id_ok = 1;
+    }
+
+    if (read_id_ok)
+    {
+        mixo_ots_reg_write(0x19,
+                           sensor_option);  // sensor_option default is 0x04, WO, Enable 12bit mode; Disable x-y swap
+        mixo_ots_reg_write(0x3E, 0x73);  // comm_mode, WO, Switch to LED CC mode, and bypass AVDD
+        mixo_ots_reg_write(0x48, 0x2F);  // led_current, WO, Control LDP driven current
+        mixo_ots_reg_write(0x1F, 0xFE);  // led_current, WO, Control LDP driven current
+        mixo_ots_reg_write(0x73, 0x08);  // 2a3_motion, WO, To be compatible with 2A3 module
+        mixo_ots_reg_write(0x68, 0x67);  // col_counter, WO, Adjust the reference voltage for the Bandgap output; Adjust
+                                         // the output voltage of the 1.8V in sleep mode
+        mixo_ots_reg_write(0x7D, 0x60);  // trb_osch, WO, Adjust the output frequency of OSCH
+        mixo_ots_reg_write(0x60, 0x00);  // col_bias_and_output_drive, WO, Adjust the magnitude of the bias current in
+                                         // the sensor column; Adjust the sensor output drive strength
+
+        // TO DO, if need calibration
+    }
+
+    if (read_id_ok)
+    {
+        mixo_ots_reg_write(0x0D, 0x20);  // If cpi value is not assigned, use default value
+        mixo_ots_reg_write(0x0E, 0x20);  // If cpi value is not assigned, use default value
+
+        /**
+         * Enable 12bit mode Read the original value
+         * If swap_xy is true, swap dx and dy
+         * If inv_x is true, invert dx's output
+         * If inv_y is true, invert dy's output
+         */
+        mixo_ots_reg_read(0x19, &tmp_read);
+        if (tmp_read != sensor_option)
+        {
+            printf("sensor_option init failed!(The expected %02X, and the actual %02X)\r\n", sensor_option, tmp_read);
+        }
+
+        ret = 0;
+    }
+    else
+    {
+        ret = -1;
+        printf("callisto_2x init failed!\r\n");
+    }
+
+    return ret;
+}
+
+static uint8_t mixo_installized = 0;
+
+int mixo_ots_init(void)
+{
+    if(mixo_installized)
+        return 0;
+
+    int rc             = 0;
+    uint8_t HardWareId = 0;
+
+    mixo_ots_reg_read(0x1B, &HardWareId);
+    printf("Address: %x, Data: %x\r\n", 0x1B, HardWareId);
+
+    switch (HardWareId)
+    {
+        case 0xA1:
+            rc = callisto_2x_init();
+            break;
+        case 0xB1:
+            rc = callisto_2x_init();
+            break;
+        case 0xC1:
+            rc = callisto_2x_init();
+            break;
+        default:
+            printf("OTS Sensor Not Support!\n");
+            rc = -1;
+            break;
+    }
+
+    if(rc == 0)
+    {
+        mixo_installized = 1;
+        printf("mixo_ots_init succed !!! \n");
+    }
+    else
+    {
+        printf("mixo_ots_init failed !!! \n");
+    }
+    return rc;
+}
+
+int16_t mixo_get_stand_still(void)
+{
+    return stand_still;
+}
+
+void mixo_clean_result(void)
+{
+    ots_result = 0;
+}
+
+
+int16_t mixo_get_crown_result(void)
+{
+    int16_t resulttemp;
+    resulttemp=ots_result;
+    ots_result = 0;
+    return resulttemp;
+}
+
+uint8_t mixo_get_check_mode(void)
+{
+    return int_mode;
+}
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_ots_driver.h
new file mode 100644 (file)
index 0000000..a991947
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-01-04 10:53:54
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-14 17:13:14
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/rotary_encoder/mixo/mixo_ots_driver.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/*
+ * Copyright (c) 2019 MixoSense Technology Ltd <contact@mixosense.com>.
+ *
+ * All rights are reserved.
+ * Proprietary and confidential.
+ * Unauthorized copying of this file, via any medium is strictly prohibited.
+ * Any use is subject to an appropriate license granted by MixoSense Technology
+ * Ltd.
+ *
+ */
+
+#ifndef _MXS_DRIVER_H_
+#define _MXS_DRIVER_H_
+
+#include <stdint.h>
+
+typedef struct
+{
+    int16_t dx;
+    int16_t dy;
+} raw_data_t;
+
+int mixo_ots_init(void);
+int mixo_ots_get_mot_status(uint8_t* mot_status);
+int mixo_ots_get_raw_data(raw_data_t* raw_data);
+void mixo_ots_forced_clear_int(void);
+void mixo_ots_enter_suspend_mode(uint8_t true_or_false);
+
+void mixo_ots_start(void);
+void mixo_ots_stop(void);
+
+int16_t mixo_get_stand_still(void);
+int16_t mixo_get_crown_result(void);
+void mixo_ots_timer_callback(void);
+void mixo_clean_result(void);
+uint8_t mixo_get_check_mode(void);
+
+#endif  //_MXS_DRIVER_H_
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c
new file mode 100644 (file)
index 0000000..314b0b2
--- /dev/null
@@ -0,0 +1,157 @@
+
+#include "debug_print.h"
+#include "soc_osal.h"
+#include "tcxo.h"
+#include "irmalloc.h"
+#include "errcode.h"
+#include "common_def.h"
+#include "tcxo.h"
+#include "input_app.h"
+#include "cmsis_os2.h"
+#include "custom_utils.h"
+#include "mixo_hal.h"
+#include "mixo_service.h"
+#include "pinctrl_porting.h"
+
+// #include "custom_runtime.h"
+/***
+ * 其他cmd在Header里定义,对外开放
+*/
+#define MIXO_SERVICE_CMD_TIMER_CHECK 0x11
+
+#define MIXO_SERVICE_TIMER_CHECK_MS  30
+
+static bool g_mixo_service_initialled = false;
+
+static bool g_mixo_sensor_exist = false;
+
+static unsigned long g_app_queue= 0xFFFFFFFF;
+
+static bool mixo_service_timer_running = false; //ots定时器是否运行标志
+
+static osTimerId_t g_mixo_service_timer = NULL;
+
+void do_mixo_service_check_msg(int cmd);
+
+static void mixo_service_timer_callback(void)
+{
+    do_mixo_service_check_msg(MIXO_SERVICE_CMD_TIMER_CHECK);
+}
+
+void mixo_service_timer_start(void)
+{
+    if(mixo_service_timer_running == false && g_mixo_service_timer)
+    {
+        mixo_resume();
+        osTimerStart(g_mixo_service_timer,MIXO_SERVICE_TIMER_CHECK_MS);
+        mixo_service_timer_running = true;
+    }
+}
+
+void mixo_service_timer_stop(void)
+{
+    if(mixo_service_timer_running == true && g_mixo_service_timer)
+    {
+        mixo_suspend();
+        mixo_clean_result();
+        osTimerStop(g_mixo_service_timer);
+        mixo_service_timer_running = false;
+    }
+}
+
+void mixo_start(void)
+{
+    do_mixo_service_check_msg(MIXO_SERVICE_CMD_START_CHECK);
+}
+
+void mixo_stop(void)
+{
+    do_mixo_service_check_msg(MIXO_SERVICE_CMD_STOP_CHECK);
+}
+
+
+void do_mixo_service_check_msg(int cmd)
+{
+    int ret;
+    if (g_mixo_sensor_exist == false)
+        return ;
+    common_notify_mail_t mail = {0};
+    mail.comm.app = cmd;
+    ret = osal_msg_queue_write_copy(g_app_queue, (void *)&mail,
+                                    sizeof(common_notify_mail_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        PRINT("Error mixo Check MSG 0x%02X send failed! err=0x%x! \r\n",cmd, ret);
+    }
+    
+}
+
+static void mixo_service_check_task(void const *arg)
+{
+    unused(arg);
+    int32_t ret;
+    common_notify_mail_t mail;
+    uint32_t msgsize = (uint32_t)sizeof(common_notify_mail_t);
+    while (1) {
+        ret = osal_msg_queue_read_copy(g_app_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            continue;
+        }
+
+        if (mail.comm.app == MIXO_SERVICE_CMD_TIMER_CHECK) {
+            mixo_check();
+        }else if (mail.comm.app == MIXO_SERVICE_CMD_START_CHECK){
+            mixo_service_timer_start();
+        }else if (mail.comm.app == MIXO_SERVICE_CMD_STOP_CHECK){
+            mixo_service_timer_stop();
+        }
+
+
+    }
+}
+void create_mixo_queue(void)
+{
+
+    if (osal_msg_queue_create("mixo_service_queue", APP_BOARD_MSG_COUNT, &g_app_queue,
+                              0, sizeof(common_notify_mail_t)) != ERRCODE_SUCC) {
+        PRINT("[mixo][service] app create mail fail\n");
+    }
+}
+
+#define MIXO_BOARD_TASK_SIZE   0x1000
+errcode_t uapi_mixo_service_init(void)
+{
+    PRINT("uapi_mixo_service_init !\r\n");
+
+    if(mixo_init() != ERRCODE_SUCC)
+    {
+        //TODO 设置光电编码器检测是否存在标识
+        PRINT("mixo not found!\r\n");
+        return ERRCODE_FAIL;
+    }
+    g_mixo_sensor_exist = true;
+
+    app_task_definition_t taskcfg={0};
+    taskcfg.create_queue_handle = create_mixo_queue;
+    taskcfg.attr.name="mixo_service";
+    taskcfg.attr.priority = osPriorityBelowNormal4;
+    taskcfg.attr.stack_size = MIXO_BOARD_TASK_SIZE;
+    taskcfg.func = mixo_service_check_task;
+    taskcfg.use_mem = USE_EXTEND_MEM;
+    
+    errcode_t ret=uapi_create_osThread_custom(&taskcfg);
+    if(ret != ERRCODE_SUCC)
+    {
+        PRINT("create mixo_service failed %d!\r\n",ret);
+        return ERRCODE_FAIL;
+    }
+
+    mixo_init();
+    
+    g_mixo_service_timer = osTimerNew((osTimerFunc_t)mixo_service_timer_callback, osTimerPeriodic, NULL, NULL);
+
+    mixo_start();
+
+    return ERRCODE_SUCC;
+}
+
diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h
new file mode 100644 (file)
index 0000000..60ded83
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-23 15:12:01
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-14 16:29:38
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/mixo/service/mixo_service.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Test adc header \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-08-16, Create file. \n
+ */
+
+#ifndef MIXO_SERVICE_H__
+#define MIXO_SERVICE_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+#include "platform_core.h"
+
+#define MIXO_SERVICE_CMD_START_CHECK 0x12
+#define MIXO_SERVICE_CMD_STOP_CHECK 0x13
+
+errcode_t uapi_mixo_service_init(void);
+void uapi_mixo_service_deinit(void);
+void do_mixo_service_check_msg(int cmd);
+void mixo_start(void);
+void mixo_stop(void);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
index 2032988..8fe6545 100644 (file)
 #include "soc_osal.h"
 #include "rotary_encoder_def.h"
 #include "input_app.h"
+
+#ifdef ROTARYENCODER_MIXO
+#include "mixo_hal.h"
+#elif defined ROTARYENCODER_HX3507
+#include "hx3507_hal.h"
+#endif
+
 // #if defined(TPTYPE_TMA525B)
 // #include "tma525b_drv1.h"
 // #include "tma525b_ctrl.h"
@@ -172,16 +179,20 @@ static ext_errno re_register_callback(struct re_driver_data *attr)
     g_attr_re = attr;
     re_err("re_register_callback ----------succ!!!\n");
 
-    if (attr->encoder_api->register_callback != NULL) {
-        ret = attr->encoder_api->register_callback(attr->private_data, re_callback_func);
-        if (ret != EXT_ERR_SUCCESS) {
-            re_err("register rotary encoder callback fail! ret=0x%x", ret);
-            return ret;
+    if(attr->encoder_api)
+    {
+        if (attr->encoder_api->register_callback != NULL) {
+            ret = attr->encoder_api->register_callback(attr->private_data, re_callback_func);
+            if (ret != EXT_ERR_SUCCESS) {
+                re_err("register rotary encoder callback fail! ret=0x%x", ret);
+                return ret;
+            }
+        } else {
+            re_err("rotary encoder callback register func is empty!");
         }
-    } else {
-        re_err("rotary encoder callback register func is empty!");
     }
 
+
     return ret;
 }
 
@@ -406,9 +417,13 @@ uint32_t re_init(void)
     int32_t ret;
     struct re_driver_data *redd = NULL;
     // re_err("re_init ----------1!!!\n");
-
-    g_encoder_drv.private_data = rotary_encoder_get_peri_attr();
-    g_encoder_drv.encoder_api = rotary_encoder_get_api();
+#ifdef ROTARYENCODER_HX3507
+    g_encoder_drv.private_data = rotary_encoder_get_hx3507_peri_attr();
+    g_encoder_drv.encoder_api = rotary_encoder_get_hx3507_api();
+#elif defined ROTARYENCODER_MIXO
+    g_encoder_drv.private_data = rotary_encoder_get_mixo_peri_attr();
+    g_encoder_drv.encoder_api = rotary_encoder_get_mixo_api();
+#endif
     g_encoder_drv.ops = &g_re_status_ops;
     redd = rotary_encoder_get_driver_data();
     redd->queue = re_init_queue(ROTARY_ENCODER_QUEUE_MAX_SIZE);
@@ -444,18 +459,30 @@ uint32_t re_close(void)
 
 void rotary_encoder_suspend(void)
 {
-
+    encoder_peripheral_api *encoder_ptr = NULL;
     /**灭屏,关闭Encoder*/
-    encoder_peripheral_api *encoder_ptr = rotary_encoder_get_api();
+#ifdef ROTARYENCODER_HX3507
+    encoder_ptr = rotary_encoder_get_hx3507_api();
+#elif defined ROTARYENCODER_MIXO
+    encoder_ptr = rotary_encoder_get_mixo_api();
+#endif
+    if(encoder_ptr == NULL)
+        return;
     ext_errno ret = encoder_ptr->encoder_sleep();
     if (ret != EXT_ERR_SUCCESS) { re_err("encoder sleep ret=0x%x", ret); }
-
 }
 
 void rotary_encoder_resume(void)
 {
+    encoder_peripheral_api *encoder_ptr = NULL;
+#ifdef ROTARYENCODER_HX3507
     /**亮屏,恢复Encoder工作*/
-    encoder_peripheral_api *encoder_ptr = (encoder_peripheral_api*)rotary_encoder_get_api();
+    encoder_ptr = (encoder_peripheral_api*)rotary_encoder_get_hx3507_api();
+#elif defined ROTARYENCODER_MIXO
+    encoder_ptr = (encoder_peripheral_api*)rotary_encoder_get_mixo_api();
+#endif
+    if(encoder_ptr == NULL)
+        return;
     ext_errno ret = encoder_ptr->encoder_resume();
     if (ret != EXT_ERR_SUCCESS) { re_err("encoder resume ret=0x%x", ret); }
 }
index 826bd68..a087994 100644 (file)
@@ -28,43 +28,72 @@ extern "C" {
 
 #include "pm.h"
 #include "pm_veto.h"
+uint32_t uapi_cat1_bat_on(uint32_t pwron)
+{
+
+#if defined(BOARD_L22)
+    pin_t bat_en_pin =  S_AGPIO_L14;
+#elif defined(BOARD_W9)
+    pin_t bat_en_pin =  S_AGPIO_L17;
 
+    if( pwron == 0)
+    {
+        uapi_gpio_set_dir(bat_en_pin, GPIO_DIRECTION_OUTPUT);
+        uapi_gpio_set_val(bat_en_pin, GPIO_LEVEL_LOW);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"BAT OFF Cat1! %d low  \r\n",bat_en_pin);
+    }else{
+        uapi_gpio_set_dir(bat_en_pin, GPIO_DIRECTION_OUTPUT);
+        uapi_gpio_set_val(bat_en_pin, GPIO_LEVEL_HIGH);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"BAT ON Cat1! %d high \r\n",bat_en_pin);
+    }
+#endif
+    
+    return 0;
+}
 uint32_t uapi_cat1_power_on(uint32_t pwron)
 {
 
+    pin_t bat_en_pin =  S_AGPIO_L23;
     if( pwron == 0)
     {
-        uapi_gpio_set_dir(S_AGPIO_L23, GPIO_DIRECTION_OUTPUT);
-        uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_LOW);
-        // wstp_WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Power OFF Cat1! L23 low  \r\n");
+        uapi_gpio_set_dir(bat_en_pin, GPIO_DIRECTION_OUTPUT);
+        uapi_gpio_set_val(bat_en_pin, GPIO_LEVEL_LOW);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Power Cat1! %d low  \r\n",bat_en_pin);
     }else{
-        uapi_gpio_set_dir(S_AGPIO_L23, GPIO_DIRECTION_OUTPUT);
-        uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);
-        // wstp_WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Power ON Cat1! L23 high \r\n");
+        uapi_gpio_set_dir(bat_en_pin, GPIO_DIRECTION_OUTPUT);
+        uapi_gpio_set_val(bat_en_pin, GPIO_LEVEL_HIGH);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Power Cat1! %d high \r\n",bat_en_pin);
     }
     
     return 0;
 }
 uint32_t uapi_cat1_reset(uint32_t pwron)
 {
+
+#if defined(BOARD_FD230)
     if( pwron == 0)
     {
         uapi_gpio_set_dir(S_AGPIO_L28, GPIO_DIRECTION_OUTPUT);
         uapi_gpio_set_val(S_AGPIO_L28, GPIO_LEVEL_HIGH);
-        // wstp_WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"clear reset Cat1! L28 high \r\n");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"clear reset Cat1! L28 high \r\n");
     }else{
         uapi_gpio_set_dir(S_AGPIO_L28, GPIO_DIRECTION_OUTPUT);
         uapi_gpio_set_val(S_AGPIO_L28, GPIO_LEVEL_LOW); 
-        // wstp_WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Reset Cat1! L28 low\r\n");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Reset Cat1! L28 low\r\n");
     }
-
+#endif
     return 0;
 }
 
 bool uapi_cat1_get_power_stat(void)
 {
-
+#if defined(BOARD_FD230)
    return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L23));
+#elif defined(BOARD_L22)
+   return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L14));
+#elif defined(BOARD_W9)
+   return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L17));
+#endif
 
 }
 
index 57f8df5..2112a69 100644 (file)
@@ -1,3 +1,11 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-02-06 09:40:52\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-06-06 17:19:07\r
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.h\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
 \r
 #ifndef __CAT1_CTL_H\r
 #define __CAT1_CTL_H\r
@@ -44,6 +52,8 @@ void uapi_cat1_resume(void);
 \r
 void recover_call_state(void);\r
 \r
+uint32_t uapi_cat1_bat_on(uint32_t pwron);\r
+\r
 #ifdef __cplusplus\r
 #if __cplusplus\r
 }\r
index 6971096..db020dc 100644 (file)
@@ -27,6 +27,12 @@ set(SOURCES ${SOURCES}
     ${CMAKE_CURRENT_SOURCE_DIR}/ft6x46_touch/ft6x46_drv1.c
     ${CMAKE_CURRENT_SOURCE_DIR}/ft6x46_touch/ft6x46_touch1.c
 )
+elseif("TPTYPE_CST86XX" IN_LIST DEFINES)
+set(SOURCES ${SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/cst86xx_touch/cst86xx_ctrl.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/cst86xx_touch/cst86xx_drv1.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/cst86xx_touch/cst86xx_touch1.c
+)
 else()
 set(SOURCES ${SOURCES}
     ${CMAKE_CURRENT_SOURCE_DIR}/ztw523_touch/ztw523_ctrl.c
@@ -53,6 +59,12 @@ set(PUBLIC_HEADER
     ${CMAKE_CURRENT_SOURCE_DIR}/ft6x46_touch
     ${ROOT_DIR}/middleware/services/gui/hal/input/include
 )
+elseif("TPTYPE_CST86XX" IN_LIST DEFINES)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/cst86xx_touch
+    ${ROOT_DIR}/middleware/services/gui/hal/input/include
+)
 else()
 set(PUBLIC_HEADER
     ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.c b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.c
new file mode 100644 (file)
index 0000000..f840c0a
--- /dev/null
@@ -0,0 +1,336 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2022-04-12\r
+ */\r
+\r
+#include "cst86xx_ctrl.h"\r
+#include "securec.h"\r
+#include "cmsis_os2.h"\r
+#include "soc_osal.h"\r
+#include "common_def.h"\r
+#include "pinctrl.h"\r
+#include "chip_io.h"\r
+#include "tcxo.h"\r
+#include "time.h"\r
+#include "i2c.h"\r
+#include "gpio.h"\r
+#include "hal_gpio.h"\r
+#include "hal_i2c.h"\r
+#include "touch_screen_def.h"\r
+\r
+bool g_host_dev_init_flag = TD_FALSE;\r
+cst86xx_ctrl_attr g_ctrl_attr;\r
+touch_callback g_cst86xx_callback = NULL;\r
+static uint8_t g_tp_send_buf[CST86XX_REG_WRITE_LEN] = {0};\r
+static uint8_t g_tp_recv_buf[CST86XX_INPUT_SIZE] = {0};\r
+\r
+static void cst86xx_gpio_isr_handle(pin_t pin, uintptr_t param)\r
+{\r
+    unused(pin);\r
+    unused(param);\r
+    if (g_cst86xx_callback != NULL) {\r
+        g_cst86xx_callback();\r
+    }\r
+}\r
+\r
+ext_errno cst86xx_register_handle(const cst86xx_ctrl_ops *peri_data, touch_callback func)\r
+{\r
+    unused(peri_data);\r
+    ext_errno ret;\r
+\r
+    g_cst86xx_callback = func;\r
+    /* register int io interrupt handler */\r
+    uapi_gpio_init();\r
+    gpio_select_core(CST86XX_INT_GPIO, CORE);\r
+    uapi_gpio_set_dir(CST86XX_INT_GPIO, GPIO_DIRECTION_INPUT);\r
+    ret = uapi_gpio_register_isr_func(CST86XX_INT_GPIO, GPIO_INTERRUPT_FALLING_EDGE, cst86xx_gpio_isr_handle);\r
+    if (ret != 0) {\r
+        tp_err("cst86xx int callback register fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_unregister_handle(const cst86xx_ctrl_ops *peri_data)\r
+{\r
+    unused(peri_data);\r
+    ext_errno ret;\r
+\r
+    /* unregister interrupt handler */\r
+    uapi_gpio_unregister_isr_func(CST86XX_INT_GPIO);\r
+    g_cst86xx_callback = NULL;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno tp_peripheral_init_status_check(void)\r
+{\r
+    if (g_host_dev_init_flag != TD_TRUE) {\r
+        return EXT_ERR_TP_DEV_INFO_NOT_REGISTER;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+// static ext_errno cst86xx_ctrl_attr_check(const cst86xx_ctrl_attr *device_attr)\r
+// {\r
+//     unused(device_attr);\r
+//     return EXT_ERR_SUCCESS;\r
+// }\r
+\r
+static ext_errno cst86xx_tp_i2c_rd_wr_param_check(const uint8_t *data_buf, uint32_t data_len)\r
+{\r
+    unused(data_buf);\r
+    unused(data_len);\r
+    ext_errno ret = tp_peripheral_init_status_check();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_tp_i2c_data_read(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_len)\r
+{\r
+    errcode_t ret;\r
+    uint32_t retry;\r
+    i2c_data_t data;\r
+\r
+    ret = cst86xx_tp_i2c_rd_wr_param_check(data_buf, data_len);\r
+    if (ret != 0) {\r
+        tp_err("tp data read param invalid! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    if (memset_s(g_tp_recv_buf, data_len, 0, data_len) != EOK) {\r
+        tp_err("tp read buff set fail! ret=0x%x", ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    g_tp_send_buf[CST86XX_I2C_SEND_INDEX0] = reg_addr & 0xff;\r
+    data.send_buf = g_tp_send_buf;\r
+    data.send_len = CST86XX_CMD_SEND_LEN;\r
+    data.receive_buf = g_tp_recv_buf;\r
+    data.receive_len = data_len;\r
+    for (retry = 0; retry < CST86XX_I2C_TIME_MAX; retry++) {\r
+        ret = uapi_i2c_master_writeread(CST86XX_I2C_BUS, CST86XX_I2C_ADDR, &data);\r
+        if (ret == EXT_ERR_SUCCESS) {\r
+            break;\r
+        }\r
+    }\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp data read fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    ret = (uint32_t)memcpy_s(data_buf, data_len, g_tp_recv_buf, data_len);\r
+    if (ret != EOK) {\r
+        tp_err("tp data buf content copy fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_tp_i2c_cmd_write(uint16_t cmd)\r
+{\r
+    errcode_t ret;\r
+    uint32_t retry;\r
+    i2c_data_t data;\r
+\r
+    ret = tp_peripheral_init_status_check();\r
+    if (ret != 0) {\r
+        tp_err("host peripheral not init! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+    g_tp_send_buf[CST86XX_I2C_SEND_INDEX0] = cmd & 0xff;\r
+    data.send_buf = g_tp_send_buf;\r
+    data.send_len = CST86XX_CMD_SEND_LEN;\r
+    data.receive_buf = NULL;\r
+    data.receive_len = 0;\r
+\r
+    for (retry = 0; retry < CST86XX_I2C_TIME_MAX; retry++) {\r
+        ret = uapi_i2c_master_write(CST86XX_I2C_BUS, CST86XX_I2C_ADDR, &data);\r
+        if (ret == EXT_ERR_SUCCESS) {\r
+            break;\r
+        }\r
+    }\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp data write fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_tp_i2c_reg_write(uint16_t reg_addr, uint16_t reg_cfg)\r
+{\r
+    errcode_t ret;\r
+    uint32_t retry;\r
+    i2c_data_t data;\r
+\r
+    ret = tp_peripheral_init_status_check();\r
+    if (ret != 0) {\r
+        tp_err("host peripheral not init! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    g_tp_send_buf[CST86XX_I2C_SEND_INDEX0] = reg_addr & 0xff;\r
+\r
+    g_tp_send_buf[1] = reg_cfg & 0xff;\r
+\r
+    data.send_buf = g_tp_send_buf;\r
+    data.send_len = CST86XX_REG_WRITE_LEN;\r
+    data.receive_buf = NULL;\r
+    data.receive_len = 0;\r
+\r
+    for (retry = 0; retry < CST86XX_I2C_TIME_MAX; retry++) {\r
+        ret = uapi_i2c_master_write(CST86XX_I2C_BUS, CST86XX_I2C_ADDR, &data);\r
+        if (ret == EXT_ERR_SUCCESS) {\r
+            break;\r
+        }\r
+    }\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp reg write fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_tp_i2c_data_write(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_len)\r
+{\r
+    errcode_t ret;\r
+    uint32_t retry;\r
+    i2c_data_t data;\r
+    uint8_t *write_data = NULL;\r
+    uint32_t send_len;\r
+\r
+    ret = cst86xx_tp_i2c_rd_wr_param_check(data_buf, data_len);\r
+    if (ret != 0) {\r
+        tp_err("tp data write param invalid! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    send_len = data_len + sizeof(uint16_t);\r
+\r
+    write_data = (uint8_t *)osal_kmalloc(send_len, OSAL_GFP_KERNEL);\r
+    if (write_data == NULL) {\r
+        tp_err("tp send buff malloc fail!");\r
+        return EXT_ERR_MALLOC_FAILURE;\r
+    }\r
+\r
+    write_data[CST86XX_I2C_SEND_INDEX0] = reg_addr & 0xff;\r
+    ret = (uint32_t)memcpy_s(write_data + sizeof(uint16_t), send_len - sizeof(uint16_t), data_buf, data_len);\r
+    if (ret != EOK) {\r
+        tp_err("tp send_buf content copy fail! ret=0x%x", ret);\r
+        osal_kfree(write_data);\r
+        return ret;\r
+    }\r
+\r
+    data.send_buf = write_data;\r
+    data.send_len = send_len;\r
+    data.receive_buf = NULL;\r
+    data.receive_len = 0;\r
+\r
+    for (retry = 0; retry < CST86XX_I2C_TIME_MAX; retry++) {\r
+        ret = uapi_i2c_master_write(CST86XX_I2C_BUS, CST86XX_I2C_ADDR, &data);\r
+        if (ret == EXT_ERR_SUCCESS) {\r
+            break;\r
+        }\r
+    }\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp data write fail! ret=0x%x", ret);\r
+        osal_kfree(write_data);\r
+        return ret;\r
+    }\r
+\r
+    osal_kfree(write_data);\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_host_peripheral_init(cst86xx_ctrl_attr *attr)\r
+{\r
+    ext_errno ret;\r
+\r
+    if (attr == NULL) {\r
+        tp_err("cst86xx communication interface cfg is empty!");\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    // ret = cst86xx_ctrl_attr_check(attr);\r
+    // if (ret != EXT_ERR_SUCCESS) {\r
+    //     tp_err("tp invalid dev attr! ret=0x%x", ret);\r
+    //     return ret;\r
+    // }\r
+\r
+    // ret = (ext_errno)memcpy_s(&(g_ctrl_attr), sizeof(cst86xx_ctrl_attr), attr, sizeof(cst86xx_ctrl_attr));\r
+    // if (ret != EOK) {\r
+    //     tp_err("tp attr content copy fail! ret=0x%x", ret);\r
+    //     return ret;\r
+    // }\r
+\r
+    /* init i2c */\r
+    errcode_t result;\r
+    result = uapi_i2c_master_init(CST86XX_I2C_BUS, 100000, I2C_SPEED_MODE_SS); /* 400000: 400KHz */\r
+    if (result != EXT_ERR_SUCCESS) {\r
+        tp_err("tp i2c init fail! ret=0x%x", result);\r
+        return EXT_ERR_SUCCESS;\r
+    }\r
+\r
+    tp_warning("TOUCH:i2c_id = %d  i2c_speed = %d  slave_addr  = 0x%x \r\n",\r
+        CST86XX_I2C_BUS, 100000, CST86XX_I2C_ADDR);\r
+    g_host_dev_init_flag = true;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_host_init_sample(void)\r
+{\r
+    ext_errno ret;\r
+    tp_warning("cst86xx_host_init_sample");\r
+    ret = cst86xx_host_peripheral_init(&g_ctrl_attr);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp host init fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+    ret = cst86xx_init();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("tp init fail! ret=0x%x", ret);\r
+        return ret;\r
+    }\r
+    \r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_reset(void)\r
+{\r
+    uapi_gpio_set_dir(CST86XX_RESET_GPIO, GPIO_DIRECTION_OUTPUT);\r
+    /* Config Gpio For Reset Pin */\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_HIGH);\r
+    /* reset high delay 20ms */\r
+    osDelay(1);\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_LOW);\r
+    /* reset low delay 100ms */\r
+    osDelay(10);\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_HIGH);\r
+    /* reset high delay 200ms */\r
+    osDelay(100);\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+void cst86xx_resume_reset(void)\r
+{\r
+    uapi_gpio_set_dir(CST86XX_RESET_GPIO, GPIO_DIRECTION_OUTPUT);\r
+    /* drvdata is global variable point and no need to handle null */\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_HIGH);\r
+    osDelay(1);\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_LOW);\r
+    /* delay 10ms */\r
+    osDelay(10);\r
+    uapi_gpio_set_val(CST86XX_RESET_GPIO, GPIO_LEVEL_HIGH);\r
+    /* delay 100ms */\r
+    osDelay(100);\r
+    // uapi_gpio_set_dir(CST86XX_RESET_GPIO, GPIO_DIRECTION_INPUT);\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.h b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_ctrl.h
new file mode 100644 (file)
index 0000000..4f731d9
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2022-04-12\r
+ */\r
+\r
+#ifndef CST86XX_CTRL_H\r
+#define CST86XX_CTRL_H\r
+\r
+#include "stdio.h"\r
+#include "debug_print.h"\r
+#include "stdint.h"\r
+#include "product.h"\r
+#include "td_base.h"\r
+#include "platform_core.h"\r
+#include "cst86xx_touch1.h"\r
+\r
+\r
+\r
+//_TODO:\r
+#define CTP_USE_SW_I2C                      0       //hard i2c:0 gpio i2c:1\r
+#define CTP_SLAVER_ADDR                     (0x2A)  //(8bit write addr  0x15<<1)\r
+\r
+#define CTP_HYNITRON_AUTO_UPDATE            0       // enable update\r
+#define CTP_HYNITRON_CST816S_UPDATE         0       //820S 816S\r
+#define CTP_HYNITRON_CST816T_UPDATE         0       //820 816t 816D\r
+#define CTP_HYNITRON_CST78xx_UPDATE         0       //716 830 826 836U\r
+\r
+#define CTP_TRUE    (0)\r
+#define CTP_FALSE   (-1)\r
+\r
+#define OUTPUT 1\r
+#define INPUT 0\r
+\r
+\r
+#define DBG_CTP\r
+#ifdef DBG_CTP\r
+#define ctp_dbg_print(fmt,args...)   printf("[HYN]"fmt"\n\r", ##args)\r
+#else\r
+#define ctp_dbg_print(...)\r
+#endif\r
+\r
+\r
+/* host peripheral definitions */\r
+#define CST86XX_I2C_ADDR           0x15\r
+#define CST86XX_I2C_SPEED          I2C_SPEED_MODE_SS\r
+#define CST86XX_REG_WRITE_LEN      2\r
+#define CST86XX_CMD_SEND_LEN       1\r
+#define CST86XX_REG_DATA_LEN       1\r
+#define CST86XX_I2C_TIME_MAX       3\r
+#define CST86XX_INPUT_SIZE         6\r
+#define CST86XX_I2C_SEND_INDEX0    0\r
+// #define CST86XX_I2C_SEND_INDEX1    1\r
+// #define CST86XX_I2C_SEND_INDEX2    2\r
+// #define CST86XX_I2C_SEND_INDEX3    3\r
+typedef struct {\r
+    uint32_t int_gpio;\r
+    i2c_bus_t i2c_id;\r
+    uint32_t i2c_speed;\r
+} cst86xx_ctrl_attr;\r
+\r
+typedef ext_errno (*cst86xx_bus_init)(cst86xx_ctrl_attr *attr);\r
+\r
+typedef struct {\r
+    cst86xx_ctrl_attr attr;\r
+    cst86xx_bus_init bus_init;\r
+} cst86xx_ctrl_ops;\r
+\r
+ext_errno cst86xx_host_peripheral_init(cst86xx_ctrl_attr *attr);\r
+ext_errno cst86xx_register_handle(const cst86xx_ctrl_ops *peri_data, touch_callback func);\r
+ext_errno cst86xx_unregister_handle(const cst86xx_ctrl_ops *peri_data);\r
+ext_errno cst86xx_reset(void);\r
+void cst86xx_resume_reset(void);\r
+void cst86xx_delay(uint32_t ms);\r
+\r
+ext_errno cst86xx_tp_i2c_data_read(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_len);\r
+ext_errno cst86xx_tp_i2c_cmd_write(uint16_t cmd);\r
+ext_errno cst86xx_tp_i2c_reg_write(uint16_t reg_addr, uint16_t reg_cfg);\r
+ext_errno cst86xx_tp_i2c_data_write(uint16_t reg_addr, uint8_t *data_buf, uint32_t data_len);\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.c b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.c
new file mode 100644 (file)
index 0000000..22fa202
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2022-04-12\r
+ */\r
+\r
+#include "cst86xx_drv1.h"\r
+#include "touch_screen_def.h"\r
+#include "cst86xx_ctrl.h"\r
+#include "i2c.h"\r
+#include "debug_print.h"\r
+#include "hal_i2c.h"\r
+\r
+static ext_errno cst86xx_drv_init(cst86xx_ctrl_ops *config)\r
+{\r
+    ext_errno ret;\r
+    cst86xx_ctrl_ops *ops = config;\r
+\r
+    if (ops == NULL) {\r
+        tp_err("peripheral ops is empty!");\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    if (ops->bus_init == NULL) {\r
+        tp_err("peripheral bus_init func is empty!");\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    ret = ops->bus_init(&(ops->attr));\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("CST86XX bus_init fail! ret = 0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    ret = cst86xx_init();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("CST86XX init fail! ret = 0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_drv_deinit(void)\r
+{\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_drv_get_info(uint8_t *data, uint8_t data_len)\r
+{\r
+    return cst86xx_irq_callback(data, data_len);\r
+}\r
+\r
+static ext_errno cst86xx_drv_suspend(void)\r
+{\r
+    return cst86xx_set_power_mode(MC_TP_SUSPEND_SCAN);\r
+}\r
+\r
+static ext_errno cst86xx_drv_resume(void)\r
+{\r
+    return cst86xx_set_power_mode(MC_TP_RESUME_SCAN);\r
+}\r
+\r
+static ext_errno cst86xx_drv_sleep(void)\r
+{\r
+    return cst86xx_set_power_mode(MC_TP_SLEEP_WORK_MODE);\r
+}\r
+\r
+touch_peripheral_api g_cst86xx_api = {\r
+    .touch_init = cst86xx_drv_init,\r
+    .touch_deinit = cst86xx_drv_deinit,\r
+    .touch_get_tpinfo = cst86xx_drv_get_info,\r
+    .touch_suspend = cst86xx_drv_suspend,\r
+    .touch_resume = cst86xx_drv_resume,\r
+    .touch_sleep = cst86xx_drv_sleep,\r
+    .touch_bus_init = cst86xx_host_peripheral_init,\r
+    .register_callback = cst86xx_register_handle,\r
+    .unregister_callback = cst86xx_unregister_handle,\r
+};\r
+\r
+cst86xx_ctrl_ops g_cst86xx_ctrl = {\r
+    .attr = {\r
+        .int_gpio = CST86XX_INT_GPIO,\r
+        .i2c_id = CST86XX_I2C_BUS,\r
+        .i2c_speed = I2C_SPEED_MODE_SS,\r
+    },\r
+    .bus_init = (cst86xx_bus_init)cst86xx_host_peripheral_init,\r
+};\r
+\r
+void *touch_screen_get_api(void)\r
+{\r
+    return ((void *)&g_cst86xx_api);\r
+}\r
+\r
+void *touch_screen_get_peri_attr(void)\r
+{\r
+    return ((void *)&g_cst86xx_ctrl);\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.h b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_drv1.h
new file mode 100644 (file)
index 0000000..199d7db
--- /dev/null
@@ -0,0 +1,14 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2022-04-12\r
+ */\r
+\r
+#ifndef CST86XX_DRV1_H\r
+#define CST86XX_DRV1_H\r
+\r
+void *touch_screen_get_api(void);\r
+void *touch_screen_get_peri_attr(void);\r
+\r
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.c b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.c
new file mode 100644 (file)
index 0000000..e1aaa3e
--- /dev/null
@@ -0,0 +1,414 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2021-05-29\r
+ */\r
+\r
+#include "cst86xx_touch1.h"\r
+#include "time.h"\r
+#include "soc_osal.h"\r
+#include "osal_timer.h"\r
+#include "osal_mutex.h"\r
+#include "securec.h"\r
+#include "cst86xx_ctrl.h"\r
+#include "tcxo.h"\r
+#include "cmsis_os2.h"\r
+#include "common_def.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+cst86xx_drv_data g_cst86xx_drv = {\r
+    .chip_status = CST86XX_NOT_READY,\r
+    .ops_mux = {0},\r
+    .int_mask = CST86XX_INT_MASK,\r
+    .work_status = CST86XX_WORK_INVALID,\r
+    .fw_upgrade_flag = TD_FALSE,\r
+    .gesture_wakeup = TD_FALSE,\r
+    .host_dev_init_flag = TD_FALSE,\r
+    .chip_info = CST86XX_DEVICE_INFO,\r
+    .p_void = NULL,\r
+};\r
+\r
+static ext_errno cst86xx_config(void);\r
+\r
+static ext_errno cst86xx_parse_input(void)\r
+{\r
+    static uint8_t touch_input[CST86XX_TOUCHINFO_LEN] = { 0 };\r
+    uint16_t touch_status;\r
+    uint16_t x_axis;\r
+    uint16_t y_axis;\r
+    uint8_t model;\r
+    static uint32_t point_count=0;\r
+\r
+    ext_errno ret = cst86xx_tp_i2c_data_read(CST86XX_POINT_STATUS_REG, touch_input, CST86XX_TOUCHINFO_LEN);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:touch input read error! ret = 0x%x", ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    model = touch_input[1];\r
+       tp_print("TOUCH:ctp_get_data finger_num=%d", model);\r
+       /*\r
+       0 fingure meas UP EVENT, so return FALSE;\r
+       And now we only support FIVE fingures at most, so if more than 5 fingures also return FALSE \r
+       */      \r
+       if (model > 2)\r
+       {\r
+               return EXT_ERR_FAILURE;\r
+       }\r
+       \r
+    x_axis = (((uint16_t)(touch_input[2]&0x0f))<<8) | touch_input[3];\r
+    y_axis = (((uint16_t)(touch_input[4]&0x0f))<<8) | touch_input[5];\r
+    tp_print("TOUCH:finger[%d], x:%d, y:%d", model, x_axis, y_axis);\r
+       \r
+    if (model == 0)\r
+    {\r
+        g_cst86xx_drv.touch_msg.tp_event = MC_TP_RELEASE;\r
+        point_count=0;\r
+    }else{\r
+        if (point_count==0)\r
+        {\r
+            g_cst86xx_drv.touch_msg.tp_event = MC_TP_PRESS;\r
+        }else{\r
+            g_cst86xx_drv.touch_msg.tp_event = MC_TP_MOVE;\r
+        }\r
+        point_count++;\r
+    }\r
+        \r
+    g_cst86xx_drv.touch_msg.tp_event_info.x_axis[0] = x_axis;\r
+    g_cst86xx_drv.touch_msg.tp_event_info.y_axis[0] = y_axis;\r
+    g_cst86xx_drv.touch_msg.tv_usec = (uint32_t)uapi_tcxo_get_ms();\r
+    \r
+    // } else {\r
+    //     g_cst86xx_drv.touch_msg.tp_event = MC_TP_INVALID;\r
+    //     tp_warning("TOUCH:parse wrong touchstatus %d", touch_status);\r
+    //     return EXT_ERR_SUCCESS;\r
+    // }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_irq_callback(uint8_t *data_buf, uint8_t data_len)\r
+{\r
+    unused(data_len);\r
+    ext_errno ret;\r
+    int32_t mem_ret;\r
+    uint16_t reg_write;\r
+    if (g_cst86xx_drv.chip_status != CST86XX_READY) {\r
+        tp_warning("TOUCH: not ready skip read");\r
+        return EXT_ERR_SUCCESS;\r
+    }\r
+\r
+    g_cst86xx_drv.touch_msg.tp_event = MC_TP_INVALID;\r
+\r
+    if ((g_cst86xx_drv.work_status == CST86XX_WORK_NORMAL) || (g_cst86xx_drv.work_status == CST86XX_WORK_STANDBY)) {\r
+        g_cst86xx_drv.irq_count++;\r
+        ret = cst86xx_parse_input();\r
+        if (ret != EXT_ERR_SUCCESS) {\r
+            cst86xx_reset();\r
+            tp_err("TOUCH: parse input fail, ret = 0x%x", ret);\r
+            return EXT_ERR_FAILURE;\r
+        }\r
+    }\r
+\r
+    mem_ret = memcpy_s(data_buf, sizeof(input_event_info), &(g_cst86xx_drv.touch_msg), sizeof(input_event_info));\r
+    if (mem_ret != EOK) {\r
+        tp_err("TOUCH:mem cpy error, ret = 0x%x", mem_ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_configuration(void)\r
+{\r
+    ext_errno ret;\r
+    uint16_t reg_read;\r
+ \r
+    tp_print("ctp_cst0_init enter ");\r
+\r
+    /* Read Firmware Version */\r
+    reg_read = 0;\r
+    ret = cst86xx_tp_i2c_data_read(CST86XX_FIRMWARE_VERSION, (uint8_t *)&reg_read, 1);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    g_cst86xx_drv.firmware_version = reg_read;\r
+\r
+    /* Read Minor Firmware Version */\r
+    reg_read = 0;\r
+    ret = cst86xx_tp_i2c_data_read(CST86XX_FACTORY_ID, (uint8_t *)&reg_read, 1);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    g_cst86xx_drv.vendor_id = reg_read;\r
+\r
+    /* Read Hw ID */\r
+    reg_read = 0;\r
+    ret = cst86xx_tp_i2c_data_read(CST86XX_HW_ID, (uint8_t *)&reg_read, 1);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("configuration error (read chip id) 0x%x", ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    g_cst86xx_drv.chip_id = reg_read;\r
+    tp_print("chip_id = 0x%x FW_ver = 0x%x factory_id = 0x%x",\r
+    g_cst86xx_drv.chip_id,\r
+    g_cst86xx_drv.firmware_version,\r
+    g_cst86xx_drv.vendor_id);\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_suspend(void)\r
+{\r
+    ext_errno ret;\r
+    uint16_t reg_write;\r
+    uint8_t retry_times = 0;\r
+\r
+    if (g_cst86xx_drv.work_status == CST86XX_WORK_SLEEP) {\r
+        tp_print("TOUCH:alread suspend");\r
+        return EXT_ERR_SUCCESS;\r
+    }\r
+\r
+    // cst86xx_reset();//唤醒IC\r
+\r
+    /* Send Sleep Cmd */\r
+    reg_write = CST86XX_SLEEP_CMD;\r
+    for (retry_times = 0; retry_times < CST86XX_INIT_RETRY_TIMERS; retry_times++) {\r
+        ret = cst86xx_tp_i2c_reg_write(CST86XX_SLEEP_CMD,0x03);\r
+        if (ret == EXT_ERR_SUCCESS) {\r
+            break;\r
+        }\r
+        osDelay(CST86XX_GENERAL_DELAY_10);\r
+    }\r
+   if (retry_times == CST86XX_INIT_RETRY_TIMERS) {\r
+        tp_err("suspend: overtimes %d", retry_times);\r
+        goto suspend_exit;\r
+    }\r
+    osDelay(CST86XX_GENERAL_DELAY_10);\r
+\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_SLEEP;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+\r
+suspend_exit:\r
+\r
+    tp_err("TOUCH:suspend failed 0x%x", ret);\r
+\r
+    return EXT_ERR_FAILURE;\r
+}\r
+\r
+ext_errno cst86xx_resume(void)\r
+{\r
+    ext_errno ret;\r
+    uint8_t retry_times = 0;\r
+\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_RESUME;\r
+\r
+    for (; retry_times < CST86XX_INIT_RETRY_TIMERS; retry_times++) {\r
+        ret = cst86xx_config();\r
+        if (ret != EXT_ERR_SUCCESS) {\r
+            tp_err("resume: post err %d", ret);\r
+            /* retry delay 200ms */\r
+            osDelay(CST86XX_GENERAL_DELAY_200);\r
+        } else {\r
+            break;\r
+        }\r
+    }\r
+\r
+    if (retry_times == CST86XX_INIT_RETRY_TIMERS) {\r
+        tp_err("resume: overtimes %d", retry_times);\r
+        goto resume_exit;\r
+    }\r
+\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_NORMAL;\r
+\r
+    /* Enable Irq */\r
+    // cst86xx_set_irq_mode(CST86XX_IRQ_ENABLE, CST86XX_INT_MASK);\r
+\r
+    return EXT_ERR_SUCCESS;\r
+\r
+resume_exit:\r
+\r
+    /* Enable Irq */\r
+    // cst86xx_set_irq_mode(CST86XX_IRQ_DISABLE, CST86XX_INT_MASK);\r
+\r
+    tp_err("resume failed 0x%x", ret);\r
+\r
+    return EXT_ERR_FAILURE;\r
+}\r
+\r
+ext_errno cst86xx_get_power_mode(uint32_t *power_mode)\r
+{\r
+    if (power_mode == NULL) {\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    *power_mode = (uint32_t)(g_cst86xx_drv.work_status);\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_set_standby_mode(void)\r
+{\r
+    ext_errno ret;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_set_sleep_mode(void)\r
+{\r
+    ext_errno ret;\r
+\r
+    ret = cst86xx_suspend();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:cst86xx set suspend fail 0x%x", ret);\r
+    }\r
+\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_SLEEP;\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_set_normal_mode(void)\r
+{\r
+    ext_errno ret;\r
+    uint16_t reg_write;\r
+\r
+    if (g_cst86xx_drv.work_status == CST86XX_WORK_NORMAL) {\r
+        return EXT_ERR_SUCCESS;\r
+    }\r
+\r
+    ret = cst86xx_config();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+    // cst86xx_set_irq_mode(CST86XX_IRQ_ENABLE, CST86XX_INT_MASK);\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_NORMAL;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_set_power_mode(tp_work_mode power_mode)\r
+{\r
+    ext_errno ret = EXT_ERR_SUCCESS;\r
+\r
+    switch (power_mode) {\r
+        case MC_TP_SLEEP_WORK_MODE:\r
+        case MC_TP_SUSPEND_SCAN:\r
+            ret = cst86xx_set_sleep_mode();\r
+            break;\r
+        case MC_TP_NORMAL_WORK_MODE:\r
+        case MC_TP_RESUME_SCAN:\r
+            ret = cst86xx_set_normal_mode();\r
+            break;\r
+        case MC_TP_STANDBY_WORK_MODE:\r
+            ret = cst86xx_set_standby_mode();\r
+            break;\r
+        default:\r
+            tp_err("TOUCH:cst86xx not support powermode 0x%x", power_mode);\r
+            ret = EXT_ERR_FAILURE;\r
+            break;\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
+static ext_errno cst86xx_config(void)\r
+{\r
+    ext_errno ret;\r
+\r
+    /* Step 1 hardware reset */\r
+    ret = cst86xx_reset();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:Init reset fail 0x%x", ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    /* Step 3 configuration */\r
+    ret = cst86xx_configuration();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:init config fail 0x%x", ret);\r
+        return EXT_ERR_FAILURE;\r
+    }\r
+\r
+    /* Record Status For Init */\r
+    g_cst86xx_drv.chip_status = CST86XX_READY;\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_NORMAL;\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+static ext_errno cst86xx_resource_deinit(void)\r
+{\r
+    g_cst86xx_drv.work_status = CST86XX_WORK_INVALID;\r
+    g_cst86xx_drv.fw_upgrade_flag = TD_FALSE;\r
+    osal_mutex_destroy(&g_cst86xx_drv.ops_mux);\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+ext_errno cst86xx_init(void)\r
+{\r
+    ext_errno ret = EXT_ERR_FAILURE;\r
+    ext_errno err_ret;\r
+\r
+    /* create tp operation mutex */\r
+    if (g_cst86xx_drv.ops_mux.mutex == NULL) {\r
+        ret = osal_mutex_init(&(g_cst86xx_drv.ops_mux));\r
+        if (ret != EXT_ERR_SUCCESS) {\r
+            tp_err("TOUCH:cst86xx init create mux lock fail 0x%x", ret);\r
+            return EXT_ERR_FAILURE;\r
+        }\r
+    }\r
+\r
+    /* get tp operater mutex */\r
+    ret = osal_mutex_lock_timeout(&g_cst86xx_drv.ops_mux, CST86XX_OPERATER_MUTEX_WAIT_TIME);\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:cst86xx init wait mux lock fail 0x%x", ret);\r
+        goto init_fail;\r
+    }\r
+\r
+    /* tp hardware reset and init */\r
+    ret = cst86xx_config();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:cst86xx init fail 0x%x", ret);\r
+        goto init_fail;\r
+    }\r
+\r
+    /* release tp operater mutex */\r
+    osal_mutex_unlock(&g_cst86xx_drv.ops_mux);\r
+\r
+    tp_print("TOUCH:cst86xx init succ!");\r
+    return EXT_ERR_SUCCESS;\r
+\r
+init_fail:\r
+    /* release tp operater mutex */\r
+    osal_mutex_unlock(&g_cst86xx_drv.ops_mux);\r
+    err_ret =  cst86xx_resource_deinit();\r
+    if (err_ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH:delete mux lock err! ret = 0x%x", err_ret);\r
+    }\r
+    return ret;\r
+}\r
+\r
+ext_errno cst86xx_deinit(void)\r
+{\r
+    ext_errno ret = cst86xx_resource_deinit();\r
+    if (ret != EXT_ERR_SUCCESS) {\r
+        tp_err("TOUCH: cst86xx deinit fail! ret = 0x%x", ret);\r
+        return ret;\r
+    }\r
+\r
+    return EXT_ERR_SUCCESS;\r
+}\r
+\r
+void cst86xx_get_chip_id(uint16_t *chip_id)\r
+{\r
+    *chip_id = g_cst86xx_drv.chip_id;\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.h b/code/sdk/drivers/peripheral/touch/cst86xx_touch/cst86xx_touch1.h
new file mode 100644 (file)
index 0000000..5250e76
--- /dev/null
@@ -0,0 +1,358 @@
+/*\r
+ * Copyright (c) @CompanyNameMagicTag 2021-2022. All rights reserved.\r
+ * Description: cst86xx touch driver.\r
+ * Author: @CompanyNameTag\r
+ * Create: 2021-05-29\r
+ */\r
+\r
+#ifndef CST86XX_TOUCH1_H\r
+#define CST86XX_TOUCH1_H\r
+\r
+#include "stdio.h"\r
+#include "soc_errno.h"\r
+#include "soc_osal.h"\r
+#include "touch_screen_def.h"\r
+#include "platform_core.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* cst86xx definitions */\r
+/* max wait time */\r
+#define CST86XX_OPERATER_MUTEX_WAIT_TIME 3000 /* operater tp mutex timeout ms */\r
+#define CST86XX_CMCP_WAIT_TIMEOUT        1000\r
+/* define some properties value */\r
+#define CST86XX_ENABLE                   0x0001\r
+#define CST86XX_DISABLE                  0x0000\r
+#define CST86XX_DATA_LEN                 2\r
+#define CST86XX_POWERON_DELAY            100\r
+#define CST86XX_POWEROFF_DELAY           100\r
+#define CST86XX_RESETHIGH_DELAY          10\r
+#define CST86XX_CLEARINT_DELAY           10\r
+#define CST86XX_FIRMWAREON_DELAY         200\r
+#define CST86XX_INIT_RETRY_TIMERS        3\r
+#define CST86XX_SETMODE_RETRY_TIMERS     3\r
+#define CST86XX_SOFTRESET_RETRY_TIMES    10\r
+#define CST86XX_RETRY_TIMES              10\r
+#define CST86XX_DEVICE_INFO              "cst,cst86xx"\r
+#define CST86XX_DEVICE_INFO_SIZE         sizeof(CST86XX_DEVICE_INFO)\r
+#define CST86XX_MAX_SUPPORTED_FINGER_NUM 1\r
+#define CST86XX_POINT_MODE               1\r
+#define CST86XX_CALIB_TOUCH_MODE         0x07\r
+#define CST86XX_REGDATA_SHIFT            8\r
+#define CST86XX_GENERAL_DELAY_1          1\r
+#define CST86XX_GENERAL_DELAY_5          5\r
+#define CST86XX_GENERAL_DELAY_10         10\r
+#define CST86XX_GENERAL_DELAY_20         20\r
+#define CST86XX_GENERAL_DELAY_25         25\r
+#define CST86XX_GENERAL_DELAY_30         30\r
+#define CST86XX_GENERAL_DELAY_50         50\r
+#define CST86XX_GENERAL_DELAY_100        100\r
+#define CST86XX_GENERAL_DELAY_200        200\r
+#define CST86XX_GENERAL_DELAY_500        500\r
+#define CST86XX_GENERAL_RETRY_1          1\r
+#define CST86XX_GENERAL_RETRY_2          2\r
+#define CST86XX_GENERAL_RETRY_3          3\r
+#define CST86XX_GENERAL_RETRY_4          4\r
+#define CST86XX_GENERAL_RETRY_10         10\r
+#define CST86XX_RAWDATA_DELAY_FOR_HOST   100\r
+#define CST86XX_FW_JUMP_CODE             0x0048\r
+#define CST86XX_REPORT_RATE              60\r
+#define CST86XX_PIXEL_THRESHOLD          5\r
+\r
+#ifndef CST86XX_RES_MAX_X\r
+#define CST86XX_RES_MAX_X 453\r
+#endif\r
+\r
+#ifndef CST86XX_RES_MAX_Y\r
+#define CST86XX_RES_MAX_Y 453\r
+#endif\r
+\r
+#ifndef CST86XX_POINT_TRESHHOLD\r
+#define CST86XX_POINT_TRESHHOLD 0x19\r
+#endif\r
+\r
+#define CST86XX_TOUCHINFO_LEN      (6)\r
+\r
+#define CST86XX_INT_NONE            0x0000\r
+#define CST86XX_INT_MASK            0x081F\r
+#define CST86XX_PALM_MASK           0x0010\r
+#define CST86XX_FIRMWARE_SIZE       48\r
+#define ZTW_PAGE_SIZE_128          128\r
+#define ZTW_PAGE_SIZE_64           64\r
+#define ZTW_SECTOR_SIZE            8\r
+#define ZTW_CHIPID_F400            0xF400\r
+#define ZTW_CHIPID_E240            0xE240\r
+#define ZTW_CHIPID_E700            0xE700\r
+#define ZTW_CHIPID_E548            0xE548\r
+#define ZTW_CHIPID_E538            0xE538\r
+#define ZTW_CHIPID_E532            0xE532\r
+#define ZTW_VENDOR_ID              0x5A49\r
+#define CST86XX_CHIP_ID             0xE628\r
+/* define touch info offset */\r
+#define CST86XX_STATUSL_OFFSET   0\r
+#define CST86XX_STATUSH_OFFSET   1\r
+#define CST86XX_EVENTL_OFFSET    2\r
+#define CST86XX_EVENTH_OFFSET    3\r
+#define CST86XX_XL_OFFSET        4\r
+#define CST86XX_XH_OFFSET        5\r
+#define CST86XX_YL_OFFSET        6\r
+#define CST86XX_YH_OFFSET        7\r
+#define CST86XX_WIDTH_OFFSET     8\r
+#define CST86XX_SUBSTATUS_OFFSET 9\r
+/* define data shift and mask */\r
+#define CST86XX_SHIFT_8_BIT  8\r
+#define CST86XX_SHIFT_16_BIT 16\r
+#define CST86XX_SHIFT_24_BIT 24\r
+#define CST86XX_MASK_BYTE    0xFF\r
+/* define CST86XX_HIGH_SPEED_DMA rely on iic dma support */\r
+#ifdef CST86XX_HIGH_SPEED_DMA\r
+#define CST86XX_TOUCH_POINT_MODE 0\r
+#else\r
+#define CST86XX_TOUCH_POINT_MODE 1\r
+#endif\r
+\r
+#define CST86XX_SEC_MODE        48\r
+#define CST86XX_NORMAL_MODE     5\r
+#define CST86XX_DND_MODE        11 /* mutual cap */\r
+#define CST86XX_SELF_DND_MODE   17 /* self cap */\r
+#define CST86XX_DNDSKIP_CNT     1\r
+#define CST86XX_SELFDNDSKIP_CNT 1\r
+/* Config Reg Info */\r
+#define CST86XX_REG_CMD_ENABLE    0xC000\r
+#define CST86XX_REG_CHIP_ID       0xCC00\r
+#define CST86XX_REG_INTN_CLEAR    0xC004\r
+#define CST86XX_REG_NVM           0xC002\r
+#define CST86XX_REG_NVM_VPP       0xC003\r
+#define CST86XX_REG_NVM_WP        0xC104\r
+#define CST86XX_REG_PROGRAM_START 0xC001\r
+#define CST86XX_POWER_CTL_BEGIN   0x000A\r
+#define CST86XX_POWER_CTL_END     0x000B\r
+#define CST86XX_CALIB_CTL1        0xC003\r
+#define CST86XX_CALIB_CTL2        0xC104\r
+#define CST86XX_SDRAM_RESET       0x0FF8\r
+#define CST86XX_REPORT_REG        0x0186  /* 设置中断上报频率 */\r
+#define CST86XX_PIXEL_THRESHOLD_REG 0x00C3\r
+/* Register Map */\r
+#define CST86XX_SLEEP_CMD                     0xE5\r
+#define CST86XX_FIRMWARE_VERSION              0xA9\r
+#define CST86XX_FACTORY_ID                    0xAA\r
+#define CST86XX_HW_ID                         0xA7\r
+#define CST86XX_POINT_STATUS_REG              0x01\r
+\r
+#ifndef CST86XX_TSP_X_CHANNEL_NUM\r
+#define CST86XX_TSP_X_CHANNEL_NUM 6\r
+#endif\r
+\r
+#ifndef CST86XX_TSP_Y_CHANNEL_NUM\r
+#define CST86XX_TSP_Y_CHANNEL_NUM 6\r
+#endif\r
+\r
+#define CST86XX_TSP_DND_NUM     (CST86XX_TSP_X_CHANNEL_NUM * CST86XX_TSP_Y_CHANNEL_NUM)\r
+#define CST86XX_TSP_SELFDND_NUM (CST86XX_TSP_X_CHANNEL_NUM + CST86XX_TSP_Y_CHANNEL_NUM)\r
+\r
+/* firmware info */\r
+#define CST86XX_FIRMWARE_VERSION_L            0\r
+#define CST86XX_FIRMWARE_VERSION_H            1\r
+#define CST86XX_FIRMWARE_VERSION_OFFSET       52\r
+#define CST86XX_FIRMWARE_MINOR_VERSION_OFFSET 56\r
+#define CST86XX_FIRMWARE_DATA_VERSION_OFFSET  60\r
+#define CST86XX_FIRMWARE_OFFSET_ZERO          0\r
+#define CST86XX_FIRMWARE_CONVERT_DATA_STEP    2\r
+#define CST86XX_FIRMWARE_CONVERT_DATA_OFFSET  1\r
+/* file op code */\r
+#define CST86XX_FILE_ERROR (-1)\r
+#define CST86XX_FILE_OK    0\r
+/* upgrade info */\r
+#define CST86XX_FWGRADE_CMD_NUM 3\r
+/* rawdata info */\r
+#define CST86XX_RAWDATA_CMD_NUM 2\r
+\r
+/* self_dnd dnd parameter */\r
+#define CST86XX_SEC_SELF_DND_N_COUNT      15\r
+#define CST86XX_SEC_SELF_DND_U_COUNT      2\r
+#define CST86XX_SEC_SELF_DND_FREQUENCY    80\r
+\r
+#define CST86XX_SEC_DND_N_COUNT           27\r
+#define CST86XX_SEC_DND_U_COUNT           3\r
+#define CST86XX_SEC_DND_FREQUENCY         240\r
+\r
+/* host peripheral typedef */\r
+typedef ext_errno (*tp_irq_callback)(void);\r
+\r
+/* CST86XX driver typedef */\r
+typedef enum {\r
+    CST86XX_POWERDOWN = 0,\r
+    CST86XX_POWERUP,\r
+} cst86xx_sw_power_status;\r
+\r
+typedef enum {\r
+    CST86XX_WORK_NORMAL = 0,\r
+    CST86XX_WORK_STANDBY,\r
+    CST86XX_WORK_GETCMCP,\r
+    CST86XX_WORK_SLEEP,\r
+    CST86XX_WORK_SUSPEND,\r
+    CST86XX_WORK_RESUME,\r
+    CST86XX_WORK_INVALID,\r
+} cst86xx_work_status;\r
+\r
+typedef enum {\r
+    CST86XX_NOT_READY = 0,\r
+    CST86XX_READY,\r
+} cst86xx_device_status;\r
+\r
+typedef enum {\r
+    MC_BUTTON_RELEASE = 0, /* button release */\r
+    MC_BUTTON_PRESSED = 1, /* button pressed */\r
+} button_event_type;\r
+\r
+typedef enum {\r
+    MC_TOUCHKEY_EVENT_PRESS = 0,\r
+    MC_TOUCHKEY_EVENT_RELASSE,\r
+    MC_TOUCHKEY_EVENT_LONG_PRESS,\r
+    MC_TOUCHKEY_EVENT_INVALID,\r
+} touch_key_event_type;\r
+\r
+typedef enum {\r
+    CST86XX_GESTURE_NONE = 0,\r
+    CST86XX_GESTURE_SIGNAL_CLICK = 1,\r
+    CST86XX_GESTURE_DOUBLE_CLICK = 2,\r
+    CST86XX_GESTURE_SLIDE_UP = 4,\r
+    CST86XX_GESTURE_SLIDE_DOWN = 5,\r
+} cst86xx_gesture_event;\r
+\r
+typedef enum {\r
+    CST86XX_IRQ_DISABLE = 0,\r
+    CST86XX_IRQ_ENABLE,\r
+} cst86xx_irq_status;\r
+\r
+typedef enum {\r
+    MC_TP_NORMAL_WORK_MODE = 0, /* tp normal mode */\r
+    MC_TP_STANDBY_WORK_MODE,    /* tp idle mode */\r
+    MC_TP_BOOTLOADER_WORK_MODE,\r
+    MC_TP_SLEEP_WORK_MODE,\r
+    MC_TP_SUSPEND_SCAN,\r
+    MC_TP_RESUME_SCAN,\r
+    MC_TP_MAX_MODE,\r
+} tp_work_mode;\r
+\r
+typedef enum {\r
+    MC_TP_UPGRADE_NEED_FLAG,\r
+    MC_TP_UPGRADE_START_ASYN,\r
+    MC_TP_UPGRADE_STATUS,\r
+    MC_TP_UPGRADE_SYNC,\r
+} mc_tp_upgrade;\r
+\r
+typedef struct {\r
+    uint32_t reset_gpio;\r
+    uint32_t int_gpio;\r
+    i2c_bus_t i2c_id;\r
+    uint32_t i2c_baudrate;\r
+} tp_peripheral_attr;\r
+\r
+typedef struct {\r
+    uint16_t button_code;\r
+} button_dev_info;\r
+\r
+typedef struct {\r
+    uint16_t xchannel_num;\r
+    uint16_t ychannel_num;\r
+    uint16_t total_dnd_num;\r
+    uint16_t total_self_dnd_num;\r
+} cst86xx_panel_data;\r
+\r
+typedef struct {\r
+    uint32_t skip_cnt;\r
+    int16_t dnd_data[CST86XX_TSP_DND_NUM];\r
+    int16_t self_dnd_data[CST86XX_TSP_SELFDND_NUM];\r
+} cst86xx_tsp_rawdata;\r
+\r
+typedef enum {\r
+    MC_TP_RAW_DATA,\r
+    MC_TP_BASE_DATA,\r
+    MC_TP_NOS_DATA,\r
+    MC_TP_SIG_DATA,\r
+    MC_TP_FT_DATA,\r
+    MC_TP_NT_DATA,\r
+    MC_TP_MAX_DATA,\r
+    MC_TP_CM_CP_DATA,     /* 7, CM CP data */\r
+    MC_TP_INT_COUNT_DATA, /* 8, TP Int count */\r
+    MC_TP_NOISE_METRICS_DATA,\r
+    MC_TP_DATA_STRUCTURE_DATA,\r
+    MC_TP_PANEL_SCAN_CM_DATA,\r
+    MC_TP_PANEL_SCAN_CP_DATA,\r
+    MC_TP_START_RAW_TRANS,\r
+    MC_TP_STOP_RAW_TRANS,\r
+    MC_TP_START_GET_WATER_TEMPR, /* 15, start get and print water level and temprature */\r
+    MC_TP_STOP_GET_WATER_TEMPR,  /* 16, stop get and print water level and temprature */\r
+    MC_TP_RAW_MAX,\r
+} mc_tp_rawdata;\r
+\r
+typedef struct {\r
+    mc_tp_rawdata cmd;\r
+    uint8_t *data_buf;\r
+    uint8_t data_in_len;\r
+    uint32_t data_out_len;\r
+    uint32_t data_addr;\r
+} touch_rawdata_info;\r
+\r
+/* define for drv process talbe */\r
+typedef ext_errno (*touch_drv_upgrade_handle)(uint8_t *data_buff, uint8_t buf_len);\r
+typedef struct {\r
+    mc_tp_upgrade cmd_id;\r
+    touch_drv_upgrade_handle process_cb;\r
+} touch_drv_upgrade_proc;\r
+\r
+typedef ext_errno (*touch_hal_rawdata_handle)(uint8_t *data_buf, uint8_t buf_len);\r
+typedef struct {\r
+    mc_tp_rawdata cmd_id;\r
+    touch_hal_rawdata_handle process_cb;\r
+} touch_drv_rawdata_proc;\r
+\r
+typedef struct {\r
+    uint16_t chip_id;\r
+    uint16_t vendor_id;\r
+    uint16_t chip_hw_id;\r
+    uint8_t chip_info[CST86XX_DEVICE_INFO_SIZE];\r
+    uint16_t firmware_version;\r
+    uint16_t minor_firmware_version;\r
+    uint16_t reg_version;\r
+    uint32_t flash_fw_version;\r
+    uint16_t int_mask;\r
+    uint16_t touch_mode;\r
+    uint32_t irq_count;\r
+    uint32_t touch_count;\r
+    uint32_t page_size;\r
+    uint16_t header_size;\r
+    uint16_t image_size;\r
+    osal_mutex ops_mux;\r
+    bool fw_upgrade_flag;\r
+    bool gesture_wakeup;\r
+    bool host_dev_init_flag;\r
+    cst86xx_sw_power_status power_status;\r
+    cst86xx_work_status work_status;\r
+    cst86xx_sw_power_status chip_sw_power_status;\r
+    cst86xx_device_status chip_status;\r
+    input_event_info touch_msg;\r
+    cst86xx_panel_data panel_info;\r
+    tp_peripheral_attr dev_attr;\r
+    void *p_void;\r
+    uint32_t tp_event;\r
+} cst86xx_drv_data;\r
+\r
+ext_errno cst86xx_init(void);\r
+ext_errno cst86xx_deinit(void);\r
+ext_errno cst86xx_set_power_mode(tp_work_mode power_mode);\r
+ext_errno cst86xx_get_power_mode(uint32_t *power_mode);\r
+ext_errno cst86xx_resume(void);\r
+ext_errno cst86xx_irq_callback(uint8_t *data_buf, uint8_t data_len);\r
+ext_errno cst86xx_host_init_sample(void);\r
+\r
+void cst86xx_get_chip_id(uint16_t *chip_id);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
index e115d19..f12dd7c 100644 (file)
@@ -21,6 +21,9 @@
 #elif defined(TPTYPE_FT6X46)
 #include "ft6x46_drv1.h"
 #include "ft6x46_ctrl.h"
+#elif defined(TPTYPE_CST86XX)
+#include "cst86xx_drv1.h"
+#include "cst86xx_ctrl.h"
 #else
 #include "ztw523_drv1.h"
 #include "ztw523_ctrl.h"
 #define TOUCH_I2C_BUS            FT6X46_I2C_BUS
 #define TOUCH_INT_GPIO           FT6X46_INT_GPIO
 #define TOUCH_RESET_GPIO         FT6X46_RESET_GPIO
+#elif defined(TPTYPE_CST86XX)
+#define TOUCH_I2C_BUS            CST86XX_I2C_BUS
+#define TOUCH_INT_GPIO           CST86XX_INT_GPIO
+#define TOUCH_RESET_GPIO         CST86XX_RESET_GPIO
 #else
 #define TOUCH_I2C_BUS            ZTW523_I2C_BUS
 #define TOUCH_INT_GPIO           ZTW523_INT_GPIO
@@ -464,6 +471,10 @@ void touch_screen_resume(void)
     {
         ft6x46_resume();
     }
+#elif defined(TPTYPE_CST86XX)
+    touch_peripheral_api *touch_ptr = (touch_peripheral_api*)touch_screen_get_api();
+    ext_errno ret = touch_ptr->touch_resume();
+    if (ret != EXT_ERR_SUCCESS) { tp_err("touch resume ret=0x%x", ret); }
 #else
     ztw523_resume();
 #endif
@@ -491,6 +502,10 @@ void touch_screen_restart(void)
     ztw523_resume();
 #elif defined(TPTYPE_FT6X46)
     ft6x46_resume();
+#elif defined(TPTYPE_CST86XX)
+    touch_peripheral_api *touch_ptr = (touch_peripheral_api*)touch_screen_get_api();
+    ext_errno ret = touch_ptr->touch_resume();
+    if (ret != EXT_ERR_SUCCESS) { tp_err("touch resume ret=0x%x", ret); }
 #else
     ztw523_resume();
 #endif
index b5fa55f..00b192f 100644 (file)
@@ -77,6 +77,7 @@
 #include "cywee_hal.h"
 #include "bluetooth/include/BluetoothModelC.h"
 #include "custom_save_runtime.h"
+#include "ppg_hal.h"
 
 errcode_t uapi_create_osThread_custom(app_task_definition_t *task_cfg)
 {
@@ -1425,15 +1426,31 @@ int uapi_callVolumeGet(void)
 
 void power_on_cat1(void)
 {
-    uapi_cat1_power_on(1);
+    #if defined(FD230) && !defined(BOARD_W9)
+    uapi_cat1_power_on(1);    
     uapi_cat1_reset(0);
+    #else
+    uapi_cat1_reset(0);
+    uapi_cat1_power_on(1);  
+    uapi_cat1_bat_on(1);
+    osDelay(900);
+    uapi_cat1_power_on(0);  
+    #endif
+
 }
 
 void power_off_cat1(void)
 {
+    #if defined(FD230) && !defined(BOARD_W9)
     uapi_cat1_reset(1);
-    uapi_cat1_power_on(0);
+    uapi_cat1_power_on(0); 
+    #else
+    uapi_cat1_bat_on(0);
+    uapi_cat1_reset(1);
+    uapi_cat1_power_on(1); 
+    #endif
 }
+
 //设置4G能力开关是否开启
 void uapi_set4GCapability(bool isopen)
 {
@@ -1855,7 +1872,7 @@ void lcd_getid(uint32_t *id)
         }
     }
 }
-
+#ifdef TPTYPE_FT6X46
 #include "ft6x46_ctrl.h"
 #include "ft6x46_touch1.h"
 #define FTS_REG_CHIP_ID                                0xA3
@@ -1932,6 +1949,8 @@ void touch_getstate(void)
     PRINT("Screen On state : %d\r\n",state);
 }
 
+#endif
+
 #include "MMC5603.h"
 #include "mmc5603_hal.h"
 #include "mag_service.h"
@@ -2396,11 +2415,6 @@ uint32_t uapi_calendar_recover_date(void)
 //     get_current_time(&tv, &tm);
 // }
 
-void uapi_ppg_get_id(uint8_t *chip_id)
-{
-    hx3695_get_id(chip_id);
-}
-
 #include "hal_i2c.h"
 #include "i2c.h"
 #define CUSTOM_I2C_TIME_MAX 3
@@ -2915,7 +2929,7 @@ errcode_t custom_i2c_test(void)
     unsigned char mmc_id = 0;
     uint8_t cywee_id = 0;
 
-    uapi_ppg_get_id(&ppg_id);
+    ppg_id = ppg_get_chip_id();
     if(ppg_id != 0x65)
         return ERRCODE_FAIL;
     PRINT("ppg_id[%x] \n",ppg_id);
@@ -3065,7 +3079,7 @@ void uapi_aging_test(uint32_t test_time)
         send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_PPG_TEST);
         LOS_Msleep(6000);
         send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);
-        uapi_ppg_get_id(&ppg_id);
+        ppg_id = ppg_get_chip_id();
         //if(ft_result.gr_data_final < 10000 || ft_result.red_data_final < 10000 || ft_result.ir_data_final < 10000)
         if(ppg_id != 0x65)
         {
index eba7bcf..b9f3b58 100644 (file)
@@ -337,7 +337,7 @@ void uapi_cywee_get_version(char *databuf,uint8_t len);
 void uapi_cywee_save_mac_key(const uint8_t *key_data,uint16_t len);
 uint8_t* uapi_cywee_get_mac_key(void);
 void uapi_get_sleep_date_on_log(char *time);
-void uapi_ppg_get_id(uint8_t *chip_id);
+
 
 
 int32_t uapi_microhone_switch(bool isopen);
index cdf4af5..26a2646 100644 (file)
@@ -343,9 +343,9 @@ static uint32_t custom_touch_getstate(uint8_t *para, uint32_t paraLen, char *str
 {
 
     UNUSED(strCommonCmd);
-
+#ifdef TPTYPE_FT6X46
     touch_getstate();
-
+#endif
     return ERRCODE_SUCC;
 }
 
@@ -436,8 +436,9 @@ static uint32_t custom_get_tpinfo(uint8_t *para, uint32_t paraLen, char *strComm
 
     UNUSED(strCommonCmd);
 
-
+#ifdef TPTYPE_FT6X46
     get_tp_info(&x,&y);
+#endif
 
     return ERRCODE_SUCC;
 }
@@ -478,8 +479,7 @@ static uint32_t custom_get_ppg_id(uint8_t *para, uint32_t paraLen, char *strComm
 {
 
     UNUSED(strCommonCmd);
-    uint8_t chip_id = 0;
-    uapi_ppg_get_id(&chip_id);
+    uint8_t chip_id = ppg_get_chip_id();
     wstp_print("ppg_id[%x]\n",chip_id);
     return ERRCODE_SUCC;
 }
index 16aded5..69a2d4b 100755 (executable)
@@ -272,6 +272,7 @@ static void pm_enter_deep_sleep(void)
     pm_enter_wfi();
     lpc_forbid_deepsleep();
 #endif
+#ifndef SUPPORT_GNSS
 #ifndef FT_SINGLE_UART
     uint16_t status = pmu_lpm_wakeup_get_status(LPM_EVT_ACTION, PMU_LPM_MCPU_UART_H1_RX_WAKEUP);
 #else
@@ -280,6 +281,7 @@ static void pm_enter_deep_sleep(void)
     if (status != 0) {
         pm_wkup_event_by_uart_callback();
     }
+#endif
     pm_wkup_prepare(PM_SLEEP_DS);
     pm_sleep_info_record(SLP_INFO_DEEPSLEEP);
     reg16_setbit(0x520003e4, 0x3);  // open mdam clock after deepsleep
diff --git a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230-r/libgfx_rm.a b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230-r/libgfx_rm.a
new file mode 100644 (file)
index 0000000..aa0af42
Binary files /dev/null and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230-r/libgfx_rm.a differ
index 18778c1..12f9d8b 100644 (file)
Binary files a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230/libgfx_rm.a and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-fd230/libgfx_rm.a differ
diff --git a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9-r/libgfx_rm.a b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9-r/libgfx_rm.a
new file mode 100644 (file)
index 0000000..aa0af42
Binary files /dev/null and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9-r/libgfx_rm.a differ
diff --git a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9/libgfx_rm.a b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9/libgfx_rm.a
new file mode 100644 (file)
index 0000000..12f9d8b
Binary files /dev/null and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-w9/libgfx_rm.a differ
index 464b21c..40adc6f 100644 (file)
Binary files a/code/sdk/middleware/services/gui/hal/display/brandy-native-js-fd230/libdisplay_gfx.a and b/code/sdk/middleware/services/gui/hal/display/brandy-native-js-fd230/libdisplay_gfx.a differ
diff --git a/code/sdk/middleware/services/gui/hal/display/brandy-native-js-w9/libdisplay_gfx.a b/code/sdk/middleware/services/gui/hal/display/brandy-native-js-w9/libdisplay_gfx.a
new file mode 100644 (file)
index 0000000..40adc6f
Binary files /dev/null and b/code/sdk/middleware/services/gui/hal/display/brandy-native-js-w9/libdisplay_gfx.a differ
index aa7a1f3..6f04c26 100644 (file)
Binary files a/code/sdk/middleware/services/gui/uikit/brandy-native-js-fd230/libuikit_ext.a and b/code/sdk/middleware/services/gui/uikit/brandy-native-js-fd230/libuikit_ext.a differ
diff --git a/code/sdk/middleware/services/gui/uikit/brandy-native-js-w9/libuikit_ext.a b/code/sdk/middleware/services/gui/uikit/brandy-native-js-w9/libuikit_ext.a
new file mode 100644 (file)
index 0000000..6f04c26
Binary files /dev/null and b/code/sdk/middleware/services/gui/uikit/brandy-native-js-w9/libuikit_ext.a differ
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230-r/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230-r/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..cddab45
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230-r/libx_vfs_private.a differ
index e94333a..6feed1e 100644 (file)
Binary files a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230/libx_vfs_private.a and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-fd230/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-r-w9/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-r-w9/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..cddab45
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-r-w9/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9-r/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9-r/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..cddab45
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9-r/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..6feed1e
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-w9/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230-r/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230-r/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..d8a248b
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230-r/libfs_yaffs2.a differ
index 5d415bd..aaa672c 100644 (file)
Binary files a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230/libfs_yaffs2.a and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-fd230/libfs_yaffs2.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r-w9/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r-w9/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..d8a248b
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r-w9/libfs_yaffs2.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9-r/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9-r/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..d8a248b
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9-r/libfs_yaffs2.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..aaa672c
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-w9/libfs_yaffs2.a differ
index 911e68a..eae8d08 100644 (file)
Binary files a/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-fd230/libams.a and b/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-fd230/libams.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-w9/libams.a b/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-w9/libams.a
new file mode 100644 (file)
index 0000000..eae8d08
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-w9/libams.a differ
index 5cd4368..d4c567f 100644 (file)
Binary files a/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-fd230/libace.a and b/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-fd230/libace.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-w9/libace.a b/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-w9/libace.a
new file mode 100644 (file)
index 0000000..d4c567f
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-w9/libace.a differ
index 2c35a7e..265db3d 100644 (file)
Binary files a/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-fd230/libbms.a and b/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-fd230/libbms.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-w9/libbms.a b/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-w9/libbms.a
new file mode 100644 (file)
index 0000000..265db3d
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-w9/libbms.a differ
index 4c6839d..c395070 100644 (file)
Binary files a/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-fd230/libjerryscript.a and b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-fd230/libjerryscript.a differ
diff --git a/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-w9/libjerryscript.a b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-w9/libjerryscript.a
new file mode 100644 (file)
index 0000000..c395070
Binary files /dev/null and b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-w9/libjerryscript.a differ
index 4482204..b98934a 100755 (executable)
@@ -71,8 +71,9 @@ def make_all_in_one_packet_8M(pack_style_str):
     recovery_bx = recovery_bin + "|0x70050000|0x40000|100"
 
     upload_app_fwpkg = os.path.join(PKG_DIR, "fwpkg", "brandy", "upload_app.fwpkg")
-
-    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", "brandy-ssb", "ssb.bin")
+    
+    ssb_target = "%s-ssb" % pack_style_str
+    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", ssb_target, "ssb.bin")
     if not os.path.exists(ssb):
         ssb = os.path.join(bin_dir, "ssb.bin")
     print("ssb_path: ", ssb)
@@ -137,7 +138,8 @@ def make_all_in_one_packet_fd230(pack_style_str):
 
     upload_app_fwpkg = os.path.join(PKG_DIR, "fwpkg", "brandy", "upload_app.fwpkg")
 
-    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", "brandy-ssb", "ssb.bin")
+    ssb_target = "%s-ssb" % pack_style_str
+    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", ssb_target, "ssb.bin")
     if not os.path.exists(ssb):
         ssb = os.path.join(bin_dir, "ssb.bin")
     print("ssb_path: ", ssb)
@@ -204,7 +206,9 @@ def make_all_in_one_packet_16M(pack_style_str):
 
     upload_app_fwpkg = os.path.join(PKG_DIR, "fwpkg", "brandy", "upload_app.fwpkg")
 
-    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", "brandy-ssb", "ssb.bin")
+    ssb_target = "%s-ssb" % pack_style_str
+    ssb = os.path.join(SDK_DIR, "output", "brandy", "acore", ssb_target, "ssb.bin")
+    
     if not os.path.exists(ssb):
         ssb = os.path.join(bin_dir, "ssb.bin")
     print("ssb_path: ", ssb)
index f5dc215..f2290de 100755 (executable)
@@ -1,4 +1,12 @@
 #!/bin/bash
+###
+ # @Author: penglei 1624952103@qq.com
+ # @Date: 2024-12-06 17:15:16
+ # @LastEditors: penglei 1624952103@qq.com
+ # @LastEditTime: 2025-06-05 19:13:08
+ # @FilePath: /FD230/tools/scripts/create_project.sh
+ # @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+### 
 projectname=$1
 projectlist="
 code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js
@@ -7,15 +15,16 @@ code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-na
 code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js
 code/sdk/application/wearable/service/msg_center/brandy-native-js
 code/sdk/middleware/utils/fs/yaffs2/brandy-native-js
-code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r
 code/sdk/middleware/utils/fs/vfs/brandy-native-js
-code/sdk/middleware/utils/fs/vfs/brandy-native-js-r
 code/sdk/middleware/services/gpu/api/rm/brandy-native-js
-code/sdk/middleware/services/gpu/api/rm/brandy-native-js-r
 code/sdk/middleware/services/gui/hal/display/brandy-native-js
 code/sdk/middleware/services/gui/uikit/brandy-native-js
 "
-
+projectlist_r="
+code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-r
+code/sdk/middleware/utils/fs/vfs/brandy-native-js-r
+code/sdk/middleware/services/gpu/api/rm/brandy-native-js-r
+"
 for l in $projectlist
 do
 targetdir=$l-$projectname
@@ -26,5 +35,15 @@ mkdir -p $targetdir
 cp -r $l/* $targetdir/
 
 done
+for l in $projectlist_r
+do
+
+targetdir=`dirname $l`/brandy-native-js-$projectname-r
+echo mkdir -p $targetdir
+echo cp -r $l/* $targetdir/
 
+mkdir -p $targetdir
+cp -r $l/* $targetdir/
+
+done