Non-blocking user input in loop without ncurses

Non-blocking user input in loop without ncurses

    The title sounds a bit awkward, let my briefly explain what is it all about.

    In my program, I want to wait for user input, but at the same time, I want my other operations keep continue processing.That I define it as non-blocking user input. I want my program to wait for user input in the loop, if receives user input process it and continue wait for next user input, else continue processing other circular operations.

    Usually, people will think about using ncurses library. By using ncurses, you can easily perform non-blocking user input using timeout(0) and getch(). Refers to thencurses matrix for references.

    What if I don’t want to uses ncurses? Its there any alternatives? Sometimes I just wanna add a function which need non-blocking in a large program, I don’t want to use ncurses because it makes my print line acts differently, or some other reason.

   I have figure out a way, thanks to programmers at ##c@irc.freenode.net. It might look messy and complected, but it works the way I wanted. I uses functions of termios and select, lets look at the functions one by one.

int NoBlocking_Read()
{
    struct timeval tTV;
    fd_set tFDs;
	
    tTV.tv_sec = 0;
    tTV.tv_usec = 0;
    FD_ZERO(&tFDs);	
    FD_SET(STDIN_FILENO, &tFDs); 
    select(STDIN_FILENO+1, &tFDs, NULL, NULL, &tTV);
    return FD_ISSET(STDIN_FILENO, &tFDs);
}

    This function perform non-blocking checking on the standard input (stdin) without timeout 0, tv.tv_sec and tv.tv_usec both set to zero. select usually uses in the case where there have multiple I/O need to process, or check at the same time. But in this case, I only interested in standard input, therefore only one FD_SET(STDIN_FILENO, &fds) is trigger. For select parameters details, please check out the manual.Seems we are only interested in input, so we place out fd set at second parameter of select(), the 3rd is for output and 4th is for exception.

    Important part, after select if user input is trigger, FD_ISSET will return non zero value, else return 0. So, we now can use it like this:

<span style="font-size:18px;">while( 0 == NoBlocking_Read() )
{

}</span>

   Due to the canonical mode (标准模式)of your terminal,you need to hit enter to confirm your user input. Canonical mode means it always wait for enter to confirms the user input. If that is not your case, bellow is another function to cater that.

int  NoBlocking_Init()
{
    struct termios tTTYState;
 
    //get the terminal state
    tcgetattr(STDIN_FILENO, &tTTYState);
 
    //turn off canonical mode
    tTTYState.c_lflag &= ~ICANON;
    //minimum of number input read.
    tTTYState.c_cc[VMIN] = 1;   /* 有一个数据时就立刻返回 */

    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);

    return 0;
}

void NoBlocking_Exit()
{
    struct termios tTTYState;
 
    //get the terminal state
    tcgetattr(STDIN_FILENO, &tTTYState);
 
    //turn on canonical mode
    tTTYState.c_lflag |= ICANON;
	
    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &tTTYState);
}


    The function name might be misleading, what the function actually does is turn off the canonical mode for stdin. First, get the states of stdin of term. Next turn off the canonical by set 0 to the bits. The line of ttystate.c_cc[VMIN] is set the minimum number of user input to accept. If you set it as 2, the select will wait until 2 character is given, then it will capture as input. At last set the term state. The function actually does allow you to turn on and off the canonical mode.

    Okay, Let see how it apply to work

int main()
{ 
	char c = 0;
	NoBlocking_Init();
	while( 0 == NoBlocking_Read() )
	{
		usleep(1);
		c = fgetc(stdin);
		if(c == 'q')
		{
			exit(0);
		}
		switch (c)
		{
			case 'u':
			{
				break;
			}
			case 'd':
			{
				break;
			}			
		}		
	}	
}
    Press ‘q’ will lead the program to quit, else you will see the print of ’0′ overwhelming the screen. Observed that I am using usleep(1) inside the loop, without putting usleep, the programs is more responsive, but it uses high CPU resources. On the other hand, putting usleep(1) reduces the CPU resources and also decreases responsiveness of the program. Depend on your needs, you may choose to put it in or not.

    I have make the comparison between this application and a simple ncurses program, this program seems to use lesser memory. Couldn’t measure for CPU resources, as bothps and top shows 0.0 %.


分数阶傅里叶变换(Fractional Fourier Transform, FRFT)是对传统傅里叶变换的拓展,它通过非整数阶的变换方式,能够更有效地处理非线性信号以及涉及时频局部化的问题。在信号处理领域,FRFT尤其适用于分析非平稳信号,例如在雷达、声纳和通信系统中,对线性调频(Linear Frequency Modulation, LFM)信号的分析具有显著优势。LFM信号是一种频率随时间线性变化的信号,因其具有宽频带和良好的时频分辨率,被广泛应用于雷达和通信系统。FRFT能够更精准地捕捉LFM信号的时间和频率信息,相比普通傅里叶变换,其性能更为出色。 MATLAB是一种强大的数值计算和科学计算工具,拥有丰富的函数库和用户友好的界面。在MATLAB中实现FRFT,通常需要编写自定义函数或利用信号处理工具箱中的相关函数。例如,一个名为“frft”的文件可能是用于执行分数阶傅里叶变换的MATLAB脚本或函数,并展示其在信号处理中的应用。FRFT的正确性验证通常通过对比变换前后信号的特性来完成,比如评估信号的重构质量、信噪比等。具体而言,可以通过计算原始信号与经过FRFT处理后的信号之间的相似度,或者对比LFM信号的关键参数(如初始频率、扫频率和持续时间)是否在变换后得到准确恢复。 在MATLAB代码实现中,通常包含以下步骤:首先,生成LFM信号模型,设定其初始频率、扫频率、持续时间和采样率等参数;其次,利用自定义的frft函数对LFM信号进行分数阶傅里叶变换;接着,使用MATLAB的可视化工具(如plot或imagesc)展示原始信号的时域和频域表示,以及FRFT后的结果,以便直观对比;最后,通过计算均方误差、峰值信噪比等指标来评估FRFT的性能。深入理解FRFT的数学原理并结合MATLAB编程技巧,可以实现对LFM信号的有效分析和处理。这个代码示例不仅展示了理论知识在
<think>好的,我现在要解决用户遇到的PDS报错:“Cannot mix blocking and non-blocking assignments to variable read_en”。这个问题出现在Verilog或SystemVerilog代码中,通常是因为在同一个always块中对同一个变量同时使用了阻塞赋值(=)和非阻塞赋值(<=)。我需要一步步分析可能的原因,然后给出解决方法。 首先,我应该回忆Verilog中阻塞和非阻塞赋值的区别。阻塞赋值是按顺序执行的,而非阻塞赋值是在块结束时并行更新的。如果在同一个always块中对同一变量混合使用这两种赋值方式,会导致仿真和综合工具无法确定正确的执行顺序,从而报错。 接下来,用户可能需要了解具体的代码示例。比如,用户可能在同一个always块中写了类似以下代码: always @(posedge clk) begin if (condition) begin read_en = 1'b1; // 阻塞赋值 end else begin read_en <= 1'b0; // 非阻塞赋值 end end 这里read_en在同一块中同时用了=和<=,导致冲突。 接下来,我需要解释为什么不能混用。阻塞赋值会立即更新变量,而非阻塞赋值则在块结束后更新。混用会导致仿真结果不确定,尤其在时序逻辑中,可能引起竞争条件,使得设计行为不可预测。 然后,解决方案应该是统一赋值方式。如果是组合逻辑,应该全部使用阻塞赋值;如果是时序逻辑(如时钟触发的always块),应该统一使用非阻塞赋值。例如,用户需要检查所有对read_en的赋值,确保在同一个always块中只用一种方式。 可能还需要检查是否有多个always块对同一变量进行赋值。比如,一个always块用阻塞,另一个用非阻塞,这种情况下即使分开块,但同一变量被不同块赋值也可能导致问题。不过根据报错信息,更可能是在同一块中混用。 另外,可能的其他情况是,在同一个块中不同的分支用了不同的赋值方式,比如if和else部分分别用了阻塞和非阻塞。需要统一修改为同一种。 最后,用户可能需要一个修改后的正确示例,比如将上述例子中的阻塞赋值改为非阻塞: always @(posedge clk) begin if (condition) begin read_en <= 1'b1; // 非阻塞 end else begin read_en <= 1'b0; // 非阻塞 end end 或者,如果是组合逻辑,使用阻塞赋值: always @(*) begin if (condition) begin read_en = 1'b1; // 阻塞 end else begin read_en = 1'b0; // 阻塞 end end 同时提醒用户,组合逻辑必须覆盖所有条件,避免锁存器生成。 总结步骤:定位所有对read_en的赋值,检查是否在同一块中混用,统一修改为同一种赋值方式,确保组合或时序逻辑的正确使用。</think>在Verilog/SystemVerilog设计中,出现`Cannot mix blocking and non-blocking assignments to variable read_en`报错,表示对同一个变量`read_en`同时使用了阻塞赋值(`=`)和非阻塞赋值(`<=`)。以下是逐步分析和解决方法: --- ### **步骤1:理解报错原因** - **阻塞赋值(`=`)**:立即生效,常用于组合逻辑(如`always @(*)`)。 - **非阻塞赋值(`<=`)**:在代码块结束时更新,用于时序逻辑(如`always @(posedge clk)`)。 - **冲突场景**:在同一个`always`块中对`read_en`混用了`=`和`<=`,导致仿真和综合工具无法确定赋值顺序。 --- ### **步骤2:定位问题代码** 检查所有对`read_en`赋值的`always`块。典型错误示例如下: ```verilog // 错误示例:混合赋值 always @(posedge clk) begin if (reset) read_en = 1'b0; // 阻塞赋值(错误!) else if (condition) read_en <= 1'b1; // 非阻塞赋值(正确) end ``` --- ### **步骤3:统一赋值方式** 根据逻辑类型选择一致的赋值规则: #### **情况1:时序逻辑(时钟驱动)** - **全部使用非阻塞赋值**(`<=`) ```verilog // 正确示例:统一非阻塞赋值 always @(posedge clk) begin if (reset) read_en <= 1'b0; // 非阻塞 else if (condition) read_en <= 1'b1; // 非阻塞 end ``` #### **情况2:组合逻辑(无时钟)** - **全部使用阻塞赋值**(`=`),并确保覆盖所有分支 ```verilog // 正确示例:统一阻塞赋值 always @(*) begin if (reset) read_en = 1'b0; // 阻塞 else if (condition) read_en = 1'b1; // 阻塞 else read_en = 1'b0; // 覆盖默认情况 end ``` --- ### **步骤4:检查多always块冲突** 确保`read_en`没有在其他`always`块中被不同赋值方式操作: ```verilog // 错误示例:多always块混合赋值 always @(posedge clk) begin read_en <= new_value; // 非阻塞 end always @(*) begin read_en = another_value; // 阻塞(冲突!) end ``` - **解决方法**:一个变量只能在一个`always`块中赋值,或统一所有赋值方式。 --- ### **总结** 1. **时序逻辑**:统一使用`<=`。 2. **组合逻辑**:统一使用`=`,并覆盖所有条件分支。 3. **禁止跨always块混用**:同一变量不可在多个块中以不同方式赋值。 通过以上步骤,可彻底解决混合赋值导致的PDS报错问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值