异步函数async和await

背景 最近在回头看nfd项目 的源码,看到了使用async和await的js代码,因此想了解一下代码运行的机制。 一个例子 function SicBo() { return new Promise((resolve, reject) => { console.log("开始摇") setTimeout(() => { let n = parseInt(Math.random() * 6 + 1, 10) resolve(n) }, 1000) }) } 上述代码的执行过程如下: 立即执行 console.log("开始摇") —— ✅ 马上输出。 启动一个“1秒后执行的任务” —— 通过 setTimeout(...) 注册了一个回调,1 秒后执行。 返回一个 Promise 对象,这个 Promise 会在 1 秒后变成“完成状态”并给出点数。 如果直接调用这个函数: function test() { const result = SicBo() console.log('骰子结果:', result) } test() 调用输出如下: 开始摇 骰子结果: Promise { <pending> } 显然并不是我们想要的结果 异步函数的一般调用: SicBo().then(result => { console.log('骰子结果:', result) }) 这种写法最大的弊端是会产生回调地狱,即调用多个异步函数产生嵌套,导致代码可读性变差。 ...

April 10, 2025 · 1 min · laning

TG机器人通知IP地址

背景 公网IPv4政策的收紧,包括不限于不能使用DDNS服务解析到未备案域名,因此使用TG机器人API服务,定时检测IP地址,若IP变化则自动更新 项目地址 Raspberry-Pi/shell/telegram-ip-bot.sh at master · laningya/Raspberry-Pi · GitHub 部署过程 获取ChatID API_TOKEN="YOUR_BOT_TOKEN" curl -s "https://api.telegram.org/bot$API_TOKEN/getUpdates" | jq '.result[0].message.chat.id' 脚本填入Bot的API Token,以及自行判断需要设置代理 添加crontab定时任务 */30 * * * * /bin/bash /root/telegram-ip-bot.sh > /dev/null 2>&1 & 参考文档 Telegram Bot API

April 9, 2025 · 1 min · laning

Emby反代及HTTPS配置教程

Nginx配置 server { listen 443 ssl; server_name your.domain.com; # Security / XSS Mitigation Headers add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; # ssl的设置 ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; ssl_session_timeout 5m; # 禁止ip访问 if ($host ~ ^\d+\.\d+\.\d+\.\d+$) { return 404; } # 防止爬虫获取header,直接访问/就返回502,其他的路径才行,app观看不影响,不用这个 location = / { return 502; } location / { resolver 1.1.1.1 ipv6=off; if ($host != $server_name) { return 403; } proxy_pass https://www.emby.com; # ssl pass相关的设置 proxy_ssl_name www.emby.com; proxy_ssl_server_name on; proxy_set_header Host www.emby.com; set $magpiecdn "$scheme://$server_name:$server_port"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Protocol $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header MagpieCDN $magpiecdn; proxy_buffering off; } location /***cdn { resolver 1.1.1.1 ipv6=off; proxy_pass https://$arg_load.emby.com; # ssl pass相关的设置 proxy_ssl_name $arg_load.emby.com; proxy_ssl_server_name on; proxy_set_header Host $arg_load.emby.com; proxy_buffering on; proxy_max_temp_file_size 50m; } } 说明: ...

March 1, 2025 · 1 min · laning

通过LangBot将大模型接入到Telergram

项目地址 GitHub - RockChinQ/LangBot: 😎丰富生态、🧩支持扩展、🦄多模态 - 大模型原生即时通信机器人平台 | 适配 QQ / 微信(企业微信、个人微信)/ 飞书 / 钉钉 / Discord / Telegram 等消息平台 | 支持 ChatGPT、DeepSeek、Dify、Claude、Gemini、xAI Grok、Ollama、LM Studio、阿里云百炼、火山方舟、SiliconFlow、Qwen、Moonshot、ChatGLM、SillyTraven、MCP 等 LLM 的机器人 / Agent | LLM-based instant messaging bots platform, supports Discord, Telegram, WeChat, Lark, DingTalk, QQ 部署过程 Git 克隆项目: git clone https://github.com/RockChinQ/LangBot cd LangBot 启动容器: docker compose up 在 LangBot 中填写信息并启动 将Telegram Bot的API Token 填写到platform.json中。 { "adapter": "telegram", "enable": true, "token": "xxxxxxx" }, 填写完成后启动 LangBot,若成功配置,日志中会出现[02-02 16:48:15.263] manager.py (68) - [INFO] : 初始化平台适配器 1: telegram的字样,保持 LangBot 运行。 ...

February 14, 2025 · 1 min · laning

数字集成电路设计实验——FIR滤波器

1. 课程信息 ■实验地点:清水河校区KB239 ■ **实验时间:**2021.04.16 ■ **实验时长:**3小时(4节课) 2. 实验要求 1. The fir filter input sampling rate is 100kHz, the filter passband single-sideband bandwidth is 20kHz, the out-of-band suppression is 90dB, and the in-band ripple is 1dB. 2. The filter coefficient needs to be fixed-point, and the effective number of ADCs is 24bit. The filter coefficient bit width is self-defined. 思考(加分项): 1. The relationship between filter passband, stopband, out-of-band rejection and filter order ...

April 21, 2023 · 2 min · laning

数字集成电路设计实验——时钟

1. 课程信息 实验地点:清水河校区KB239 **实验时间:**2021.04.9 实验时长: 3小时(4节课) 2. 实验要求 驱动板上数码管显示当前时间(包含时、分、秒) ①建议定义n个按键,如用于功能切换 (tab)、校时+1(up)及确认(ok) ②整点报时: 7:00~23:00间每个整点蜂鸣器响1s 思考(加分项): 1. 如何添加闹钟功能? 2. 如何添加定时器功能? 3. 设计模N计数器的测试向量集,撰写testbench进行验证测试 3. 设计与实现 3.1 电路功能说明 (包括各个模块功能、关键代码分析,可以使用文字、框图、功能表、状态图等进行说明) 3.1.1 顶层设计 3.1.2 timing_module 接收PLL多次分频得到的1Hz时钟信号作为模块的时钟信号,设置17位数据用来存储当前时间([5:0]表示秒,[11:6]表示分,[16:12]表示小时),当秒达到59时,则下一次操作为秒位置0,同时分位加1,分钟与小时的关系依次类推。同时当load信号使能时,即设置时间功能打开时,数据位数据将被加载进来的数据覆盖。 // timing_module.v `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: UESTC // Engineer: Qy_Ley // // Create Date: 2021/03/14 15:06:37 // Design Name: Digital Clock for EES331 // Module Name: timing_module // Project Name: Digital Clock // Target Devices: EES331 // Tool Versions: Vivado 18.3 // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module timing_module( input i_clk_1Hz, input i_load, input i_rstn, input i_ena, input [16:0] i_load_hms, // [5:0] for sec, [11:6] for min, [16:12] for hour, BCD coding output [16:0] o_hms // [5:0] for sec, [11:6] for min, [16:12] for hour, BCD coding ); // wire m_co_sec, m_co_min; // Carry output from second & minute counter reg ld; reg [16:0] ld_cnt; reg [4:0] hour_cnt; reg [5:0] min_cnt,sec_cnt; always @(posedge i_clk_1Hz) begin ld <= i_load; ld_cnt <= i_load_hms; end //clock cross-domain buffer always @(posedge i_clk_1Hz or negedge i_rstn) begin if(!i_rstn) begin hour_cnt <= 0; min_cnt <= 0; sec_cnt <= 0; end else if(ld) begin {hour_cnt, min_cnt, sec_cnt} <= ld_cnt; end else if(i_ena) begin if(sec_cnt == 6'd59) begin sec_cnt <= 0; if(min_cnt == 6'd59) begin min_cnt <= 0; if(hour_cnt == 5'd23) begin hour_cnt <= 0; end else begin hour_cnt <= hour_cnt+1; end end else begin min_cnt <= min_cnt+1; end end else begin sec_cnt <= sec_cnt+1; end end end /* Complete the counter for second, minute, hour */ assign o_hms = {hour_cnt, min_cnt, sec_cnt}; endmodule 3.1.3 control_module 为系统控制的模块,采用有限状态机的描述方式,如图: ...

April 15, 2023 · 4 min · laning

数字集成电路设计实验——流水灯

1. 课程信息 实验地点:****** **实验时间:**2021.03.25 实验时长: 3小时(4节课) 2. 实验要求 驱动板上LED1 ~LED8按如下2个模式循环闪烁: ① 每个灯亮1s灭1s,从右至左依次闪烁,共8次 ② 每个灯亮1s灭0.5s,从左至右间隔闪烁,共4次 思考(加分项): 如何使用按键控制流水灯的闪烁时间? 如:按一次亮1s,再按一次变为亮0.5s。 2. 如何使用按键控制流水模式? 如:按一次8个灯依次闪烁,再按一次LED2/4/6/8间隔闪烁 3. 设计与实现 3.1 实验步骤 在Vivado中创建工程,并添加.v文件 阅读实验提供的源码文件并完善部分代码 添加testbeach文件,做仿真分析 添加.xdc文件(将模块引脚与开发板引脚绑定),并下板验证 3.2 电路功能说明 (包括各个模块功能、关键代码分析,可以使用文字、框图、功能表、状态图等进行说明) 3.2.1 关键代码分析 计数器模块 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) counter1 <= 32'd0; else if(!led_control)//led_control==0为状态1 if (counter1 < 32'd200_000_000)//系统时钟100M,计数器计200M次即2s counter1 <= counter1 + 1'b1; else counter1 <= 32'd0; else counter1 <= 32'd0; //状态2时,counter1置零不计数 end //通过led_control信号来控制计数器2秒或1.5秒,并分别记为counter1和counter2 模式控制模块 always @ (posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) cnt<=32'd0; else if(cnt<32'd2200_000_000) cnt<=cnt+1; else cnt<=0; end //cnt计数器来记录一轮循环,cnt<1600_000_000,即小于16秒为左移,cnt>1600_000_000时为右移。 led移动 always @(posedge sys_clk or negedge sys_rst_n) begin if(!sys_rst_n) led1<=8'b00000001; else if (!led_control) begin if (counter1 == 32'd200_000_000) led1 <= led1<<1; //左移1位 else led1 <= led1; end else led1 <= 8'b00000001;//状态2时led1就在led2基础上左移,状态转换时即可无缝衔接 end always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) led <= 8'b00000001; else case (led_control) 0 : if(counter1 < 32'd100_000_000) led = led1; else led = 8'b0; //进入状态1时,先让灯亮1s,再将移位寄存器led1的值赋值给led 1 : if(counter2 < 32'd100_000_000) led = led2; else led = 8'b0; //进入状态2时,先让灯亮1s,再将移位寄存器led2的值赋值给led default : led <= led; endcase end //分别用led1和led2来表示两种状态下的led状态,led_control为0时,当达到2秒时,led1进行左移。通过counter1的值判断是否达到1秒,未达到时,将led1的值赋给led,否则led置为8’b0。led_control为1同理 3.2.2 系统级表示 ...

March 27, 2023 · 2 min · laning

GPU在并行信息处理中的应用

摘要 随着前端数据采集设备精度的不断提高,对信息处理系统的实时性、准确性提出更高的要求。而从日趋完善的计算机体系结构中,半导体工艺难以取得重大突破的情况下,想要获取更高的计算性能(信息处理能力),我们就必须探索另外一条道路——并行处理。GPU在应用于图像处理领用,其CUDA平台的支持,对于浮点运算的高效,因而作为并行信息处理的技术被广泛应用。 关键词 GPU,CUDA ,并行信息处理 1. 并行处理技术 1.1 并行处理技术介绍 并行处理或并行计算是指利用多台计算机或处理器同时执行运算任务,从而减少解决问题所需要的时间。一般可分为时间并行计算和空间并行计算。 时间上的并行计算叫做流水线处理,即多个处理器按照处理时间的先后顺序执行计算;空间上的并行是指多个处理器同时执行计算,各处理器在时间上相互独立。并行处理技术主要研究空间上的并行,即通过总线方式将多个计算机或处理器并联,从而获得更快的处理速度。 并行计算根据规模不同,分为一下几个层次。如图所示,最底层是单核指令级并行(ILP),即单个处理器,但可同时执行多条指令;其上为多核并行,即单芯片拥有多个处理器核心;再往上是多处理器并行,即通过多个芯片之间分工协作做到并行处理;最上层为集群或分布式并行,通过网络互联实现超大规模并行运算,可参考大型数据中心。 1.2 Flynn计算机体系分类 1966年,Flynn根据指令流和数据流的多倍性对计算机体系结构进行了分类。分为单指令流单数据流模式(SISD),单指令流多数据流模式(SIMD),多指令流单数据流模式(MISD),多指令流多数据流模式(MIMD)。其中SIMD和MIMD属于并行处理器。 SIMD和MIMD处理器结构示意图如图所示。SIMD只有一个控制单元,这个控制单元控制多个计算处理单元,这些处理单元共享存储器或信号进行通信。MIMD处理器拥有多个控制单元,每个控制单元控制自己的计算单元,通过共享存储器或信号进行通信。 2.CUDA GPU并行架构 CUDA是设备计算统一框架的简称(Compute Unified Device Architecture)。其目的是为了用C语言再GPU上进行编程,而无需关注图形API和GPU编程的知识。它可以运行和访问GPU设备的指令和存储空间,从而可以非常快速入门并且从GPU的并行计算中获利。再此之前,GPGPU编程需要针对特定的处理器,而不是标准的API,不能在不同GPU之间进行移植。在CUDA并行架构中,GPU被当作CPU的协处理器来运作,一些数据并行独立且计算密集的函数适合放入GPU中运行。 图为CUDA并行架构框图。底层为CUDA的组成部件,其包括:支持CUDA并行计算的GPU、支持CUDA的操作系统内核、用户模式驱动、PTX并行计算指令集。 在软件层次,CUDA提供了完备的软件开发环境,包括编译器、调试器、性能测评工具及基础库。并且支持C语言编程,从而可以支持其他高级语言,比如Java和Python。CUDA提供了两种编程接口:设备级编程接口和语言集成编程接口。 3. CUDA 硬件原理 CUDA 硬件基础结构由一组多线程流处理器(SM,Multitreaded Stream Multiprocessors)的单元组成。如图所示,SM中又有多个SP(Stream Processors)负责具体运算。多线程流处理器SM被设计成拥有可以同时执行上百个线程的能力。为了获得同时执行这么多线程的能力,CUDA从SIMD结构上发展出单指令流多线程(SIMT, Single Instruction Multiple Thread)结构。 SM多线程处理器负责创建、调度和执行线程,这些线程以32个为一组,成为一个Warp。组成同一个Warp的单独线程从同一个程序地址执行。但是他们拥有单独的指令地址计数器和独立的存储器。所以他们可以互不干扰的运行各自的指令及分支。 当多线程处理器执行一个或多个线程块时,它把他们分为独立的Warp,之后由Warp调度器进行调度。线程块中的线程根据线程号线性的分组为Warp,即前32个线程号的线程为第一个Warp,接下来32个线程号为第二个Warp,以此类推。一个Warp内的线程每次执行一条指令,所以如果Warp里的32个线程在执行时执行相同的指令路径可以使效率最大化。如果一个Warp中的线程在执行过程中产生了分支,则Warp顺序执行完每个分支,直到所有分支都执行完毕后会和到同一个指令开始执行。不同的Warp各自独立运行,在一个Warp内产生的分支不影响其他的Warp。对于一个特定的线程块,它只能在一个多线程处理器(SM)中执行。但是一个多线程处理器可以执行多个线程块。

December 19, 2022 · 1 min · laning

FPGA工程应用开发综合实验报告二

基于FPGA的BPSK信号产生器设计 2022年12月19日 摘 要 本次基于FPGA的计时器设计,在熟悉Quartus基本操作、Verilog编程语言的基本规则、SignalTap的基本应用,在前两次PN码序列产生器和DDS设计的基础上,通过分模块设计后进行连接的方式,完成基于FPGA的BPSK信号产生器设计。 本次设计分为PLL分频模块、自动复位模块、PN码生成模块、DDS模块以及IP核实现方式的NCO模块。 实验需求分析 技术指标分析 功能指标分析 PN码(Gold码)产生器模块需对传输数据进行扩频;DDS模块生成所需频率的载波信号;通过相位选择法(2选1数据选择器)来实现调制。 性能指标分析 减少信息传输延迟,调制后的信号应尽量与原数据一致。 系统方案设计 顶层设计 项目实现所要用到的时钟问题分析 时钟频率控制是FPGA设计的重要组成部分。通过上面功能指标分析,我们不难发现,实现BPSK的调制,我们需要三个时钟来完成我们的设计。一是我们需要一个时钟来控制我们的DDS模块来产生我们需要的频率的载波信号;二是我们需要一个时钟来控制PN码(Gold)码的产生;三是我们需要一个调制信息的时钟 DDS的两种实现 我们通过调用IP核和查找表法两种方法实现DDS。调用IP的好处在于设计简单,但其中的延迟为随机确定的数,在设计未完成前,我们很难确定其值为多少,而当通过查找表来实现DDS,我们能够很好的控制这个延迟,从而提升系统的性能。 PN码序列生成器 将两个PN码进行异或运算(模2加法)生成Gold码。 具体顶层设计文件截图: 模块设计 例如: 1)PLL分频模块 由上文中对系统时钟分析可知,我们需要250MHz 、5MHz、10KHz分别作为DDS系统钟、PN码生成器码钟和产生调制信息的码钟,如图1所示: 图1 PLL模块 2)自动复位模块 本模块接收PLL分频后所得的250MHz时钟信号,如图2: 图2 自动复位模块 3)PN码生成器模块 本模块接收250MHz的c0和5MHz的c1,如图3: 图3 PN码生成器模块 图5.1023位m序列产生器原理框图 如图5:为1023位m序列产生器的原理图, {an}=c1an-1+c2an-2+……+cna0 由于m序列自相关良好但是互相关特性不好且可用于产生 图6:Gold序列产生原理框图 m序列的本原多项式较少,在一些要求地址码多的系统钟m序列很难满足要求,因而引入Gold码。产生Gold码序列可以将两个m序列的移位寄存器并联再进行模2加法,如图6为生成Gold码的逻辑图。图7为顶层文件的Gold码实现。 图7:生成Gold码的顶层文件 4)DDS模块 本模块接收c0和频率控制字作为输入,32位相位信息作为输出,结构如图8所示: 图8:DDS模块 由DDS原理我们可知:K=f0/fc*2N 其中fc为250MHz,f0为25MHz,N为32,计算出K值约为429496730,输出相位信息后,通过查表的方式我们得到最终结果。 IP核加二选一数据选择器实现方式,如图9所示**:** 图9:IP核加二选一数据选择器实现 二.基于SignalTap分析重点时序 本次实验,我们理论上应该看到经过自己设计的DDS模块与调用IP核相比延迟更低。BPSK调制的基本流程如下: 调制信息与通过PN码发生器进行扩频,通过扩频操作可以降低我们调制信息的峰值,减少信息被检测的概率。 DDS模块产生我们所需频率的载波信号,将经过扩频的调制信息通过调相的方式,0和1选择相反相位,即相差为pi的,从而实现BPSK的全过程。 三.反思与总结 1.关于系统时钟c0(250MHz)难以达到 因为我们的FPGA的默认时钟频率为50MHz,想要达到250MHz对我们开发板有一些困难,所以我们可以适当降低c0的时钟频率,比如可以选择200MHz作为系统时钟。 2.总结反思 本次基于FPGA的BPSK设计实验,从了解PN码这种扩频通信的理念,到通过查找表的方式,实现直接数字频率合成技术,得到我们所需频率的载波信号,到最后通过调相的方式,将我们的信号调制到载波信号钟,从而实现BPSK。进一步熟悉了FPGA开发的整体流程以及模块化的复用思想,了解数字通信调制信息的过程。 四.参考文献 ...

December 19, 2022 · 1 min · laning

FPGA工程应用开发综合实验报告一

基于LCD的显示系统设计 2022年11月30日 摘 要 本次基于FPGA的LCD显示系统设计,在熟悉Quartus基本操作、Verilog编程语言的基本规则、SignalTap的基本应用后,通过自顶向下、分模块设计后进行连接的方式,完成控制FPGA在LCD屏幕显示内容。 本次设计分为PLL分频模块、上电复位模块、显示控制模块、显示驱动模块组成。通过分功能分模块的设计方式,便于调试,较好地完成了本次设计任务。 一、 实验需求分析 技术指标分析 (1) 功能指标分析 通过FPGA控制LCD,实现在LCD上显示自己姓名英文书写,对外提供良好的接口,可实现修改源代码来显示不同内容。 (2) 性能指标分析 二、 系统方案设计 顶层设计 图1:Cyclone IV E FPGA芯片和 LCD模块间连接示意图 表1:LCD模块引脚配置说明 分析图1、表1,我们能得到FPGA与LCD模块之间是8根数据线、5根控制线,为了简化我们程序内部的逻辑,经过分析,在本次实验中,我们只对LCD进行写操作,而误差控制我们通过增大每次写数据后的延时来减小,所以LCD_RW可以始终置0;LCD_ON始终置1;LCD_BLON可始终置1或0。 进而我们得到了下面的顶层设计 三、 模块设计 例如: 1)PLL分频模块 由于实验板载FPGA提供50MHz晶振,通过Quartus自带的PLL模块,为了更快实现在LCD上显示所需内容,设置参数,产生50MHz的时钟,作为本次设计的系统时钟,如图1所示: 图1 PLL模块 2)上电复位模块 本模块接收PLL分频后所得的50MHz时钟信号,通过Cont变量进行计数计时,便于后续模块使用,框图如图2: 图2 计数器模块 3)显示驱动模块 本模块接收系统时钟与上电复位模块输出以及显示控制模块的输出mLCD_Done;产生mLCD_Start信号、8位数据线内容和LCD_RS信号,如图3所示: 图3 显示驱动模块 在此显示之前,我们需要位LCD进行初始化操作,分析图4,我们需要配置LCD的基本功能,具体代码与分析如下: 图4 1602LCD控制指令 有限状态机分析(如图5): S0:写内容,将数据内容送给数据线,并自动跳转状态S1; S1:等待mLCD_done信号,有效时跳转到状态S2; S2:计数延时,为了简化程序,我们通过延迟来保证数据正确写入到LCD中,当延时结束,计数归零,并跳转到状态S3; S3:当S2的延时后,S3在LCD显示屏上自动向后移位,并跳转到状态S0 图5 有限状态机示意图 由编码表找到需要的字符对应的二进制表示,代码如下,映射表如图6: 图6 字符映射表 4)显示控制模块 本模块接收系统时钟与上电复位模块输出以及mLCD_start作为输入,输出为LCD_EN与mLCD_done信号,如图7: 图7 显示控制模块 ...

November 30, 2022 · 1 min · laning