整板业务,就是整板需要实现的功能。
这是主业务流程,需要调用大部分类对象提供的服务函数。
是基于业务流程来设计的函数处理流程。
而之前所述,设计的各个类的操作集,均是为了服务于业务逻辑而设计。
来看看工程的main函数做了哪些工作,
SystemManager xsys;
int main()
{
init_platform();
xsys.open_device();
xsys.main_loop();
cleanup_platform();
return 0;
}
定义了一个全局的system manager对象,
在main中,调用init_platform函数,这是生成C语言的example工程时,会包含的代码,这里我们移植过来。对应的,在最后, 调用cleanup_platform函数。
在这两个函数之间,就是我们需要调用的主流程业务逻辑。
首先调用了system manager的功能级函数open_device。
然后调用了system manager的业务级函数main_loop。
1)主流程业务逻辑
void SystemManager::main_loop()
{
syslog("camera boot ok, goto loop....\r\n");
boot_state_ = 1;
xout_.set_sdi_reset(1);
watchdog_start();
while(1)
{
//喂狗
watchdog_feed();
xmotor_.recv_loop();
xhost_.recv_loop();
xaec_.compute();
motor_loop();
sensor_loop();
}
}
这里可以看到,主流程是一个while(1)循环,说明工程使用了前后台程序架构。
main_loop工作在后台,各个中断ISR工作在前台。
前后台之间,通过共享变量来通信。
前台函数中修改共享变量,后台函数中轮询共享变量,并进行对应的处理。
这里面使用的xmotor_,是MotorMCU这个类的对象,以内嵌的方式,作为system manager的一个成员对象存在。关于MotorMCU这个类,后面再讲。
这里面使用的xhost_,是CameraHost这个类的对象,以内嵌的方式,作为system manager的一个成员对象存在。关于CameraHost这个类,后面再讲。
这里面使用的xaec_,是AutoExpGain这个类的对象,以内嵌的方式,作为system manager的一个成员对象存在。关于AutoExpGain这个类,后面再讲。
2)motor业务逻辑
void SystemManager::motor_loop()
{
static u32 tv0 = 0;
u32 tv1 = get_timestamp();
u32 dlt_time = ABS_DEC(tv0, tv1);
if (dlt_time < 35) {
return;
}
tv0 = tv1;
switch(zoom_state_)
{
case 1://视场放大
{
set_dzoom_scale_inc(0);
if (get_dzoom_scale_state() == 2) {
xmotor_.set_zoom_up(zoom_speed_);
}
}break;
case 2://视场缩小
{
xmotor_.set_zoom_down(zoom_speed_);
if (xmotor_.get_optics_focus_state() == 2) {
set_dzoom_scale_dec(0);
}
}break;
}
switch(focus_state_)
{
case 1:
{
xmotor_.set_focus_far(focus_speed_);
}break;
case 2:
{
xmotor_.set_focus_near(focus_speed_);
}break;
default:
break;
}
}
这里使用了一个static变量tv0,由于是在函数内定义的,所以编译时的全名类似于motor_loop_tv0。
其中使用了一个宏拟函数ABS_DEC,
#define ABS_DEC(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
通过计算时间戳的差值,来决定loop是否执行。从而避免过度操作。
之后的代码中,使用了两个FSM进行状态对应的处理。
zoom_state_和focus_state_,是两个共享变量,在前台ISR中被修改,在后台的motor_loop中,被轮询处理。
3)sensor业务逻辑
void SystemManager::sensor_loop()
{
static u32 tv0 = 0;
u32 tv1 = get_timestamp();
u32 dlt_time = ABS_DEC(tv0, tv1);
if (dlt_time < 1000 * 1) {
return;
}
tv0 = tv1;
//设置统计亮度均值的区域
set_agc_roi();
if (debug_mode_ == 0)
return;
}
这里使用了一个static变量tv0,由于是在函数内定义的,所以编译时的全名类似于sensor_loop_tv0。
其中使用了一个宏拟函数ABS_DEC。通过计算时间戳的差值,来决定loop是否执行。从而避免过度操作。