lowermachine/source/linux_app/main.c
Miaow 71f8e672d5 机器已经部署到淮安
8月底出差告一段落,运行一切正常
1. 添加了喷阀数据队列走空计数和自动补偿功能
2. 喷阀数据队列发生不可恢复的异常时向上位机报告错误
3. 取消双FIFO
2022-09-01 21:40:16 +08:00

225 lines
7.7 KiB
C

/**
* @file main.c
* @brief Excute the commands from host_computer
* @author miaow (3703781@qq.com)
* @version 1.0
* @date 2022/06/12
* @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/12 <td>1.0 <td>miaow <td>Write this file
* </table>
*/
#include <fifo_dev.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <math.h>
#include <queue_uint64.h>
#include <encoder_dev.h>
#include <host_computer.h>
#include <memory.h>
#include <stdio.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
*/
typedef enum
{
SLEEPING = 0,
RUNNING = 1,
} status_enum_t;
queue_uint64_msg_t cmd_queue = {0};
static status_enum_t status = SLEEPING;
static int camera_trigger_pulse_count = 1200;
static int valve_trigger_pulse_count = 120;
static int camera_to_valve_pulse_count = 500;
void process_cmd(uint64_t *cmd);
/**
* @brief Read from the cmd_queue and excute the command every 100ms.
* @param argc not used
* @param argv not used
* @return int should not return.
*/
int main(int argc, char *argv[])
{
queue_uint64_init(&cmd_queue, 9999);
// Initialize drivers and clear all caches
encoder_dev_init();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_set_divide(2, 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);
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
while (TRUE)
{
if (queue_uint64_get(&cmd_queue, &cmd) == 0)
process_cmd(&cmd);
usleep(1000);
}
// Never run here
hostcomputer_deinit();
fifo_dev_clear();
encoder_dev_set_divide(2, 8);
encoder_dev_virtual_trig(20);
fifo_dev_deinit();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_deinit();
queue_uint64_deinit(&cmd_queue);
return 0;
}
/**
* @brief Excute the command and control the states
* @param cmd The command to be excuted
*/
void process_cmd(uint64_t *cmd)
{
int tmp_cmd = (int)*cmd;
int tmp_data = (int)(*cmd >> 32);
// Only in the SLEEPING state, it resbonds to START or TEST command.
if (status == SLEEPING)
{
if (tmp_cmd == HOSTCOMPUTER_CMD_START)
{
// 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
fifo_dev_clear();
encoder_dev_flush();
encoder_dev_set_divide(valve_trigger_pulse_count, camera_trigger_pulse_count);
fifo_dev_write_delay(camera_to_valve_pulse_count + HOST_COMPUTER_PICTURE_ROW_NUM * HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM);
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"
"camera_to_valve_pulse_count=%d\r\n<<<<<\r\n\r\n", camera_trigger_pulse_count,
valve_trigger_pulse_count, camera_to_valve_pulse_count + HOST_COMPUTER_PICTURE_ROW_NUM * HOST_COMPUTER_PICTURES_BEGINNING_IGNORE_NUM);
status = RUNNING;
}
else if (tmp_cmd == HOSTCOMPUTER_CMD_TEST)
{
uint32_t row_data[8] = {0};
// 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)
{
camera_trigger_pulse_count = tmp_data;
}
else if (tmp_cmd == HOSTCOMPUTER_CMD_SETVALVETRIGPULSECOUNT)
{
valve_trigger_pulse_count = tmp_data;
}
else if (tmp_cmd == HOSTCOMPUTER_CMD_SETCAMERATOVALVEPULSECOUNT)
{
camera_to_valve_pulse_count = tmp_data;
}
}
// Only in RUNNING state, the lower machine responds to STOP command.
else if (status == RUNNING)
{
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.
fifo_dev_clear();
encoder_dev_set_trigmod(ENCODER_TRIG_MODE_INTERNEL);
encoder_dev_set_divide(4, 4);
encoder_dev_virtual_trig(20);
encoder_dev_flush();
status = SLEEPING;
printf("\r\n>>>>>\r\nstatus==SLEEPING\r\n<<<<<\r\n\r\n");
}
}
}