refactor(app, drv): 移植下位机的应用程序到新的通信协议

1. 应用程序实现了心跳包
2. 应用程序实现了4个相机的单独设置
3. 应用程序去除了有关喷阀、接收处理mask和硬件fifo相关的代码
4. 删除了fifo相关驱动程序
5. 修正了encoder驱动程序中的清除缓存逻辑

Co-authored-by: lyz <1942503466@qq.com>
This commit is contained in:
Miaow 2023-05-27 23:01:10 +08:00
parent fe7b3308bc
commit 6449ebeeac
14 changed files with 210 additions and 498 deletions

View File

@ -307,10 +307,11 @@ $ make CROSS_COMPILE=交叉编译工具链前缀
8. 安装编译得到的驱动文件`encode.ko`,并设置自动加载,对应自启脚本可以如下方式写入,也可以直接上传[script/loadencoder.sh](../script/loadencoder.sh)ssh方式`root`登录: 8. 安装编译得到的驱动文件`encode.ko`,并设置自动加载,对应自启脚本可以如下方式写入,也可以直接上传[script/loadencoder.sh](../script/loadencoder.sh)ssh方式`root`登录:
```shell ```shell
上传encoder.ko到/lib/modules/[内核版本]/kernel/drivers/ 上传encoder.ko到/lib/modules/[内核版本]/extra/
$ cd /lib/modules/[内核版本]; depmod $ cd /lib/modules/[内核版本]/extra/; depmod
$ set +H $ set +H
$ echo -e "#!/bin/sh\nmodprobe encoder" > /etc/init.d/loadencoder.sh $ echo -e "#!/bin/sh\nmodprobe encoder" > /etc/init.d/loadencoder.sh
$ chmod 755 /etc/init.d/loadencoder.sh
$ cd /etc/rc5.d $ cd /etc/rc5.d
$ ln -s ../init.d/loadencoder.sh S20loadencoder.sh $ ln -s ../init.d/loadencoder.sh S20loadencoder.sh
``` ```

View File

@ -1 +1 @@
1.5 1.6

View File

@ -1,17 +1,19 @@
/** /**
* @file encoder_dev.c * @file encoder_dev.c
* @brief Manage the hardware encoder unit * @brief Manage the hardware encoder unit
* @author miaow (3703781@qq.com) * @author miaow, lyz (3703781@qq.com)
* @version 1.0 * @version 0.11
* @date 2022/06/11 * @date 2022/04/26
* @mainpage github.com/NanjingForestryUniversity * @mainpage github.com/NanjingForestryUniversity
* *
* @copyright Copyright (c) 2022 miaow * @copyright Copyright (c) 2023 miaow, lyz
* *
* @par Changelog: * @par Changelog:
* <table> * <table>
* <tr><th>Date <th>Version <th>Author <th>Description * <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/06/11 <td>0.9 <td>Miaow <td>Write this module * <tr><td>2022/06/11 <td>0.9 <td>Miaow <td>Write this module
* <tr><td>2022/04/11 <td>0.10 <td>lyz <td>Add seprate dividers up to 4 cameras
* <tr><td>2023/04/26 <td>0.11 <td>Miaow <td>Add Clear mode
* </table> * </table>
*/ */
@ -31,9 +33,13 @@
static int encoder_dev_fd = -1; static int encoder_dev_fd = -1;
static char perror_buffer[128]; static char perror_buffer[128];
static struct { static struct
unsigned int valve_divide_value; {
unsigned int camera_divide_value; uint32_t valve_divide_value;
uint32_t camera_a_divide_value;
uint32_t camera_b_divide_value;
uint32_t camera_c_divide_value;
uint32_t camera_d_divide_value;
} encoder_dev_divide_value_structure; } encoder_dev_divide_value_structure;
/** /**
@ -45,22 +51,37 @@ int encoder_dev_init()
{ {
encoder_dev_fd = open(ENCODER_DEV_PATH, O_RDWR); encoder_dev_fd = open(ENCODER_DEV_PATH, O_RDWR);
ON_ERROR_RET(encoder_dev_fd, "", "", -1); ON_ERROR_RET(encoder_dev_fd, "", "", -1);
encoder_dev_set_divide( 100, 100, 100, 100);
return 0; return 0;
} }
/** /**
* @brief Set the two divider in the hareware encoder unit. * @brief Set the two divider in the hareware encoder unit.
* @param valve_divide the frequency division factor between the encoder signal and valve output * @param camera_a_divide the frequency division factor between the encoder signal and camera a triggle signal
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter * Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @param camera_divide the frequency division factor between the encoder signal and camera triggle signal * @param camera_b_divide the frequency division factor between the encoder signal and camera b triggle signal
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @param camera_c_divide the frequency division factor between the encoder signal and camera c triggle signal
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @param camera_d_divide the frequency division factor between the encoder signal and camera d triggle signal
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter * Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
*
* @return 0 - success, other - error * @return 0 - success, other - error
*/ */
int encoder_dev_set_divide(int valve_divide, int camera_divide) int encoder_dev_set_divide(int camera_a_divide,
int camera_b_divide,
int camera_c_divide,
int camera_d_divide)
{ {
encoder_dev_divide_value_structure.valve_divide_value = valve_divide; encoder_dev_divide_value_structure.valve_divide_value = 2;
encoder_dev_divide_value_structure.camera_divide_value = camera_divide; if (camera_a_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.camera_a_divide_value = camera_a_divide;
if (camera_b_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.camera_b_divide_value = camera_b_divide;
if (camera_c_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.camera_c_divide_value = camera_c_divide;
if (camera_d_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.camera_d_divide_value = camera_d_divide;
ssize_t size = write(encoder_dev_fd, &encoder_dev_divide_value_structure, sizeof(encoder_dev_divide_value_structure)); ssize_t size = write(encoder_dev_fd, &encoder_dev_divide_value_structure, sizeof(encoder_dev_divide_value_structure));
int res = -(size != sizeof(encoder_dev_divide_value_structure)); int res = -(size != sizeof(encoder_dev_divide_value_structure));
ON_ERROR_RET(res, "size=", "", -1); ON_ERROR_RET(res, "size=", "", -1);
@ -70,12 +91,12 @@ int encoder_dev_set_divide(int valve_divide, int camera_divide)
/** /**
* @brief Set the trig signal to internal or external. * @brief Set the trig signal to internal or external.
* @param mode ENCODER_TRIG_MODE_EXTERNEL for externally trig, or ENCODER_TRIG_MODE_INTERNEL for internally trig * @param count the count of virtual trig cycles.
* @return 0 - success, other - error * @return 0 - success, other - error
*/ */
int encoder_dev_virtual_trig(int count) int encoder_dev_virtual_trig(int count)
{ {
int res = ioctl(encoder_dev_fd, _IOW('D', ENCODER_CMD_FUNCTION_VIRT_INPUT, 4), count); int res = ioctl(encoder_dev_fd, _IOW('D', ENCODER_CMD_FUNCTION_VIRT_INPUT, int), count);
ON_ERROR_RET(res, "", "", -1); ON_ERROR_RET(res, "", "", -1);
return 0; return 0;
} }
@ -85,9 +106,20 @@ int encoder_dev_virtual_trig(int count)
* @param mode ENCODER_TRIG_MODE_EXTERNEL for externally trig, or ENCODER_TRIG_MODE_INTERNEL for internally trig * @param mode ENCODER_TRIG_MODE_EXTERNEL for externally trig, or ENCODER_TRIG_MODE_INTERNEL for internally trig
* @return 0 - success, other - error * @return 0 - success, other - error
*/ */
int encoder_dev_set_trigmod(int mode) int encoder_dev_set_trigmod(encoder_dev_trig_mode_enum mode)
{ {
int res = ioctl(encoder_dev_fd, _IOW('D', mode, 0)); int res = ioctl(encoder_dev_fd, _IOW('D', mode, int));
ON_ERROR_RET(res, "", "", -1);
return 0;
}
/**
* @brief Set the clr signal to internal or both external and internal.
* @return 0 - success, other - error
*/
int encoder_dev_set_clrmod(encoder_dev_clear_mode_enum mode)
{
int res = ioctl(encoder_dev_fd, _IOW('D', mode, int));
ON_ERROR_RET(res, "", "", -1); ON_ERROR_RET(res, "", "", -1);
return 0; return 0;
} }

View File

@ -1,16 +1,19 @@
/** /**
* @file encoder_dev.h * @file encoder_dev.h
* @brief Manage the hardware encoder unit * @brief Manage the hardware encoder unit
* @author miaow (3703781@qq.com) * @author miaow, lzy (3703781@qq.com)
* @version 1.0 * @version 0.11
* @date 2022/06/11 * @date 2022/04/26
* @mainpage github.com/NanjingForestryUniversity
* *
* @copyright Copyright (c) 2022 miaow * @copyright Copyright (c) 2023 miaow, lyz
* *
* @par Changelog: * @par Changelog:
* <table> * <table>
* <tr><th>Date <th>Version <th>Author <th>Description * <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/06/11 <td>0.9 <td>Miaow <td>Write this module * <tr><td>2022/06/11 <td>0.9 <td>Miaow <td>Write this module
* <tr><td>2022/04/11 <td>0.10 <td>lyz <td>Add seprate dividers up to 4 cameras
* <tr><td>2023/04/26 <td>0.11 <td>Miaow <td>Add Clear mode
* </table> * </table>
*/ */
#ifndef __ENCODER_DEV_H #ifndef __ENCODER_DEV_H
@ -20,14 +23,27 @@
#define ENCODER_DEV_PATH "/dev/encoder" #define ENCODER_DEV_PATH "/dev/encoder"
#define ENCODER_DEV_DIVIDE_NOT_TO_SET 0 #define ENCODER_DEV_DIVIDE_NOT_TO_SET 0
#define ENCODER_TRIG_MODE_EXTERNEL 100 typedef enum
#define ENCODER_TRIG_MODE_INTERNEL 101 {
ENCODER_TRIG_MODE_EXTERNEL = 100,
ENCODER_TRIG_MODE_INTERNEL = 101
} encoder_dev_trig_mode_enum;
int encoder_dev_set_divide(int valve_divide, int camera_divide); typedef enum
{
ENCODER_CLEAR_MODE_BOTH = 200,
ENCODER_CLEAR_MODE_INTERNAL = 201
} encoder_dev_clear_mode_enum;
int encoder_dev_set_divide(int camera_a_divide,
int camera_b_divide,
int camera_c_divide,
int camera_d_divide);
int encoder_dev_flush(void); int encoder_dev_flush(void);
int encoder_dev_set_trigmod(int mode); int encoder_dev_set_trigmod(encoder_dev_trig_mode_enum mode);
int encoder_dev_set_clrmod(encoder_dev_clear_mode_enum mode);
int encoder_dev_virtual_trig(int count); int encoder_dev_virtual_trig(int count);
int encoder_dev_init(void); int encoder_dev_init(void);
int encoder_dev_deinit(void); int encoder_dev_deinit(void);

View File

@ -1,149 +0,0 @@
/**
* @file fifo_dev.c
* @brief Operate the hardware fifo with Linux application
* @details Call fifo_dev_init() paired with fifo_dev_deinit() as their names imply, fifo_dev_write_xxx() can be executed several times to operate the hardware fifo between fifo_dev_init() and fifo_dev_deinit()
* @mainpage github.com/NanjingForestryUniversity
* @author miaow (3703781@qq.com)
* @version 1.1
* @date 2022/08/07
* @mainpage github.com/NanjingForestryUniversity
*
* @copyright Copyright (c) 2022 miaow
*
* @par Changelog:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/06/09 <td>1.0 <td>miaow <td>Write this file
* <tr><td>2022/08/07 <td>1.1 <td>miaow <td>Add ignore_row_num to fifo_dev_write_frame
* </table>
*/
#include <fifo_dev.h>
#include <pthread.h>
#include <unistd.h>
#include <common.h>
#include <fcntl.h>
#include <host_computer.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <data_filter.h>
#define FIFO_CMD_FUNCTION_CLEAR 1
#define FIFO_CMD_FUNCTION_PADDING 2
#define FIFO_CMD_GET_EMPTYCOUNT 3
static int fifo_dev_fd = -1;
static char perror_buffer[128];
/**
* @brief Initialize the hardware fifo
* @note This function just open the file descriptor of the hardware fifo
* @return 0 - success, other - error
*/
int fifo_dev_init()
{
fifo_dev_fd = open(FIFO_DEV_PATH, O_RDWR);
ON_ERROR_RET(fifo_dev_fd, "", "", -1);
return 0;
}
/**
* @brief Get the count of read operation when the fifo is empty.
* @note The empty read count will be set to zero at fifo_dev_clear() only.
* @return >=0 - success, other - error
*/
int fifo_dev_get_emptycount()
{
int count;
int res = ioctl(fifo_dev_fd, _IOR('D', FIFO_CMD_GET_EMPTYCOUNT, 0), &count);
ON_ERROR_RET(res, "", "", -1);
return count;
}
/**
* @brief Set value to put of a frame.
* @param valve_data An array HOST_COMPUTER_PICTURE_COLUMN_BYTES bytes * HOST_COMPUTER_PICTURE_ROW_NUM rows.
* @param ignore_row_num Remove the ignore_row_num rows at the beginning of the frame. range: [0, HOST_COMPUTER_PICTURE_BYTES)
* @return 0 - success, other - error
*/
int fifo_dev_write_frame(void *valve_data, int ignore_row_num)
{
ssize_t size;
char *valve_to_write = (char *)valve_data + ignore_row_num * HOST_COMPUTER_PICTURE_COLUMN_BYTES;
int size_to_write = HOST_COMPUTER_PICTURE_COLUMN_BYTES * (HOST_COMPUTER_PICTURE_ROW_NUM - ignore_row_num);
size = write(fifo_dev_fd, valve_to_write, size_to_write);
int res = -(size < size_to_write);
ON_ERROR_RET(res, "size=", "", -1);
return 0;
}
/**
* @brief Set value to put of a row.
* @param valve_data An array 32bytes.
* @return 0 - success, other - error
*/
int fifo_dev_write_row(void *valve_data)
{
ssize_t size = write(fifo_dev_fd, valve_data, 32);
int res = -(size < 32);
ON_ERROR_RET(res, "size=", "", -1);
return 0;
}
/**
* @brief Flush and clear the hardware fifo.
* @return 0 - success, other - error
*/
int fifo_dev_clear()
{
int res = ioctl(fifo_dev_fd, _IOW('D', FIFO_CMD_FUNCTION_CLEAR, 0));
ON_ERROR_RET(res, "", "", -1);
return 0;
}
/**
* @brief Write `count` zero-items to the haredware fifo, which acts as delay time.
* @param count Count of zero-items to write.
* @return 0 - success, other - error
*/
int fifo_dev_write_delay(uint32_t count)
{
int res = ioctl(fifo_dev_fd, _IOW('D', FIFO_CMD_FUNCTION_PADDING, 0), count);
ON_ERROR_RET(res, "", "", -1);
return 0;
}
/**
* @brief Get the count of items in the hardware fifo.
* @note An item from hardware fifo is of 256 bits in size, aka. 32 bytes, 8 integers
* @return >=0 - success, other - error
*/
int fifo_dev_get_count()
{
uint32_t fifo_item_count;
ssize_t size = read(fifo_dev_fd, &fifo_item_count, sizeof(fifo_item_count));
if (size != sizeof(fifo_item_count))
ON_ERROR(-1, "size=", "");
return fifo_item_count;
}
/**
* @brief Deinitialize the hardware fifo.
* @note This function just close the file descriptor of the hardware fifo.
* @return 0 - success, -1 - error
*/
int fifo_dev_deinit()
{
int res = close(fifo_dev_fd);
ON_ERROR_RET(res, "", "", -1);
return 0;
}

View File

@ -1,37 +0,0 @@
/**
* @file fifo_dev.h
* @brief Operate the hardware fifo with Linux application
* @details Call fifo_dev_init() paired with fifo_dev_deinit() as their names imply, fifo_dev_write_xxx() can be executed several times to operate the hardware fifo between fifo_dev_init() and fifo_dev_deinit()
* @mainpage github.com/NanjingForestryUniversity
* @author miaow (3703781@qq.com)
* @version 1.1
* @date 2022/08/07
* @mainpage github.com/NanjingForestryUniversity
*
* @copyright Copyright (c) 2022 miaow
*
* @par Changelog:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/06/09 <td>1.0 <td>miaow <td>Write this file
* <tr><td>2022/08/07 <td>1.1 <td>miaow <td>Add ignore_row_num to fifo_dev_write_frame
* </table>
*/
#ifndef __FIFO_DEV_H
#define __FIFO_DEV_H
#include <stdint.h>
#define FIFO_DEV_PATH "/dev/fifo"
int fifo_dev_init(void);
int fifo_dev_get_emptycount(void);
int fifo_dev_write_frame(void *valve_data, int ignore_row_num);
int fifo_dev_clear(void);
int fifo_dev_write_delay(uint32_t count);
int fifo_dev_write_row(void *valve_data);
int fifo_dev_get_count(void);
int fifo_dev_deinit(void);
#endif

View File

@ -1,18 +1,19 @@
/** /**
* @file host_computer.c * @file host_computer.c
* @brief Commnunicate with host computer. Protocal is described in hostcomputer通信协议.md * @brief Commnunicate with host computer. Protocal is described in V1.4
* @author miaow (3703781@qq.com) * @author miaow (3703781@qq.com)
* @version 1.1 * @version 1.2
* @date 2022/08/06 * @date 2023/05/07
* @mainpage github.com/NanjingForestryUniversity * @mainpage github.com/NanjingForestryUniversity
* *
* @copyright Copyright (c) 2022 miaow * @copyright Copyright (c) 2023 miaow
* *
* @par Changelog: * @par Changelog:
* <table> * <table>
* <tr><th>Date <th>Version <th>Author <th>Description * <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/01/16 <td>1.0 <td>miaow <td>Write this file * <tr><td>2022/01/16 <td>1.0 <td>miaow <td>Write this file
* <tr><td>2022/08/06 <td>1.1 <td>miaow <td>Add fifob * <tr><td>2022/08/06 <td>1.1 <td>miaow <td>Add fifob
* <tr><td>2023/05/07 <td>1.2 <td>miaow <td>Port to b03 branch
* </table> * </table>
*/ */
#include <host_computer.h> #include <host_computer.h>
@ -24,11 +25,14 @@
#include <pthread.h> #include <pthread.h>
#include <common.h> #include <common.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <fifo_dev.h>
#include <encoder_dev.h> #include <encoder_dev.h>
#include <data_filter.h> #include <data_filter.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
static char perror_buffer[128]; static char perror_buffer[128];
/** /**
@ -41,33 +45,42 @@ typedef struct
int need_exit; // The flag variable to indicate whether to exit the loop_thread in this file int need_exit; // The flag variable to indicate whether to exit the loop_thread in this file
pthread_t loop_thread; // The main routine of this module, which parses commands and data from host, puts them into the queue pthread_t loop_thread; // The main routine of this module, which parses commands and data from host, puts them into the queue
pthread_mutex_t loop_thread_mutex; // The mutex for loop_thread pthread_mutex_t loop_thread_mutex; // The mutex for loop_thread
pthread_mutex_t is_connected_mutex;
timer_t heartbeat_timer;
} hostcomputer_t; } hostcomputer_t;
static hostcomputer_t _global_structure; static hostcomputer_t _global_structure;
void *loop_thread_func(void *param); void *loop_thread_func(void *param);
void heartbeat_timer_func(__sigval_t param);
/** /**
* @brief Pre initialize host computer module * @brief Pre initialize host computer module
* @param data_q A pointer to the queue storing the valve data from host computer * @param data_q A pointer to the queue storing the valve data from host computer
* @param cmd_q A pointer to the queue storing the cmd from host computer * @param cmd_q A pointer#include <sys/time.h> to the queue storing the cmd from host computer
* @return 0 - success * @return 0 - success
*/ */
int hostcomputer_init(queue_uint64_msg_t *cmd_q) int hostcomputer_init(queue_uint64_msg_t *cmd_q)
{ {
struct sigevent evp;
struct itimerspec ts;
_global_structure.cmd_q = cmd_q; _global_structure.cmd_q = cmd_q;
pthread_mutex_init(&_global_structure.loop_thread_mutex, NULL); pthread_mutex_init(&_global_structure.loop_thread_mutex, NULL);
pthread_mutex_init(&_global_structure.is_connected_mutex, NULL);
pthread_create(&_global_structure.loop_thread, NULL, loop_thread_func, NULL); pthread_create(&_global_structure.loop_thread, NULL, loop_thread_func, NULL);
memset(&evp, 0, sizeof(evp));
evp.sigev_value.sival_ptr = &_global_structure.heartbeat_timer;
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_notify_function = heartbeat_timer_func;
timer_create(CLOCK_REALTIME, &evp, &_global_structure.heartbeat_timer);
ts.it_interval.tv_sec = 3;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = 3;
ts.it_value.tv_nsec = 0;
timer_settime(_global_structure.heartbeat_timer, TIMER_ABSTIME, &ts, NULL);
return 0; return 0;
} }
static void send_error(int fd)
{
write(fd, "error", 5);
printf("\r\nerror sent\r\n");
}
/** /**
* @brief Receive `size` bytes from a socket. If no more bytes are available at the socket, this function return -1 when timeout reaches. * @brief Receive `size` bytes from a socket. If no more bytes are available at the socket, this function return -1 when timeout reaches.
* @param fd The socket fd * @param fd The socket fd
@ -105,7 +118,9 @@ static int is_connected(int sock_fd)
{ {
struct tcp_info info; struct tcp_info info;
int len = sizeof(info); int len = sizeof(info);
pthread_mutex_lock(&_global_structure.is_connected_mutex);
getsockopt(sock_fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); getsockopt(sock_fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
pthread_mutex_unlock(&_global_structure.is_connected_mutex);
return info.tcpi_state == TCP_ESTABLISHED; return info.tcpi_state == TCP_ESTABLISHED;
} }
@ -117,16 +132,12 @@ static int is_connected(int sock_fd)
void *loop_thread_func(void *param) void *loop_thread_func(void *param)
{ {
// printf("loop thread in %s start\r\n", __FILE__); // printf("loop thread in %s start\r\n", __FILE__);
int need_exit = 0, frame_count = 0, error_sent = 0; int need_exit = 0;
int std_count, empty_packets_num = 0;
int empty_count_initial = 0;
int empty_count_processed = 0;
char pre; char pre;
uint16_t n_bytes; uint32_t n_bytes;
char type[2]; char type[2];
char data[HOST_COMPUTER_PICTURE_BYTES + 1]; char data[20];
char check[2]; char check[2];
datafilter_typedef datafilter;
while (!need_exit) while (!need_exit)
{ {
@ -136,6 +147,7 @@ void *loop_thread_func(void *param)
// reconnect if not connected // reconnect if not connected
if (!is_connected(_global_structure.socket_fd)) if (!is_connected(_global_structure.socket_fd))
{ {
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_STOP);
_global_structure.socket_fd = socket(AF_INET, SOCK_STREAM, 0); _global_structure.socket_fd = socket(AF_INET, SOCK_STREAM, 0);
struct timeval timeout = {.tv_sec = 10, .tv_usec = 0}; struct timeval timeout = {.tv_sec = 10, .tv_usec = 0};
setsockopt(_global_structure.socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); setsockopt(_global_structure.socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
@ -158,7 +170,6 @@ void *loop_thread_func(void *param)
} }
// =======================parse the protocol========================================= // =======================parse the protocol=========================================
if (recvn(_global_structure.socket_fd, (char *)&pre, 1) > 1) if (recvn(_global_structure.socket_fd, (char *)&pre, 1) > 1)
{ {
// close(_global_structure.socket_fd); // close(_global_structure.socket_fd);
@ -172,17 +183,17 @@ void *loop_thread_func(void *param)
// fflush(stdout); // fflush(stdout);
continue; continue;
} }
if (recvn(_global_structure.socket_fd, (char *)&n_bytes, 2) != 2) if (recvn(_global_structure.socket_fd, (char *)&n_bytes, 4) != 4)
{ {
// close(_global_structure.socket_fd); // close(_global_structure.socket_fd);
printf("n_bytes_len!=2\r\n"); printf("n_bytes_len!=4\r\n");
continue; continue;
} }
n_bytes = ntohs(n_bytes); n_bytes = ntohl(n_bytes);
if (n_bytes != HOST_COMPUTER_PICTURE_BYTES + 2 && n_bytes > 10) if (n_bytes != 10 && n_bytes != 3)
{ {
// close(_global_structure.socket_fd); // close(_global_structure.socket_fd);
printf("n_bytes> 10 and n_bytes!=HOST_COMPUTER_PICTURE_BYTES + 2\r\n"); printf("n_bytes is not 10 or 3\r\n");
continue; continue;
} }
if (recvn(_global_structure.socket_fd, (char *)type, 2) != 2) if (recvn(_global_structure.socket_fd, (char *)type, 2) != 2)
@ -220,96 +231,9 @@ void *loop_thread_func(void *param)
// =======================parse the commands========================================= // =======================parse the commands=========================================
// commands are reformed as an uint64_t, 0x--------xxxxxxxx, where `-` refers its paramter and `x` is HOSTCOMPUTER_CMD // commands are reformed as an uint64_t, 0x--------xxxxxxxx, where `-` refers its paramter and `x` is HOSTCOMPUTER_CMD
if (type[0] == 'd' && type[1] == 'a') if (type[0] == 's' && type[1] == 't')
{
/*
int current_count = fifo_dev_get_count();
int current_count_filtered = datafilter_calculate(&datafilter_a, current_count);
if (++frame_count_a > HOST_COMPUTER_BEGINNING_PICTURES_IGNORE_NUM)
{
fifo_dev_write_frame(data, 0);
}
int added_count = fifo_dev_get_count();
printf("before %d->after %d, diff %d, filter %d\r\n", current_count, added_count, added_count - current_count, current_count_filtered);
*/
//=================================================
int current_count, current_count_filtered, diff_count, empty_count_to_process;
if (n_bytes - 2 != HOST_COMPUTER_PICTURE_BYTES)
{
printf("n_bytes-2!=%d\r\n", HOST_COMPUTER_PICTURE_BYTES);
continue;
}
// get the item counts and its slide average value
current_count = fifo_dev_get_count();
current_count_filtered = datafilter_calculate(&datafilter, current_count);
frame_count++;
if (frame_count == HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM + 1)
{
empty_count_initial = fifo_dev_get_emptycount();
}
else if (frame_count == 100) // record the normal item counts in fifo
{
std_count = current_count_filtered;
}
if (frame_count > HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM)
{
// do nothing at first two frames, because that the first frame is set to zero and was concatenated to the delay frame before
// in case of late arrival of the first two frames.
empty_count_to_process = fifo_dev_get_emptycount() - empty_count_initial - empty_count_processed;
if (empty_count_to_process >= HOST_COMPUTER_PICTURE_ROW_NUM)
{
empty_count_processed += HOST_COMPUTER_PICTURE_ROW_NUM;
}
else
{
fifo_dev_write_frame(data, empty_count_to_process);
empty_count_processed += empty_count_to_process;
}
}
if (current_count == 0)
empty_packets_num++;
else
empty_packets_num = 0;
// print fifo status
printf("a ||| %d | cnt %d | avgcnt %d | stdcnt %d",
frame_count, current_count, current_count_filtered, std_count);
fflush(stdout);
// if (empty_count_to_process)
printf(" ||| initemp %d | toprc %d | prcd %d\r\n", empty_count_initial,
empty_count_to_process, empty_count_processed);
// else
// printf("\r\n");
// if the item counts changes a lot compared with normal counts,
// meaning something goes wrong, a message will send to the hostcomputer
diff_count = current_count_filtered - std_count;
int diff_cond = diff_count > 250 || diff_count < -250;
int frame_count_cond = frame_count > 100;
int empty_packets_cond = empty_packets_num >= 5;
if (((frame_count_cond && diff_cond) || empty_packets_cond) && !error_sent)
{
error_sent = 1;
printf("\r\na ||| avgcnt %d | %d larger", current_count_filtered, diff_count);
fflush(stdout);
send_error(_global_structure.socket_fd);
}
}
else if (type[0] == 's' && type[1] == 't')
{ {
// printf("Start put to cmd queue, param:%d\r\n", (int)atoll(data)); // printf("Start put to cmd queue, param:%d\r\n", (int)atoll(data));
frame_count = 0;
error_sent = 0;
empty_packets_num = 0;
std_count = 0;
datafilter_deinit(&datafilter);
datafilter_init(&datafilter, 20);
empty_count_processed = 0;
empty_count_initial = 0;
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_START); queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_START);
} }
else if (type[0] == 's' && type[1] == 'p') else if (type[0] == 's' && type[1] == 'p')
@ -317,47 +241,46 @@ void *loop_thread_func(void *param)
// printf("Stop put to cmd queue, param:%d\r\n", (int)atoll(data)); // printf("Stop put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_STOP); queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_STOP);
} }
else if (type[0] == 't' && type[1] == 'e') else if (type[0] == 'p' && type[1] == 'a')
{
// printf("Test put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_TEST);
}
else if (type[0] == 't' && type[1] == 't')
{
// printf("Test put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_STOP_TEST);
}
else if (type[0] == 'p' && type[1] == 'o')
{
// printf("Power on put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_POWERON);
}
else if (type[0] == 's' && type[1] == 'c')
{ {
// printf("Set camera triggle pulse count put to cmd queue, param:%d\r\n", (int)atoll(data)); // printf("Set camera triggle pulse count put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT); queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_A);
} }
else if (type[0] == 's' && type[1] == 'v') else if (type[0] == 'p' && type[1] == 'b')
{ {
// printf("Set valve pulse count put to cmd queue, param:%d\r\n", (int)atoll(data)); // printf("Set camera triggle pulse count put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETVALVETRIGPULSECOUNT); queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_B);
} }
else if ((type[0] == 's' && type[1] == 'd')) else if (type[0] == 'p' && type[1] == 'c')
{ {
// printf("Set camera to valve pulse count put to cmd queue, param:%d\r\n", (int)atoll(data)); // printf("Set camera triggle pulse count put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATOVALVEPULSECOUNT); queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_C);
}
else if (type[0] == 'p' && type[1] == 'd')
{
// printf("Set camera triggle pulse count put to cmd queue, param:%d\r\n", (int)atoll(data));
queue_uint64_put(_global_structure.cmd_q, (atoll(data) << 32) | HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_D);
} }
} }
printf("loop thread in %s exit\r\n", __FILE__); printf("loop thread in %s exit\r\n", __FILE__);
return NULL; return NULL;
} }
void heartbeat_timer_func(__sigval_t param)
{
static uint8_t heartbeat_packet[] = {0xaa, 0x00, 0x00, 0x00, 0x03, 'h', 'b', 0xff, 0xff, 0xff, 0xbb};
if (is_connected(_global_structure.socket_fd))
write(_global_structure.socket_fd, heartbeat_packet, sizeof(heartbeat_packet));
}
/** /**
* @brief Deinitialize and release resources used by host computer module * @brief Deinitialize and release resources used by host computer module
* @return int * @return int
*/ */
int hostcomputer_deinit() int hostcomputer_deinit()
{ {
timer_delete(_global_structure.heartbeat_timer);
pthread_mutex_lock(&_global_structure.loop_thread_mutex); pthread_mutex_lock(&_global_structure.loop_thread_mutex);
_global_structure.need_exit = 1; _global_structure.need_exit = 1;
pthread_mutex_unlock(&_global_structure.loop_thread_mutex); pthread_mutex_unlock(&_global_structure.loop_thread_mutex);

View File

@ -1,17 +1,19 @@
/** /**
* @file host_computer.h * @file host_computer.h
* @brief Commnunicate with host computer. Protocal is described in hostcomputer通信协议.md * @brief Commnunicate with host computer. Protocal is described in V1.4
* @author miaow (3703781@qq.com) * @author miaow (3703781@qq.com)
* @version 1.1 * @version 1.2
* @date 2022/08/6 * @date 2023/05/07
* @mainpage github.com/NanjingForestryUniversity
* *
* @copyright Copyright (c) 2022 miaow * @copyright Copyright (c) 2023 miaow
* *
* @par Changelog: * @par Changelog:
* <table> * <table>
* <tr><th>Date <th>Version <th>Author <th>Description * <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/01/16 <td>1.0 <td>miaow <td>Write this file * <tr><td>2022/01/16 <td>1.0 <td>miaow <td>Write this file
* <tr><td>2022/08/06 <td>1.1 <td>miaow <td>Add fifob * <tr><td>2022/08/06 <td>1.1 <td>miaow <td>Add fifob
* <tr><td>2023/05/07 <td>1.2 <td>miaow <td>Port to b03 branch
* </table> * </table>
*/ */
#ifndef __HOST_COMPUTER_H #ifndef __HOST_COMPUTER_H
@ -21,27 +23,20 @@
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#define HOST_COMPUTER_IP "192.168.10.8" #define HOST_COMPUTER_IP "192.168.2.125"
#define HOST_COMPUTER_PORT 13452 #define HOST_COMPUTER_PORT 13452
#define HOST_COMPUTER_PICTURE_ROW_NUM 1024
#define HOST_COMPUTER_PICTURE_COLUMN_NUM 256
#define HOST_COMPUTER_PICTURE_COLUMN_BYTES (HOST_COMPUTER_PICTURE_COLUMN_NUM / 8)
#define HOST_COMPUTER_PICTURE_BYTES (HOST_COMPUTER_PICTURE_COLUMN_BYTES * HOST_COMPUTER_PICTURE_ROW_NUM)
#define HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM 1
/** /**
* @brief The commonds, ref * @brief The commonds, ref V1.4
*/ */
enum HOSTCOMPUTER_CMD enum HOSTCOMPUTER_CMD
{ {
HOSTCOMPUTER_CMD_START = 2, HOSTCOMPUTER_CMD_START = 1,
HOSTCOMPUTER_CMD_STOP = 3, HOSTCOMPUTER_CMD_STOP = 2,
HOSTCOMPUTER_CMD_TEST = 4, HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_A = 3,
HOSTCOMPUTER_CMD_POWERON = 5, HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_B = 4,
HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT = 6, HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_C = 5,
HOSTCOMPUTER_CMD_SETVALVETRIGPULSECOUNT = 7, HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_D = 6,
HOSTCOMPUTER_CMD_SETCAMERATOVALVEPULSECOUNT = 8,
HOSTCOMPUTER_CMD_STOP_TEST = 9
}; };
int hostcomputer_init(queue_uint64_msg_t *cmd_q); int hostcomputer_init(queue_uint64_msg_t *cmd_q);

View File

@ -2,19 +2,20 @@
* @file main.c * @file main.c
* @brief Excute the commands from host_computer * @brief Excute the commands from host_computer
* @author miaow (3703781@qq.com) * @author miaow (3703781@qq.com)
* @version 1.0 * @version 1.2
* @date 2022/06/12 * @date 2023/05/27
* @mainpage github.com/NanjingForestryUniversity * @mainpage github.com/NanjingForestryUniversity
* *
* @copyright Copyright (c) 2022 miaow * @copyright Copyright (c) 2023 miaow
* *
* @par Changelog: * @par Changelog:
* <table> * <table>
* <tr><th>Date <th>Version <th>Author <th>Description * <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2022/06/12 <td>1.0 <td>miaow <td>Write this file * <tr><td>2022/06/12 <td>1.0 <td>miaow <td>Write this file
* <tr><td>2023/05/07 <td>1.1 <td>miaow <td>Port to b03
* <tr><td>2023/05/27 <td>1.2 <td>miaow <td>Fix bug caused by the missing encoder_dev_set_clrmod()
* </table> * </table>
*/ */
#include <fifo_dev.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <math.h> #include <math.h>
@ -25,12 +26,6 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#define SET_VALVE_ONLY_N_ON(u32_buf, n) \
bzero(u32_buf, sizeof(u32_buf)); \
SET_VALVE_N_ON(u32_buf, n)
#define SET_VALVE_N_ON(u32_buf, n) u32_buf[n / 32] = 1 << (n % 32)
/** /**
* @brief Value of state machine * @brief Value of state machine
*/ */
@ -43,9 +38,19 @@ typedef enum
queue_uint64_msg_t cmd_queue = {0}; queue_uint64_msg_t cmd_queue = {0};
static status_enum_t status = SLEEPING; static status_enum_t status = SLEEPING;
static int camera_trigger_pulse_count = 1200; typedef struct
static int valve_trigger_pulse_count = 120; {
static int camera_to_valve_pulse_count = 500; uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} camera_trigger_pulse_count_typedef;
camera_trigger_pulse_count_typedef camera_trigger_pulse_count = {
.a = 100,
.b = 100,
.c = 100,
.d = 100};
void process_cmd(uint64_t *cmd); void process_cmd(uint64_t *cmd);
@ -57,51 +62,19 @@ void process_cmd(uint64_t *cmd);
*/ */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
uint64_t cmd;
queue_uint64_init(&cmd_queue, 9999); queue_uint64_init(&cmd_queue, 9999);
// Initialize drivers and clear all caches // Initialize drivers and clear all caches
encoder_dev_init(); encoder_dev_init();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL); encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_set_divide(2, 8); encoder_dev_set_divide(8, 8, 8, 8);
fifo_dev_init();
//==test encoder================================================================
// fifo_dev_init();
// encoder_dev_set_trigmod(ENCODER_TRIG_MODE_EXTERNEL);
// encoder_dev_set_divide(4, 8);
// int a = 1;
// while (a)
// {
// printf("input a\r\n");
// scanf("%d", &a);
// printf("a=%d\r\n\r\n\r\n", a);
// }
// encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
// encoder_dev_deinit();
// queue_uint64_deinit(&cmd_queue);
// return 0;
//==test fifo================================================================
// char data[HOST_COMPUTER_PICTURE_COLUMN_BYTES * HOST_COMPUTER_PICTURE_ROW_NUM + 1];
// fifo_dev_init();
// fifo_dev_write_frame(data);
// printf("%d\r\n", fifo_dev_get_count());
// fifo_dev_write_frame(data);
// printf("%d\r\n", fifo_dev_get_count());
// fifo_dev_clear();
// printf("%d\r\n", fifo_dev_get_count());
// fifo_dev_deinit();
// encoder_dev_deinit();
// return 0;
//==================================================================
fifo_dev_clear();
hostcomputer_init(&cmd_queue); hostcomputer_init(&cmd_queue);
printf("\r\n>>>>>\r\nstatus==SLEEPING\r\n<<<<<\r\n\r\n"); printf("\r\n>>>>>\r\nstatus==SLEEPING\r\n<<<<<\r\n\r\n");
uint64_t cmd;
int TRUE = 1;
// Read from the cmd_queue and excute the command every 100ms // Read from the cmd_queue and excute the command every 100ms
while (TRUE) while (1)
{ {
if (queue_uint64_get(&cmd_queue, &cmd) == 0) if (queue_uint64_get(&cmd_queue, &cmd) == 0)
process_cmd(&cmd); process_cmd(&cmd);
@ -110,11 +83,9 @@ int main(int argc, char *argv[])
// Never run here // Never run here
hostcomputer_deinit(); hostcomputer_deinit();
fifo_dev_clear(); encoder_dev_set_divide(100,100,100,100);
encoder_dev_set_divide(2, 8);
encoder_dev_virtual_trig(20); encoder_dev_virtual_trig(20);
fifo_dev_deinit();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL); encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_deinit(); encoder_dev_deinit();
queue_uint64_deinit(&cmd_queue); queue_uint64_deinit(&cmd_queue);
@ -138,70 +109,37 @@ void process_cmd(uint64_t *cmd)
{ {
// Before running, clear the hardware fifo and hardware encoder. Then, the two dividers and delay value should be set. // Before running, clear the hardware fifo and hardware encoder. Then, the two dividers and delay value should be set.
// Also, the hareware encoder is expected to receiving pluse of encoder: the EXTERNAL mode // Also, the hareware encoder is expected to receiving pluse of encoder: the EXTERNAL mode
fifo_dev_clear();
encoder_dev_flush(); encoder_dev_flush();
encoder_dev_set_divide(valve_trigger_pulse_count, camera_trigger_pulse_count); encoder_dev_set_divide(camera_trigger_pulse_count.a,
fifo_dev_write_delay(camera_to_valve_pulse_count + HOST_COMPUTER_PICTURE_ROW_NUM * HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM); camera_trigger_pulse_count.b,
camera_trigger_pulse_count.c,
camera_trigger_pulse_count.d);
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_EXTERNEL); encoder_dev_set_trigmod(ENCODER_TRIG_MODE_EXTERNEL);
printf("\r\n>>>>>\r\nstatus==RUNNING\r\ncamera_trigger_pulse_count=%d\r\nvalve_trigger_pulse_count=%d\r\n" encoder_dev_set_clrmod(ENCODER_CLEAR_MODE_BOTH);
"camera_to_valve_pulse_count=%d\r\n<<<<<\r\n\r\n", camera_trigger_pulse_count, printf("\r\n>>>>>\r\nstatus==RUNNING\r\ncamera_a=%d\r\ncamera_b=%d\r\ncamera_c=%d\r\ncamera_d=%d\r\n<<<<<\r\n\r\n",
valve_trigger_pulse_count, camera_to_valve_pulse_count + HOST_COMPUTER_PICTURE_ROW_NUM * HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM); camera_trigger_pulse_count.a,
camera_trigger_pulse_count.b,
camera_trigger_pulse_count.c,
camera_trigger_pulse_count.d);
status = RUNNING; status = RUNNING;
} }
else if (tmp_cmd == HOSTCOMPUTER_CMD_TEST) else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_A)
{ {
uint32_t row_data[8] = {0}; camera_trigger_pulse_count.a = tmp_data;
// When to excute TEST cmd (aka testing the valve), hardware fifo and hardware encoder should be cleared.
// A new combination of divider is set: 2 for both valve and camera, for less virtual pluse is needed to triggle valve in INTERNAL mode.
// Note that camera can be triggled during testing.
fifo_dev_clear();
encoder_dev_flush();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_set_divide(2, 8); // fifo out every 8/4=2 cycle, valveboard operate every 2 cycle
// A parameter below 256 represents a single shot, the value of parameter indicates the valve to triggle.
if (tmp_data < 256)
{
SET_VALVE_ONLY_N_ON(row_data, tmp_data);
fifo_dev_write_row(row_data);
// delay for 15000 us and turn off the valve
encoder_dev_virtual_trig(2);
usleep(15000);
encoder_dev_virtual_trig(2);
}
// 257 represents triggle valve from NO.1 to 256 sequenctially. This loop blocks for 25.7s.
else if (tmp_data == 257)
{
for (int i = 0; i < 256; i++)
{
SET_VALVE_ONLY_N_ON(row_data, i);
fifo_dev_write_row(row_data);
bzero(&row_data, sizeof(row_data));
fifo_dev_write_row(row_data);
// printf("%d,%d\r\n", fifo_dev_get_count(), fifob_dev_get_count());
}
for (int i = 0; i < 257; i++)
{
encoder_dev_virtual_trig(2);
usleep(15000);
encoder_dev_virtual_trig(2);
usleep(100000 - 15000);
// printf("%d,%d\r\n", fifo_dev_get_count(), fifob_dev_get_count());
}
}
} }
else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT) else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_B)
{ {
camera_trigger_pulse_count = tmp_data; camera_trigger_pulse_count.b = tmp_data;
} }
else if (tmp_cmd == HOSTCOMPUTER_CMD_SETVALVETRIGPULSECOUNT) else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_C)
{ {
valve_trigger_pulse_count = tmp_data; camera_trigger_pulse_count.c = tmp_data;
} }
else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATOVALVEPULSECOUNT) else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATRIGPULSECOUNT_D)
{ {
camera_to_valve_pulse_count = tmp_data; camera_trigger_pulse_count.d = tmp_data;
} }
} }
// Only in RUNNING state, the lower machine responds to STOP command. // Only in RUNNING state, the lower machine responds to STOP command.
@ -209,12 +147,9 @@ void process_cmd(uint64_t *cmd)
{ {
if (tmp_cmd == HOSTCOMPUTER_CMD_STOP) if (tmp_cmd == HOSTCOMPUTER_CMD_STOP)
{ {
// Clear hardware fifo.
// 10 virtual triggles in internal mode ensure valve is turned off.
// Hardware encoder is flushed for a fresh start. // Hardware encoder is flushed for a fresh start.
fifo_dev_clear();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL); encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_set_divide(4, 4); encoder_dev_set_divide(4, 4, 4, 4);
encoder_dev_virtual_trig(20); encoder_dev_virtual_trig(20);
encoder_dev_flush(); encoder_dev_flush();
status = SLEEPING; status = SLEEPING;

View File

@ -1 +1 @@
1.2 1.3

View File

@ -188,12 +188,12 @@ static long encoder_ioctl(struct file *fp, unsigned int cmd, unsigned long tmp)
// 3. 恢复为原来的状态和模式 // 3. 恢复为原来的状态和模式
writel(data, encoder_cr_addr); writel(data, encoder_cr_addr);
} }
else if (cmd_parsed == ENCODER_CMD_CLEAR_MODE_INTERNAL) else if (cmd_parsed == ENCODER_CMD_CLEAR_MODE_BOTH)
{ {
// 设为允许内部和外部信号清除缓存 // 设为允许内部和外部信号清除缓存
writel(data & ~ENCODER_CR_ICO_MASK, encoder_cr_addr); writel(data & ~ENCODER_CR_ICO_MASK, encoder_cr_addr);
} }
else if (cmd_parsed == ENCODER_CMD_CLEAR_MODE_BOTH) else if (cmd_parsed == ENCODER_CMD_CLEAR_MODE_INTERNAL)
{ {
// 设为仅允许内部清除缓存 // 设为仅允许内部清除缓存
writel(data | ENCODER_CR_ICO_MASK, encoder_cr_addr); writel(data | ENCODER_CR_ICO_MASK, encoder_cr_addr);

View File

@ -57,8 +57,6 @@ int encoder_dev_init()
/** /**
* @brief Set the two divider in the hareware encoder unit. * @brief Set the two divider in the hareware encoder unit.
* @param valve_divide the frequency division factor between the encoder signal and valve output
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @param camera_a_divide the frequency division factor between the encoder signal and camera a triggle signal * @param camera_a_divide the frequency division factor between the encoder signal and camera a triggle signal
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter * Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @param camera_b_divide the frequency division factor between the encoder signal and camera b triggle signal * @param camera_b_divide the frequency division factor between the encoder signal and camera b triggle signal
@ -69,14 +67,13 @@ int encoder_dev_init()
* Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter * Set ENCODER_DEV_DIVIDE_NOT_TO_SET to skip changing the division facter
* @return 0 - success, other - error * @return 0 - success, other - error
*/ */
int encoder_dev_set_divide(int valve_divide, int encoder_dev_set_divide(int camera_a_divide,
int camera_a_divide,
int camera_b_divide, int camera_b_divide,
int camera_c_divide, int camera_c_divide,
int camera_d_divide) int camera_d_divide)
{ {
if (valve_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET) if (valve_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.valve_divide_value = valve_divide; encoder_dev_divide_value_structure.valve_divide_value = 100;
if (camera_a_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET) if (camera_a_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)
encoder_dev_divide_value_structure.camera_a_divide_value = camera_a_divide; encoder_dev_divide_value_structure.camera_a_divide_value = camera_a_divide;
if (camera_b_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET) if (camera_b_divide != ENCODER_DEV_DIVIDE_NOT_TO_SET)

View File

@ -37,8 +37,7 @@ typedef enum
ENCODER_CLEAR_MODE_INTERNAL = 201 ENCODER_CLEAR_MODE_INTERNAL = 201
} encoder_dev_clear_mode_enum; } encoder_dev_clear_mode_enum;
int encoder_dev_set_divide(int valve_divide, int encoder_dev_set_divide(int camera_a_divide,
int camera_a_divide,
int camera_b_divide, int camera_b_divide,
int camera_c_divide, int camera_c_divide,
int camera_d_divide); int camera_d_divide);

View File

@ -1 +1 @@
1.5 1.6