从SOD到OOD(整板资源管理,system manager,成员函数定义,功能级服务函数)

在操作级别的服务函数之上,需要定义功能级服务函数,
这些功能级服务函数,需要调用大部分类对象提供的服务函数。
为了增强可读性,也设计了大量的操作级别的服务函数,用来为功能级服务函数提供调用。

1)自检功能

void SystemManager::selftest()
{
	xmotor_.set_motor_selftest();
}

通过调用MotorMCU这个class提供的服务函数,完成自检功能。

2)系统配置打印功能

void SystemManager::system_state(int value)
{
	syslog("system_state=%d\r\n", value);
	debug_mode_ = value;
	if (debug_mode_ == 0)
		return;

	syslog("ts=%u, host_irq=%u, mcu_irq=%u, sensor_irq=%u, sensor_frame_count=%u, focus_motor_reach_=%d\r\n", get_timestamp(), host_uart_.irq_count, mcu_uart_.irq_count, cam_uart_.irq_count, sensor_frame_count_, focus_motor_reach_);

	syslog("video_lock=%d, photo_lock=%d\r\n", xin_.get_video_lock(), xin_.get_photo_lock());

	u32 clarity = xaf_accl_.get_clarity_value();
	syslog("clarity=%d, zoom_motor=%d, focus_motor: %d\r\n", clarity, xmotor_.zoom_motor_value_, xmotor_.focus_motor_value_);

	syslog("focus: min=%d, max=%d, best=%d, focus_direct_mode=%d, focus_radio=%d\r\n", xaf_.af_min_focus_, xaf_.af_max_focus_, xaf_.af_init_focus_, xmotor_.focus_direct_mode_, focus_radio_);


	syslog("dehazing_mode=%d, hdr_mode=%d, enhance_mode=%d, awb_mode=%d, flip_mode=%d\r\n", dehazing_mode_, hdr_mode_, enhance_mode_, awb_mode_, flip_mode_);

	u32 current_hsize = 0, current_vsize = 0, max_hsize = 0, max_vsize = 0;
	xcmos_.get_current_hsize(&current_hsize);
	xcmos_.get_current_vsize(&current_vsize);
	xcmos_.get_max_hsize(&max_hsize);
	xcmos_.get_max_vsize(&max_vsize);

	syslog("C5180 size: (%d %d) (%d %d)\r\n", current_hsize, current_vsize, max_hsize, max_vsize);

	syslog("sensor crop: (%d %d %d %d)\r\n", xbayer_video_.crop_x_, xbayer_video_.crop_y_, xbayer_video_.crop_width_, xbayer_video_.crop_height_);


	syslog("sensor_uart=%d, mcu_uart=%d, host_uart=%d\r\n", ring_buffer_valid_len(&cam_uart_.recv_buff), ring_buffer_valid_len(&mcu_uart_.recv_buff), ring_buffer_valid_len(&host_uart_.recv_buff));

	...
}

在board_common.h这个H文件中定义了

#define syslog(...)			xil_printf(__VA_ARGS__)

使得syslog可以作为xil_printf的别名使用。

3)加载默认配置参数功能。

void SystemManager::load_default_config()
{
	//C5180
	xcmos_.set_aoi_hsize(sensor_width_);
	xcmos_.set_aoi_vsize(sensor_height_);
	xcmos_.set_aoi_hoff(0);
	xcmos_.set_aoi_voff(480);
	xcmos_.set_pixel_clock_rate(110);
	xcmos_.set_fixed_frame_period(33333);
	xcmos_.set_fixed_frame_period_en(1);

	xcmos_.set_digital_gain(1024);
	xcmos_.set_anglog_gain(0);
#if SENSOR_TRIGGER_ENABLE
	xcmos_.set_ignore_next_trigger(1);
	xcmos_.set_trigger_edge_selector(0);
	xcmos_.set_trigger_input(2);
	xcmos_.set_trigger_enable(1);
	xcmos_.set_exposure_mode(1);
	xout_.set_exposure_time(15000);
#else
	xcmos_.set_trigger_enable(0);
	xcmos_.set_exposure_mode(2);
	xcmos_.set_exposure_time(15000);
#endif

	//system
	set_dehazing_mode(0);
	set_color_mode(0);
	set_rgbyuv_mode(0);
	set_brightness_mode(0);
	set_brightness_value(0);
	set_contrast_mode(0);
	set_contrast_value(0);
	set_saturation_mode(1);
	set_saturation_value(22000);
	set_flip_mode(0);
	set_cursor_mode(0);
	set_cursor_x(video_width_ / 2);
	set_cursor_y(video_height_ / 2);
	set_sharpness_mode(0);
	set_hdr_mode(0);
	set_enhance_mode(0);
//	set_sync_mode(0);
	set_auto_exposure_on(0, 0);

}

注意这个函数中的几个技术点。

首先是宏开关,用于代码裁剪和代码选择。针对不同的系统配置需求,来选择不同的代码块,进入不同的处理流程。

然后是成员对象的服务函数的调用。通过在成员对象的类中,设计对应的服务函数,然后分别调用这些服务函数,可以增加程序的可读性。

然后是本类的服务函数的调用。通过在本类中,设计对应的服务函数,然后分别调用这些服务函数,可以增加程序的可读性。

4)加载配置参数功能

int SystemManager::load_config()
{
	int ret;
	union PageConfig cfg;

	int bytes = sizeof(cfg.param);
	syslog("load_config: bytes=%d\r\n", bytes);
	if (bytes > 255) {
		syslog("/-------------------------------------------------------------------------------------/\r\n");
		syslog("error: config bytes too large!\r\n");
		syslog("/-------------------------------------------------------------------------------------/\r\n");
	}

	ret = spi_flash_read_page(&sys_flash_, 0);
	if (ret < 0)
	{
		syslog("spi_flash_read_page error!\r\n");
		return -1;
	}


	memcpy(cfg.data, &sys_flash_.ReadBuffer[4], PAGE_SIZE);
	ret = check_sum_crc(cfg.data, PAGE_SIZE - 1, cfg.data[PAGE_SIZE - 1]);
	if (ret < 0)
	{
		syslog("load config crc error\r\n");
		return -1;
	}

	set_dehazing_mode(cfg.param.dehazing_mode);
	set_color_mode(cfg.param.color_mode);
	set_rgbyuv_mode(cfg.param.rgbyuv_mode);
	set_brightness_mode(cfg.param.brightness_mode);
	set_brightness_value(cfg.param.brightness_value);
	set_contrast_mode(cfg.param.contrast_mode);
	set_contrast_value(cfg.param.contrast_value);
	set_saturation_mode(cfg.param.saturation_mode);
	set_saturation_value(cfg.param.saturation_value);
	set_flip_mode(cfg.param.flip_mode);
	set_cursor_mode(cfg.param.cursor_mode);
	set_cursor_x(cfg.param.cursor_x);
	set_cursor_y(cfg.param.cursor_y);
	set_awb_mode(cfg.param.awb_mode);
	set_focus_radio(cfg.param.focus_radio);
	set_sharpness_mode(cfg.param.sharpness_mode);
	set_hdr_mode(cfg.param.hdr_mode);
	set_enhance_mode(cfg.param.enhance_mode);
	set_focus_direct_mode(cfg.param.focus_direct_mode);
	if (cfg.param.exposure_mode)
		set_auto_exposure_on(0, 0);
	else
		set_auto_exposure_off(cfg.param.exposure_time);
	set_auto_focus_param(cfg.param.af_min_focus, cfg.param.af_max_focus, cfg.param.af_init_focus);

	syslog("load config ok!\r\n");
	return 0;
}

注意这个函数中的几个技术点。

首先是union的使用,可以进行便捷的内存块截取并强制类型转换。
union实际上用简洁的代码,完成了几个步骤的操作,首先将当前选取的member,解析成pointer和length,然后用pointer和length,截取出一个内存块,然后将这个内存块中的值,强制类型转换成当前选取的member的类型,返回给调用者。

最常见的就是这种structure和BYTE ARRAY的联合体。

union PageConfig
{
	struct ConfigParam
	{
		int dehazing_mode;
		int color_mode;
		int rgbyuv_mode;
		int brightness_mode;
		int brightness_value;
		int contrast_mode;
		int contrast_value;
		int flip_mode;
		int cursor_mode;
		int cursor_x;
		int cursor_y;
		int awb_mode;
		int focus_radio;
		int sharpness_mode;
		int hdr_mode;
		int enhance_mode;
		int focus_direct_mode;
		int exposure_mode;
		int exposure_time;
		int saturation_mode;
		int saturation_value;
		int af_min_focus;
		int af_max_focus;
		int af_init_focus;
	} param;
	u8 data[256];
};

由于数组名即指针,这个特性可以用于memcpy。
在本例中,先以数组的视角,将数据拷贝,然后再切换视角,以struct的视角,来解析数据格式,分别选取结构体的成员,传给对应的成员变量。

然后是返回值检查,对函数返回值进行错误判别。

5)存储配置参数功能

int SystemManager::save_config()
{
	int ret;
	union PageConfig cfg;

	//C5180
	xcmos_.boot_from(1);
	xcmos_.save_to_user1();

	//qspi flash
	int bytes = sizeof(cfg.param);
	syslog("save_config: bytes=%d\r\n", bytes);
	if (bytes > 255) {
		syslog("/-------------------------------------------------------------------------------------/\r\n");
		syslog("error: config bytes too large!\r\n");
		syslog("/-------------------------------------------------------------------------------------/\r\n");
	}


	cfg.param.dehazing_mode = dehazing_mode_;
	cfg.param.color_mode = color_mode_;
	cfg.param.rgbyuv_mode = rgbyuv_mode_;
	cfg.param.brightness_mode = brightness_mode_;
	cfg.param.brightness_value = brightness_value_;
	cfg.param.contrast_mode = contrast_mode_;
	cfg.param.contrast_value = contrast_value_;
	cfg.param.flip_mode = flip_mode_;
	cfg.param.cursor_mode = cursor_mode_;
	cfg.param.cursor_x = cursor_x_;
	cfg.param.cursor_y = cursor_y_;
	cfg.param.awb_mode = awb_mode_;
	cfg.param.focus_radio = focus_radio_;
	cfg.param.sharpness_mode = sharpness_mode_;
	cfg.param.hdr_mode = hdr_mode_;
	cfg.param.enhance_mode = enhance_mode_;
	cfg.param.focus_direct_mode = xmotor_.focus_direct_mode_;
	cfg.param.exposure_mode = exposure_mode_;
	cfg.param.exposure_time = exposure_time_;
	cfg.param.saturation_mode = saturation_mode_;
	cfg.param.saturation_value = saturation_value_;
	cfg.param.af_min_focus = xaf_.af_min_focus_;
	cfg.param.af_max_focus = xaf_.af_max_focus_;
	cfg.param.af_init_focus = xaf_.af_init_focus_;
	cfg.data[PAGE_SIZE - 1] = calc_sum_crc(cfg.data, PAGE_SIZE - 1);

	memcpy(&sys_flash_.WriteBuffer[4], cfg.data, PAGE_SIZE);
	ret = spi_flash_write_enable(&sys_flash_);
	if (ret < 0)
	{
		syslog("spi_flash_write_enable error!\r\n");
		return -1;
	}

	ret = spi_flash_sector_erase(&sys_flash_, 0);
	if (ret < 0)
	{
		syslog("spi_flash_sector_erase error!\r\n");
		return -1;
	}

	ret = spi_flash_write_enable(&sys_flash_);
	if (ret < 0)
	{
		syslog("spi_flash_write_enable error!\r\n");
		return -1;
	}

	ret = spi_flash_write_page(&sys_flash_, 0);
	if (ret < 0)
	{
		syslog("spi_flash_write_page error!\r\n");
		return -1;
	}

	syslog("save config ok!\r\n");
	return 0;
}

注意这个函数中的几个技术点。

首先是union的使用,可以通过切换数据视角的方式,解析同一个内存块,将内存块解析成不同的数据格式。
在本例中,首先以结构体的视角,用成员变量的值,填充结构体中的各成员,
然后,再切换到byte array的视角,整体拷贝给buffer。

然后是返回值检查,对函数返回值进行错误判别。

4)设备启动功能

int SystemManager::open_device()
{
	//硬件初始化
	isp_gpio_init(&isp_gpio_, ISP_GPIO_DEV_ID);
	watchdog_init(&xwdt_, WATCHDOG_DEV_ID);
	stamp_timer_init(&sys_timer_, SYS_TIMER_DEV_ID);
	uart_lite_init(&host_uart_, HOST_UART_REGS_ADDR);
	uart_lite_init(&mcu_uart_, MCU_UART_REGS_ADDR);
	uart_lite_init(&cam_uart_, CAM_UART_REGS_ADDR);
	spi_flash_init(&sys_flash_, SYS_FLASH_DEV_ID);

	// 中断初始化
	intc_init();

	// 启动硬件
	stamp_timer_start(&sys_timer_);
	uart_lite_start(&host_uart_);
	uart_lite_start(&mcu_uart_);
	uart_lite_start(&cam_uart_);
	spi_flash_start(&sys_flash_);

	print("camera boot...\r\n");

	//等待逻辑启动和相机启动

    sleep(8);

	// fpga isp 参数初始化
	fpga_isp_init();

	//复位逻辑电路
	fpga_reset();

	// hls isp 参数初始化
	hls_isp_init();

	// 相机初始化
	sensor_init();

	//等待相机配置生效
	sleep(1);

	// 启动hls IP
	hls_isp_start();

	set_auto_exposure_on(0, 0);
	//	set_auto_exposure_off(0);

	//加载配置
	if (load_config() < 0) {
		load_default_config();
	}

	//开机默认最大视场

		xmotor_.set_filter_light(9);
		xmotor_.set_focus_value(9, xaf_.af_init_focus_);

	//启动vtc
	vtc_start();

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值