当前位置:  编程技术>移动开发
本页文章导读:
    ▪haxe的nem与box2d入门例子在物体下贴图        haxe的nem与box2d入门例子在物体上贴图接上篇的例子:haxe的nem与box2d入门例子 这个例子是将一个png的图片贴到小球上,并与小球一起做自由落体运动。 首先导入3个类包: import nme.display.BitmapDa.........
    ▪ STM32 简略多任务调度        STM32 简单多任务调度        STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进.........
    ▪ 大众化理解gstreamer的调度模式       通俗化理解gstreamer的调度模式        gstreamer的官方文档里,调度的英文是schedule. 什么是schedule? 它的英文解释为" to plan that something will happen at a particular time “.在gstreamer里,调度的意义跟.........

[1]haxe的nem与box2d入门例子在物体下贴图
    来源: 互联网  发布时间: 2014-02-18
haxe的nem与box2d入门例子在物体上贴图
接上篇的例子:haxe的nem与box2d入门例子
这个例子是将一个png的图片贴到小球上,并与小球一起做自由落体运动。

首先导入3个类包:
import nme.display.BitmapData;
import nme.display.Bitmap;
import nme.Assets;

首先创建一个Circle类:
/**
 * 球体
 */
class Circle extends Sprite {
    private var radius : Float;
    private var wheel : Bitmap;
    
    public function new(x : Float, y : Float, radius : Float) {
        super();
        
        this.radius = radius;    
        this.wheel = new Bitmap(Assets.getBitmapData('img/wheel.png'));
        this.wheel.x = x - radius;
        this.wheel.y = y - radius;
        
        this.addChild(this.wheel);
    }
    
    public function move(position : B2Vec2) : Void {
        //box2d以物体的中心为原点,而nme则以左上角为原点,所有要减去圆的半径
        this.wheel.x = position.x / Settings.METERTOPIXEL - this.radius;
        this.wheel.y = position.y / Settings.METERTOPIXEL - this.radius;
    }
}

然后在createBall方法中加入:
    //添加皮肤
    var myCircle : Circle = new Circle(x, y, radius);
    wheelBodyDef.userData = myCircle;
    addChild(myCircle);

上面的代码要放在var wheelBody : B2Body = world.createBody(wheelBodyDef);之前。

按F5调试你会只会看到一个球体,这个球体自由落体后你就可以看到刚才加载的那张图片。
下面设置球体与皮肤的同步运动:
在update方法中加入同步更新位置:
    var body : B2Body = world.getBodyList();        
    while (null != body) {
        //body.m_type == 2时,物体为动态的
        if (2 == body.m_type && Std.is(body.getUserData(), Sprite)) {
            body.getUserData().move(body.getPosition());
        }
        body = body.getNext();
    }

在init方法中把drawDebug()及update()方法中的world.drawDebugData();调用去掉,按F5,加载在图片在做自由落体运动。

最后给出这个例子的下载地址:
最后给出这个例子的下载地址:
    共享链接:http://163.fm/TygF3Ie

    提取码:1x1cZAxs

原文地址:http://gentwolf.sinaapp.com/index/detail/170.html



    
[2] STM32 简略多任务调度
    来源: 互联网  发布时间: 2014-02-18
STM32 简单多任务调度

        STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理,在main函数中你可能会写成如下方式:

int main(void)
{
	while (1)
	{
		Task1(); // 调用任务1
		Task2(); // 调用任务2
	}
}

       但简单这样写的话会存在一个问题,假如任务1是一个很紧急的任务,如AD采样任务,需要不断的去执行,而任务2是一个不太紧急的任务,只要保证一段时间执行一次就行(如控制LED灯闪烁,只需要每1s钟闪烁一次),这样的话一是频繁的调用任务2占用了任务1执行的时间,二是任务2根本不需要这样频繁的执行,白白耗费了CPU的处理。因此可以考虑实现一个调度策略来解决这个问题。对于每个任务,我们可以定义这样一个结构:

typedef struct{
	  void (*fTask)(void);
	  int64u uNextTick;
	  int32u uLenTick;
}sTask;

        其中fTask为任务指针,指向具体的任务,uNextTick为该任务下一次执行的时间,uLenTick为任务的调度周期或叫调度频率,即每隔多长时间执行一次。

        按照这个结构,可以预先定义一个结构体数组,然后将要调用的任务和任务的调度时间按照如下方式罗列出来:

// 任务列表
static sTask mTaskTab[] = 
{
	 {Task_SysTick,    0, 0}
	,{Task1,           0, 10}    // 10ms执行一次
	,{Task2,           0, 200}   // 200ms执行一次	
};

        其中第一个任务Task_SysTick为计算系统时间的任务,用以获取上电后运行的时间(Task_SysTick任务相关代码附在文章后面)。这里默认任务下一次执行的时间为0,在main函数中,不断的轮询这个数组,然后将当前任务的下一次调用时间和当前时间比较,如果发现轮到该任务执行,就执行该任务,执行完成后,将该任务的下一次执行时间设为当前时间加任务的调度时间,然后按照此方法去执行下一个需要执行的任务,代码如下:

	while (1)
	{
		// 任务循环
		for (i = 0; i < ARRAYSIZE(mTaskTab); i++)
		{
			if (mTaskTab[i].uNextTick <= GetTimingTick())
			{
				mTaskTab[i].uNextTick += mTaskTab[i].uLenTick;
				mTaskTab[i].fTask();	
			}
		}
	} 

        这样,就可以对多个任务做一个简单的调度,以后添加任务时只需要在mTaskTab表中添加即可,需要强调的是,由于执行每个任务也需要耗费时间,就会导致一个任务的实际调度周期可能会比设定的调度周期要长,这样会存在时间不准的情况,当然这仅仅是适合于对轮询周期不是很严格的任务,如果想要任务在严格的时间周期内执行或者需要更精确的时间处理,则必须采用定时器的方式了。

附:

        完整的main文件代码:

#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif

// 任务结构
typedef struct{
	  void (*fTask)(void);
	  u64 uNextTick;
	  u32 uLenTick;
}sTask;


// 任务列表
static sTask mTaskTab[] = 
{
	 {Task_SysTick,    0, 0}
	,{Task1,           0, 10}   // 10ms执行一次	
	,{Task2,           0, 200}  // 200ms执行一次	
	
	// 在这之前添加任务
};

/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
	int i = 0;
	// 硬件初始化
	HW_init();
	// 初始化系统Tick任务
	dev_SysTick_init(void);
	// ...  
	while (1)
	{
		// 任务循环
		for (i = 0; i < ARRAYSIZE(mTaskTab); i++)
		{
			if (mTaskTab[i].uNextTick <= GetTimingTick())
			{
				mTaskTab[i].uNextTick += mTaskTab[i].uLenTick;
				mTaskTab[i].fTask();	
			}
		}
	} 
}


Task_SysTick任务相关代码:

volatile int64u g_TimingTick = 0;
volatile int64u g_TimingTickOld = 0;

//=================================================================================================
//【函 数 名 称】 void dev_SysTick_init(void)
//【参       数】 
//【功       能】 初始化
//【返   回  值】 None
//【创   建  者】 2010-07-27 firehood
//=================================================================================================
void dev_SysTick_init(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = 65535;               
	TIM_TimeBaseStructure.TIM_Prescaler = 36000-1; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;    
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	
	TIM_SetCounter(TIM2, 0);

	/* TIM enable counter */
	TIM_Cmd(TIM2, ENABLE);
}

//=================================================================================================
//【函 数 名 称】 void GetTimingTick(void)
//【参       数】 
//【功       能】 获取MCU启动后的运行时间
//【返   回  值】 MCU启动后的运行时间,单位ms
//【创   建  者】 2010-07-27 firehood
//=================================================================================================
int64u GetTimingTick(void)
{
	return g_TimingTick;
}

//=================================================================================================
//【函 数 名 称】 void Task_SysTick(void)
//【参       数】 
//【功       能】 Tick任务,从TIM2获取系统时间
//【返   回  值】 None
//【创   建  者】 2010-07-27 firehood
//=================================================================================================
void Task_SysTick(void)
{
	int16u temp = TIM_GetCounter(TIM2);

	if (temp > 1000)
	{
		TIM_SetCounter(TIM2, 0);
		g_TimingTickOld = g_TimingTickOld + temp;
		temp = 0;
	}
	g_TimingTick = g_TimingTickOld + temp;
}

 


    
[3] 大众化理解gstreamer的调度模式
    来源: 互联网  发布时间: 2014-02-18
通俗化理解gstreamer的调度模式

        gstreamer的官方文档里,调度的英文是schedule. 什么是schedule? 它的英文解释为" to plan that something will happen at a particular time “.在gstreamer里,调度的意义跟它基本差不多。在gstreamer里,调度的目的主要有以下几个:

      (1)在适当的时候通知每个元件去完成相应的任务,确保这些职责的执行。这个任务,就是数据处理。

      (2)每个元件都从它的上一个源元件获取数据,并为下一个元件准备好数据。即获取输入数据,处理数据,最后输出数据给下一个元件。   

       在GStreamer中,衬垫(pad)是用来在元件间协商连接和数据流的。衬垫可以看作元件间互相连接的“接口”,数据流通过这些接口流入流出元件。Pad具有特殊的数据处理能力:衬垫可以限制通过它的数据类型。只有当两个衬垫允许通过的数据类型兼容时才可以将它们连接起来。

    第一个source元件,只有src衬垫,即只输出数据;最后一个sink(输出)元件,即只接收输入数据;管道中其他元件,一般都有一个sink衬垫和source衬垫。

    Gstreamer的调度,也可以理解为不同元件的pad连接和通信,即处理pad之间的数据流的启动,暂停,继续和终止。

      调度模式有两种:PUSH模式和PULL模式。在此,我将其翻译为推送模式和拉拽模式。

1.什么是推送模式和拉拽模式?

      Downstream(下游) 和 Upstream(上游)模式是管道中用于描述数据流动方向的术语。从source元件到sink元件的数据流动称作“下游”,从sink元件到source元件的数据流动模式称为“上游”模式。

       在推送模式下,上游元件通过调用gst_pad_push,实现把数据“推送”给下游元件。

       在拉拽模式下,下游元件通过请求调用gst_pad_pull_range(),从上游组件那里把数据“拉”过来。

     上面提到的数据,一般是一个缓存(buffer).

      用得最多的数据流模式是推送模式。拉拽模式可以用在某些特殊情况下,如demuxer元件。

2.推送模式是怎么工作的?

       
  .----------.             .----------.           .----------.
  | element1 |      | element2 |      | element3 |
 ...        src -> sink       src -> sink       ...
  '----------'               '----------'            '----------'      

      如上图所示,假设元件1的src pad工作在push模式。当元件1打算把数据推送给下一个与之相连接的元件2时,元件1的src pad通常产生数据,元件2的相应sink pad(相对于元件1,被称为peer pad)接受数据。通常,元件1会实现一个loop函数,该函数会被循环调用直到它返回值为假。该函数可以根据需要进行阻塞循环调用,但当元件1的pad解除激活时,该函数就解除阻塞(即不再调用)。

       元件2的pad通过实现一个链条(chain)函数来接受元件1的pad生产的数据。

       push模式的实现是由元件1通过gst_pad_push()来实现的. 产生数据的元件pad, 注意:这个方法根据传入的pad参数,具体调用相应的链接函数xx_chain。该方法的函数原型是GstFlowReturngst_pad_push (GstPad * pad, GstBuffer * buffer)。在该函数的实现里,通过调用 GST_PAD_CHAINFUNC (peer) (peer, buffer)来把数据推送给下一个元件,同时下一个元件根据他来接受数据。

 

3.拉拽模式是怎么工作的?

      工作在PULL模式的pad, 通常只能从实现了pull_range函数的pad那里“拉”数据。

   .----------.             .----------.          .----------.         .----------.
  | element1 |      | element2 |      | demuxer|    |decoder|
 ...        src -> sink            src -> sink          src -> sink     ...
   '----------'             '----------'           '----------'            ----------'     

        如上图所示,我们假设demuxer元件的sink pad工作在pull模式,并是以plugin的形式加载到工作管道中。在demuxer对象实例初始化时候,我们一般首先会新建和初始化一个sink pad,并通过调用gst_pad_set_activate_function (avi->sinkpad, gst_xx_demux_sink_activate)来设置pad激活时的函数指针。于是,当pipeline状态变化时,尤其是demuxer元件从READY切换到PAUSE状态时,会进行如下图所示的函数调用:

 

在上图的激活函数里,会去激活demuxer 的sink pad, 它是通过遍历所有的sink pads,调用activate_pads来激活pad的。如下图所示:

在gst_pad_set_actie函数里,最后会调用(GST_PAD_ACTIVATEFUNC(pad)) (pad); 被调用这个宏函数由于在demuxer元件里设置了函数指针gst_pad_set_activate_function (avi->sinkpad, gst_xx_demux_sink_activate),于是其实对于demuxer组件来说,执行的是gst_xx_demux_sink_activate函数。

     通常,这个函数会调用gst_pad_check_pull_range,并根据前面图中的element2的pad(称之为peer pad)是否实现了XX_pull_range函数,来判断demuxer 元件的sink pad应该激活在pull模式还是push模式。我们这里讨论激活在pull模式的情况。

         当激活在pull模式下,我们会给demux起一个task, task函数为gst_xx_demux_loop函数。gst_avi_demux_loop函数会从peer pad 拉拽数据。拉拽完数据后,通常会把数据push 到下一个元件的sink pad.

 

4.调度模式是如何动态决定的

      这个问题的答案可以在上面第3节找到找到。这里总结下:当一个pad被激活时,gst_element_pad_activate()函数被调用. 这个pad随后可以根据上游的能力(upstream capabilities,实际上为是否实现了XX_pull_range)来决定激活在push模式还是pull模式。如果一个pad没有activate函数,gstreamer core将默认为它激活在push模式。

 

5.getrange函数

     当gst_pad_check_pull_range调用时,peer pad的getrange函数被调用。事实上,前面说过,一个上游pad只有实现了getrange函数,才能被下游的pad以pull的模式调用它从而拉拽数据。下游pad对getrange函数的调用,是通过以宏的形式---GST_PAD_GETRANGEFUNC (pad)来传递的。而该宏的赋值,是上游的可以支持pull模式的元件在初始化的时候,调用gst_pad_set_getrange_function 设置的。

6.chain函数(链条函数)

    当上游元件的pad调用gst_pad_push函数时,下游元件pad的chain函数被调用。



 

         

 

 


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
编程语言 iis7站长之家
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3