从SOD到OOD(sensor_cmd模块)

为了更好的封装,这个模块使用class封装。

class Cheetah
{
public:
	Cheetah(struct UartLiteDev* uart, struct StampTimerDev* timer);
	int set_value(u16 addr, u32 value, int timeout = 1000);
	int get_value(u16 addr, u32* value, int timeout = 1000);
	
	int set_value_retry(u16 addr, u32 value, int timeout = 1000, int count = 5) {
		while(count--)
		{
			int ret = set_value(addr, value, timeout);
			if (ret == 0)
				return 0;
		}
		return -1;
	}
	
	int get_value_retry(u16 addr, u32* value, int timeout = 1000, int count = 5) {
		while(count--)
		{
			int ret = get_value(addr, value, timeout);
			if (ret == 0)
				return 0;
		}
		return -1;
	}
	
	...
protected:
	struct UartLiteDev* uart_;
	struct StampTimerDev* timer_;
};

这个class里,定义了几个基础的方法,用来获取值或者设置值,这些值都是通过串口进行收发的,所以这里需要关联到一个串口结构体,这是整板的一个硬件资源,所以不使用内嵌,而使用指针关联。
另外,发送过程中,需要用到时间戳,所以,这个需要关联到一个TIMER,这也是整板的一个硬件资源,所以不使用内嵌,而使用指针关联。

其他的特定的函数,都是基于基础方法获取特定的值或者设置特定的值,为了便于使用,增加可读性,所以封装成独立的函数。
例如:

	int get_current_hsize(u32* value) {
		u32 data = 0;
		int ret = get_value_retry(0x6090, &data);
		if (ret < 0)
			return -1;
		*value = data;
		return 0;
	}
	
	int get_exp_time_limit(u32* max_value, u32* min_value) {
		u32 data = 0;
		int ret = get_value_retry(0x6088, &data);
		if (ret < 0)
			return -1;
		*max_value = data & 0xffffff;
		*min_value = data >> 24;
		return 0;
	}

	int get_cam_attri(u32* paio_en, u32* aec_en, u32* agc_en) {
		u32 data = 0;
		int ret = get_value_retry(0x60AC, &data);
		if (ret < 0)
			return -1;
		plog("%x\r\n", data);
		*paio_en = (data >> 29) & 0x1;
		*aec_en = (data >> 30) & 0x1;
		*agc_en = (data >> 31) & 0x1;
		return 0;
	}

	int get_current_exp_time(u32* value) {
		return get_value_retry(0x6080, value);
	}
	
	...
	
	int set_software_reset() {
		return set_value_retry(0x601c, 0xDEADBEEF);
	}

	int set_exposure_mode(u8 value) {
		//0x0 – Off (Free Running)
		//0x1 – Trigger Pulse Width (Duration of selected trigger pulse determines exposure time)
		//0x2 – Internal (Exposure Time register sets exposure time in microseconds)
		//0x3 – Reserved
		return set_value_retry(0x0720, value);
	}

	int set_exposure_time(u32 value, int timeout = 1000) {
		return set_value_retry(0x0728, value, timeout);
	}

	int set_digital_gain(u32 value, int timeout = 1000) {
		return set_value_retry(0x0438, value, timeout);
	}
   
   ...

来看看几个基础函数的实现,在CPP文件中,

首先是构建函数,

Cheetah::Cheetah(struct UartLiteDev* uart, struct StampTimerDev* timer) : uart_(uart), timer_(timer)
{

}

并没有做特殊的处理,只是在构建时进行了成员的初始化。
将传入的参数,即两个资源结构体的指针,赋值给成员变量uart_和timer_。

再来看get

int Cheetah::get_value(u16 addr, u32* value, int timeout)
{

	struct RingBuffer* ring = &uart_->recv_buff;

	u8 data = 0;
	ring_buffer_clear(ring);

	struct SensorReadCommand cmd = {0};
	cmd.data[0] = 0x52;
	cmd.data[1] = (addr >> 8) & 0xff;
	cmd.data[2] = addr & 0xff;
	uart_lite_send(uart_, (u8*)&cmd.data[0], sizeof(cmd.data));

	struct SensorReadAck ack = {0};

	u32 action_time = get_timestamp_ms(timer_);
	while(ring_buffer_valid_len(ring) < sizeof(ack.data))
	{
		u32 now_time = get_timestamp_ms(timer_);
		u32 dlt_time = ABS_DEC(now_time, action_time);
		if (dlt_time > (u32)timeout) {
			plog("Cheetah get_value:0x%x timeout!\r\n", addr);
			return -1;
		}
	}

	u8* rptr = (u8*)&ack.data[0];
	for (int i = 0; i < sizeof(ack.data); i++)
	{
		ring_buffer_pop(ring, &rptr[i]);
	}

	if (ack.data[0] == 0x06) {
		u32 val = (((u32)ack.data[1]) << 24) | (((u32)ack.data[2]) << 16) | (((u32)ack.data[3]) << 8) | (((u32)ack.data[4]) << 0);
		*value = val;
		return 0;
	} else {
		plog("Cheetah get_value:0x%x error!\r\n", addr);
		return -1;
	}
}

按照协议要求,
先发命令,
然后等待ACK,这里等待是定时等待的,如果不定时,则可能出现卡死,
然后取出ACK,并分析,并从ACK的数组中,取出所需要的数据。

这里,使用了几个结构体对data数组进行封装,是为了增加可读性。

struct SensorWriteCommand
{
	u8 data[7];
};

struct SensorWriteAck
{
	u8 data[2];
};

struct SensorReadCommand
{
	u8 data[3];
};

struct SensorReadAck
{
	u8 data[5];
};

再来看set

int Cheetah::set_value(u16 addr, u32 value, int timeout)
{
	struct RingBuffer* ring = &uart_->recv_buff;

	u8 data = 0;
	//while(ring_buffer_pop(ring, &data) == 0);
	ring_buffer_clear(ring);

	struct SensorWriteCommand cmd = {0};
	cmd.data[0] = 0x57;
	cmd.data[1] = (addr >> 8) & 0xff;
	cmd.data[2] = addr & 0xff;
	cmd.data[3] = (value >> 24) & 0xff;
	cmd.data[4] = (value >> 16) & 0xff;
	cmd.data[5] = (value >> 8) & 0xff;
	cmd.data[6] = value & 0xff;
	uart_lite_send(uart_, (u8*)&cmd.data[0], sizeof(cmd.data));

	if (timeout <= 0)
		return 0;

	struct SensorWriteAck ack = {0};

	u32 action_time = get_timestamp_ms(timer_);
	while(ring_buffer_valid_len(ring) < 1)
	{
		u32 now_time = get_timestamp_ms(timer_);
		u32 dlt_time = ABS_DEC(now_time, action_time);
		if (dlt_time > (u32)timeout) {
			plog("Cheetah set_value:0x%x 0x%x timeout!!!\r\n", addr, value);
			return -1;
		}
	}

	ring_buffer_pop(ring, &ack.data[0]);
	if (ack.data[0] == 0x15) {
		action_time = get_timestamp_ms(timer_);
		while(ring_buffer_valid_len(ring) < 1)
		{
			u32 now_time = get_timestamp_ms(timer_);
			u32 dlt_time = ABS_DEC(now_time, action_time);
			if (dlt_time > (u32)timeout) {
				plog("Cheetah set_value:0x%x 0x%x timeout!!!\r\n", addr, value);
				return -1;
			}
		}
		ring_buffer_pop(ring, &ack.data[1]);
	}

	if (ack.data[0] == 0x06) {
		return 0;
	} else {

		if (ack.data[0] == 0x15) {

			if (ack.data[1] == 0x00) {
				return 0;
			}
			else {
				plog("Cheetah set_value:0x%x 0x%x error, ", addr, value);
				if (ack.data[1] == 0x01) {
					plog("Error Code: Invalid command\r\n");
				} else if (ack.data[1] == 0x02) {
					plog("Error Code: Time out\r\n");
				} else if (ack.data[1] == 0x03) {
					plog("Error Code: Checksum error\r\n");
				} else if (ack.data[1] == 0x04) {
					plog("Error Code: Value less then minimum\r\n");
				} else if (ack.data[1] == 0x05) {
					plog("Error Code: Value higher than maximum\r\n");
				} else if (ack.data[1] == 0x06) {
					plog("Error Code: AGC error\r\n");
				} else if (ack.data[1] == 0x07) {
					plog("Error Code: Supervisor mode error\r\n");
				} else if (ack.data[1] == 0x07) {
					plog("Error Code: Mode not supported error\r\n");
				} else {
					plog("Error Code: 0x%x: ack=0x%x 0x%x\r\n", addr, ack.data[0], ack.data[1]);
				}
			}


		}

		return -1;
	}
}

按照协议要求,
先发命令,
然后等待ACK,这里等待是定时等待的,如果不定时,则可能出现卡死,
然后取出ACK,并分析,并从ACK的数组中,取出所需要的数据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值