AVS/GD32F103C8T6/App/User/app.c

867 lines
24 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app.h"
#include "can_parsing.h"
#define STROBE_LIGHT_MODE_SETTING_INDEX (0x00)
#define CAN_TYPE_SETTING_INDEX (0x01)
#define STROBE_LIGHT_ENABLE_SETTING_INDEX (0x02)
#define VOLUME_LEVEL_SETTING_INDEX (0x03)
static uint64_t led_rx_timestamp = 0, led_tx_timestamp = 0;
static uint8_t door_front_status = 1, door_front_status_temporary = 1;
static uint8_t door_back_status = 1, door_back_status_temporary = 1;
static uint8_t door_status = 1, door_status_temporary = 1;
static uint8_t turn_left_status = 1, turn_left_status_temporary = 1;
static uint8_t turn_left_parsing_count = 0; /* 转向接收次数 */
static uint8_t turn_right_status = 1, turn_right_status_temporary = 1;
static uint8_t turn_right_parsing_count = 0; /* 转向接收次数 */
static uint8_t emergency_flashers_status = 1, emergency_flashers_status_temporary = 1; /* 双闪 */
static uint8_t reversing_status = 1, reversing_status_temporary = 1;
static uint8_t diaodu_status = 0, diaodu_status_temporry = 0;
static uint8_t volume_1_status = 1, volume_1_status_temporary = 1;
static uint8_t volume_2_status = 1, volume_2_status_temporary = 1;
static uint8_t volume_3_status = 1, volume_3_status_temporary = 1;
static uint8_t volume_4_status = 1, volume_4_status_temporary = 1;
static uint8_t can_type = 0;
static uint8_t strobe_light_flashing_enable = 1; /* 0 关闭; 1 开启 */
static uint8_t strobe_light_flashing_mode = 1; /* 0 常亮; 1 频闪; 2 爆闪; */
static uint32_t strobe_light_flashing_count = 0;
static uint8_t strobe_light_task_uuid = 0; /* 频闪灯控制任务 ID */
static uint8_t emergency_flashers_operate_task_uuid = 0; /* 双闪状态下频闪灯控制任务 ID */
static uint8_t volume_level = 0; /* 音量默认级别 */
static uint8_t set_volume_count = 0;
/* 车辆状态上传状态, 0x00 不需要上传0x01 需要上传 */
static uint8_t door_front_upload_status = 0;
static uint8_t door_back_upload_status = 0;
static uint8_t turn_left_upload_status = 0;
static uint8_t turn_right_upload_status = 0;
static uint8_t reversing_upload_status = 0;
static uint8_t diaodu_upload_status = 0;
/* 频闪灯复位*/
static void strobe_light_reset(void);
/* 频闪灯闪烁*/
static void strobe_light_toggle(uint8_t count);
#ifdef USE_LED
/* LED 指示灯分析任务 */
static void led_parsing_task(uint8_t uuid);
#endif
/* 设置音量级别 */
static void set_volume_level(uint8_t level);
/* 音量级别控制按钮 分析任务 */
static void volume_io_control_parsing_task(uint8_t uuid);
/* can 数据分析任务 */
static void can_parsing_task(uint8_t uuid);
/* 频闪灯控制任务 */
static void strobe_light_operate_task(uint8_t uuid);
/* 双闪状态下频闪灯控制任务 */
static void emergency_flashers_operate_task(uint8_t uuid);
/* 车辆状态 分析任务 */
static void vehicle_status_parsing_task(uint8_t uuid);
/* 车辆状态 上传任务 */
static void vehicle_status_upload_task(uint8_t uuid);
/* 发送状态灯更新 */
static void led_tx_update(void);
/* 接受状态灯更新 */
static void led_rx_update(void);
/**
* @brief 定时器回调处理函数
*/
void timer_interrupt_callback(uint32_t timer_periph)
{
}
/**
* @brief GPIO中断回调函数
*/
void gpio_interrupt_callback(uint32_t pin)
{
switch (pin)
{
case DOOR_FRONT_PIN:
door_front_status_temporary = gpio_input_bit_get(DOOR_FRONT_PERIPH, DOOR_FRONT_PIN);
door_front_upload_status = 0x01;
break;
case DOOR_BACK_PIN:
door_back_status_temporary = gpio_input_bit_get(DOOR_BACK_PERIPH, DOOR_BACK_PIN);
door_back_upload_status = 0x01;
break;
case TURN_LEFT_PIN:
turn_left_status_temporary = gpio_input_bit_get(TURN_LEFT_PERIPH, TURN_LEFT_PIN);
turn_left_upload_status = 0x01;
break;
case TURN_RIGHT_PIN:
turn_right_status_temporary = gpio_input_bit_get(TURN_RIGHT_PERIPH, TURN_RIGHT_PIN);
turn_right_upload_status = 0x01;
break;
case REVERSING_PIN:
reversing_status_temporary = gpio_input_bit_get(REVERSING_PERIPH, REVERSING_PIN);
reversing_upload_status = 0x01;
break;
}
}
/**
* @brief 串口中断回调函数
*/
void usart_interrupt_callback(uint32_t usart_periph, uint8_t data)
{
switch (usart_periph)
{
case HOST_USART_PERIPH:
api_concat_byte(data);
break;
case RS485_USART_PERIPH:
diaodu_concat_byte(data);
break;
}
}
/**
* @brief 应用程序初始化
*/
void app_init(void)
{
/* 上位机通讯协议初始化 */
api_init();
/* 语音芯片初始化 */
v58_init();
m62429_init();
ir_init();
/* 主动获取一次IO状态 */
door_front_status = door_front_status_temporary = gpio_input_bit_get(DOOR_FRONT_PERIPH, DOOR_FRONT_PIN);
door_back_status = door_back_status_temporary = gpio_input_bit_get(DOOR_BACK_PERIPH, DOOR_BACK_PIN);
turn_left_status = turn_left_status_temporary = gpio_input_bit_get(TURN_LEFT_PERIPH, TURN_LEFT_PIN);
turn_right_status = turn_right_status_temporary = gpio_input_bit_get(TURN_RIGHT_PERIPH, TURN_RIGHT_PIN);
reversing_status = reversing_status_temporary = gpio_input_bit_get(REVERSING_PERIPH, REVERSING_PIN);
can_type = setting_read_byte(CAN_TYPE_SETTING_INDEX, 0x00);
strobe_light_flashing_mode = setting_read_byte(STROBE_LIGHT_MODE_SETTING_INDEX, 0x01);
strobe_light_flashing_enable = setting_read_byte(STROBE_LIGHT_ENABLE_SETTING_INDEX, 0x01);
volume_level = setting_read_byte(VOLUME_LEVEL_SETTING_INDEX, 0x01); /* 默认中档 */
set_volume_level(volume_level);
/* 创建 上位机数据检测任务 */
task_create((task_func)api_process, 0);
/* 创建 红外遥控器数据检测任务 */
task_create((task_func)ir_process, 0);
/* 创建 调度数据检测任务 */
task_create((task_func)diaodu_process, 0);
/* 创建 心跳发送任务 */
task_create((task_func)api_upload_heart_beat, 3000);
#ifdef USE_LED
/* 创建 LED 指示灯分析任务 */
task_create(led_parsing_task, 30);
#endif
/* 创建 CAN数据分析任务 */
task_create(can_parsing_task, 0);
/* 创建 频闪灯控制任务, 并挂起 */
strobe_light_task_uuid = task_create(strobe_light_operate_task, 500);
task_suspend(strobe_light_task_uuid);
/* 创建 双闪状态下频闪灯控制任务 */
emergency_flashers_operate_task_uuid = task_create(emergency_flashers_operate_task, 500);
task_suspend(emergency_flashers_operate_task_uuid);
/* 创建 车辆状态分析任务 */
task_create(vehicle_status_parsing_task, 1000);
/* 创建 车辆状态 定时上传任务 */
task_create(vehicle_status_upload_task, 100);
/* 创建 音量按键 定时分析任务 */
task_create(volume_io_control_parsing_task, 100);
}
static void strobe_light_reset(void)
{
gpio_bit_write(LED_STROBE_PERIPH, LED_STROBE_PIN, RESET);
}
static void strobe_light_toggle(uint8_t count)
{
while(count--)
{
gpio_bit_write(LED_STROBE_PERIPH, LED_STROBE_PIN, SET);
delay_ms(100);
gpio_bit_write(LED_STROBE_PERIPH, LED_STROBE_PIN, RESET);
delay_ms(100);
}
}
#ifdef USE_LED
static void led_parsing_task(uint8_t uuid)
{
/* 超过500ms钟未发送数据熄灭发送指示灯 */
if (timestamp - led_rx_timestamp > 500)
{
gpio_bit_write(LED_RX_PERIPH, LED_RX_PIN, RESET);
led_rx_timestamp = timestamp;
}
/* 超过500ms钟未接收到数据熄灭接收指示灯 */
if (timestamp - led_tx_timestamp > 500)
{
gpio_bit_write(LED_TX_PERIPH, LED_TX_PIN, RESET);
led_tx_timestamp = timestamp;
}
}
#endif
static void set_volume_level(uint8_t level)
{
switch (level)
{
case 0x00:
m62429_set_vol(0);
strobe_light_flashing_enable = 0x01;
break;
case 0x01:
m62429_set_vol(8);
strobe_light_flashing_enable = 0x01;
break;
case 0x02:
m62429_set_vol(9);
strobe_light_flashing_enable = 0x01;
break;
case 0x03:
m62429_set_vol(11);
strobe_light_flashing_enable = 0x00;
break;
default:
return;
}
if (level == 3)
gpio_bit_write(AMP_CTRL_PERIPH, AMP_CTRL_PIN, RESET); /* 停止功放 */
else
gpio_bit_write(AMP_CTRL_PERIPH, AMP_CTRL_PIN, SET); /* 开启功放 */
setting_write_byte(STROBE_LIGHT_ENABLE_SETTING_INDEX, strobe_light_flashing_enable);
setting_write_byte(VOLUME_LEVEL_SETTING_INDEX, volume_level = level);
setting_save();
}
static void volume_io_control_parsing_task(uint8_t uuid)
{
uint8_t level = 0xFF;
volume_1_status_temporary = gpio_input_bit_get(VOLUME_1_PERIPH, VOLUME_1_PIN);
volume_2_status_temporary = gpio_input_bit_get(VOLUME_2_PERIPH, VOLUME_2_PIN);
volume_3_status_temporary = gpio_input_bit_get(VOLUME_3_PERIPH, VOLUME_3_PIN);
volume_4_status_temporary = gpio_input_bit_get(VOLUME_4_PERIPH, VOLUME_4_PIN);
if (volume_1_status != volume_1_status_temporary)
{
volume_1_status = volume_1_status_temporary;
if (volume_1_status == 0)
level = 0;
}
if (volume_2_status != volume_2_status_temporary)
{
volume_2_status = volume_2_status_temporary;
if (volume_2_status == 0)
level = 1;
}
if (volume_3_status != volume_3_status_temporary)
{
volume_3_status = volume_3_status_temporary;
if (volume_3_status == 0)
level = 2;
}
if (volume_4_status != volume_4_status_temporary)
{
volume_4_status = volume_4_status_temporary;
if (volume_4_status == 0)
level = 3;
}
if (level != 0xFF)
{
set_volume_level(level);
api_upload_data_forwarding(0x06, level);
}
}
static void can_parsing_task(uint8_t uuid)
{
can_receive_message_struct receive_message = {0};
if (can_try_receive(CAN0, &receive_message))
{
/* CAN 解析 */
if (receive_message.rx_ff == CAN_FF_EXTENDED)
{
switch (can_type)
{
case 0x00:
can_byd_01_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
case 0x01:
can_byd_02_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
case 0x02:
can_byd_03_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
case 0x03:
can_yutong_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
case 0x04:
can_jinlong_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
case 0x05:
can_ankai_parsing(receive_message.rx_efid, receive_message.rx_data, &door_front_status_temporary, &door_back_status_temporary, &turn_left_status_temporary, &turn_right_status_temporary, &reversing_status_temporary);
break;
}
if (door_front_status_temporary != door_front_status)
door_front_upload_status = 0x01;
if (door_back_status_temporary != door_back_status)
door_back_upload_status = 0x01;
if (turn_left_status_temporary != turn_left_status)
turn_left_upload_status = 0x01;
if (turn_right_status_temporary != turn_right_status)
turn_right_upload_status = 0x01;
if (reversing_status_temporary != reversing_status)
reversing_upload_status = 0x01;
}
}
}
/* 频闪灯控制任务 */
static void strobe_light_operate_task(uint8_t uuid)
{
if (strobe_light_flashing_enable == 0)
{
/* 恢复频闪灯状态 */
strobe_light_reset();
strobe_light_flashing_count = 0;
return;
}
strobe_light_flashing_count += 1;
if (strobe_light_flashing_mode == 0)
{
/* 设置任务频率 1000 毫秒 */
task_set_frequency(uuid, 1000);
/* 常亮 */
gpio_bit_write(LED_STROBE_PERIPH, LED_STROBE_PIN, SET);
/* 计数归零 */
strobe_light_flashing_count = 0;
}
else if (strobe_light_flashing_mode == 1)
{
/* 频闪 */
gpio_bit_toggle(LED_STROBE_PERIPH, LED_STROBE_PIN);
if (strobe_light_flashing_count >= 4)
{
strobe_light_flashing_count = 0;
task_set_frequency(uuid, 1000);
}
else if (strobe_light_flashing_count == 2)
task_set_frequency(uuid, 500);
else
task_set_frequency(uuid, 50);
}
else if (strobe_light_flashing_mode == 2)
{
/* 爆闪 */
gpio_bit_toggle(LED_STROBE_PERIPH, LED_STROBE_PIN);
if (strobe_light_flashing_count >= 20)
{
strobe_light_flashing_count = 0;
task_set_frequency(uuid, 1000);
}
else
task_set_frequency(uuid, 50);
}
}
static void emergency_flashers_operate_task(uint8_t uuid)
{
strobe_light_flashing_count += 1;
/* 频闪 */
gpio_bit_toggle(LED_STROBE_PERIPH, LED_STROBE_PIN);
if (strobe_light_flashing_count >= 4)
{
strobe_light_flashing_count = 0;
task_set_frequency(uuid, 1000);
}
else if (strobe_light_flashing_count == 2)
task_set_frequency(uuid, 500);
else
task_set_frequency(uuid, 50);
}
static void vehicle_status_parsing_task(uint8_t uuid)
{
uint8_t status = 0xFF, status_type = 0xFF;
uint8_t door_change = 0;
/* 倒车状态判断 */
if (reversing_status != reversing_status_temporary)
{
reversing_status = reversing_status_temporary;
status_type = 3;
status = reversing_status;
/* 优先级最高, 如果状态为触发, 关闭语音 */
if (reversing_status == 0)
v58_stop();
goto EXECUTE;
}
/* 处于倒车状态时, 不继续检测 */
if (reversing_status == 0)
return;
/* 进出站状态判断 */
if (diaodu_status_temporry != 0 && diaodu_status != diaodu_status_temporry)
{
diaodu_status = diaodu_status_temporry;
/* 到站 */
if (diaodu_status == 1)
{
status_type = 4;
status = 0x00;
/* 优先级最高,关闭语音 */
v58_stop();
}
///* 出站 */
// else if(diaodu_status == 2)
// status_type = 5;
goto EXECUTE;
}
if (door_front_status_temporary != door_front_status)
door_front_status = door_front_status_temporary;
if (door_back_status_temporary != door_back_status)
door_back_status = door_back_status_temporary;
door_status_temporary = door_front_status_temporary | door_back_status_temporary;
if (door_status != door_status_temporary)
{
door_status = door_status_temporary;
status_type = 0;
status = door_status;
}
/* 进站状态, 不继续执行 */
if (diaodu_status == 1)
{
/* 当前后门开启后 */
if (door_status == 0)
{
/* 重置进站状态 */
diaodu_status = diaodu_status_temporry = 0;
/* 关闭语音 */
v58_stop();
goto EXECUTE;
}
return;
}
/* 当前后门开启后, 不处理其他数据 */
if (door_status == 0)
goto EXECUTE;
/* 左转弯状态判断 */
if (turn_left_status != turn_left_status_temporary)
{
/* 如果未触发状态, 需进行二次判断 */
if (turn_left_status_temporary == 1)
{
turn_left_parsing_count++;
if (turn_left_parsing_count < 3)
goto TURN_RIGHT_STATUS_TAG2;
}
turn_left_parsing_count = 0;
turn_left_status = turn_left_status_temporary;
status_type = 1;
status = turn_left_status;
/* 屏蔽此时左转弯数据 */
if (turn_left_status == 1 && turn_right_status == 0)
status_type = 0xFF;
}
TURN_RIGHT_STATUS_TAG2:
/* 右转弯状态判断 */
if (turn_right_status != turn_right_status_temporary)
{
/* 如果未触发状态, 需进行二次判断 */
if (turn_right_status_temporary == 1)
{
turn_right_parsing_count++;
if (turn_right_parsing_count < 3)
goto EXECUTE;
}
turn_right_parsing_count = 0;
turn_right_status = turn_right_status_temporary;
status_type = 2;
status = turn_right_status;
/* 屏蔽此时右转弯数据 */
if (turn_right_status == 1 && turn_left_status == 0)
status_type = 0xFF;
}
#if 0
/* 判断双闪状态 */
emergency_flashers_status_temporary = turn_left_status | turn_right_status;
if (emergency_flashers_status != emergency_flashers_status_temporary)
{
emergency_flashers_status = emergency_flashers_status_temporary;
if (emergency_flashers_status_temporary == 0)
{
/* 挂起 频闪灯控制任务 */
task_suspend(strobe_light_task_uuid);
/* 恢复频闪灯状态 */
strobe_light_reset();
/* 停止语音播报 */
v58_stop();
/* 恢复 双闪状态下频闪灯控制任务 */
task_resume(emergency_flashers_operate_task_uuid);
#if defined(USE_AK517)
ak517_please_note_that();
#elif defined(USE_QGEL50X)
qgel50x_please_note_that();
#endif
}
else if (emergency_flashers_status_temporary == 1)
{
/* 挂起 频闪灯控制任务 */
task_suspend(emergency_flashers_operate_task_uuid);
/* 恢复频闪灯状态 */
strobe_light_reset();
/* 停止语音播报 */
v58_stop();
}
}
#endif
EXECUTE:
if (status_type == 0xFF || emergency_flashers_status_temporary == 0)
return;
if (status == 0x01)
{
/* 挂起 频闪灯控制任务 */
task_suspend(strobe_light_task_uuid);
/* 恢复频闪灯状态 */
strobe_light_reset();
/* 停止语音播报 */
v58_stop();
}
else
{
/* 停止语音播报 */
v58_stop();
/* 播报语音 */
switch (status_type)
{
case 0:
v58_door_opening_warning();
break;
case 1:
v58_left_turn_warning();
break;
case 2:
v58_right_turn_warning();
break;
case 3:
v58_reverse_warning();
break;
case 4:
v58_arrival_warning();
break;
case 5:
return;
}
/* 恢复 频闪灯控制任务 */
task_resume(strobe_light_task_uuid);
}
}
/* IO 数据定时上传任务 */
static void vehicle_status_upload_task(uint8_t uuid)
{
if (door_front_upload_status == 0x01)
{
api_upload_vehicle_status(0x00, door_front_status_temporary);
api_upload_data_forwarding(0x00, door_front_status_temporary);
door_front_upload_status = 0x00;
}
if (door_back_upload_status == 0x01)
{
api_upload_vehicle_status(0x01, door_back_status_temporary);
api_upload_data_forwarding(0x01, door_back_status_temporary);
door_back_upload_status = 0x00;
}
if (turn_left_upload_status == 0x01)
{
api_upload_vehicle_status(0x02, turn_left_status_temporary);
api_upload_data_forwarding(0x02, turn_left_status_temporary);
turn_left_upload_status = 0x00;
}
if (turn_right_upload_status == 0x01)
{
api_upload_vehicle_status(0x03, turn_right_status_temporary);
api_upload_data_forwarding(0x03, turn_right_status_temporary);
turn_right_upload_status = 0x00;
}
if (reversing_upload_status == 0x01)
{
api_upload_vehicle_status(0x04, reversing_status_temporary);
api_upload_data_forwarding(0x04, reversing_status_temporary);
reversing_upload_status = 0x00;
}
if (diaodu_upload_status == 0x01)
{
api_upload_vehicle_status(0x05, diaodu_status_temporry);
api_upload_data_forwarding(0x05, diaodu_status_temporry);
diaodu_upload_status = 0x00;
}
}
static void led_tx_update(void)
{
#ifdef USE_LED
gpio_bit_toggle(LED_TX_PERIPH, LED_TX_PIN);
led_tx_timestamp = timestamp;
#endif
}
static void led_rx_update(void)
{
#ifdef USE_LED
gpio_bit_toggle(LED_RX_PERIPH, LED_RX_PIN);
led_rx_timestamp = timestamp;
#endif
}
void diaodu_arrival_or_departure_parsing(uint8_t status)
{
diaodu_status_temporry = status;
diaodu_upload_status = 0x01;
}
void ir_key_triggered(uint8_t key)
{
uint8_t level = 0x00;
if (key == 0x98) /* + */
level = volume_level - 1;
else if (key == 0x68) /* - */
level = volume_level + 1;
else if(key == 0xA2)
level = 3;
else
return;
strobe_light_toggle(2);
set_volume_level(level);
api_upload_data_forwarding(0x06, level);
}
void api_notify_data_upload(uint8_t *buffer, uint16_t length)
{
led_tx_update();
usart_send_bytes(HOST_USART_PERIPH, buffer, length);
}
void api_notify_set_strobe_light_mode(uint8_t mode)
{
led_rx_update();
strobe_light_flashing_mode = mode;
setting_write_byte(STROBE_LIGHT_MODE_SETTING_INDEX, mode);
setting_save();
api_response_set_strobe_light_mode(API_SUCCESS);
}
void api_notify_get_strobe_light_mode(void)
{
led_rx_update();
api_response_get_strobe_light_mode(API_SUCCESS, strobe_light_flashing_mode);
}
void api_notify_set_volume_level(uint8_t level)
{
led_rx_update();
set_volume_level(level);
api_response_set_volume_level(API_SUCCESS);
api_upload_data_forwarding(0x06, level);
}
void api_notify_get_volume_level(void)
{
api_response_get_volume_level(API_SUCCESS, volume_level);
}
void api_notify_set_can_type(uint8_t type)
{
led_rx_update();
can_type = type;
setting_write_byte(CAN_TYPE_SETTING_INDEX, type);
setting_save();
api_response_set_can_type(API_SUCCESS);
}
void api_notify_get_can_type(void)
{
led_rx_update();
api_response_get_can_type(API_SUCCESS, can_type);
}
void api_notify_send_audio_pulse(uint8_t pulse_count)
{
v58_send_pulse(pulse_count);
api_response_send_audio_pulse(API_SUCCESS);
}
void api_notify_data_forwarding(uint8_t type, uint8_t value)
{
switch (type)
{
case 0x00:
door_front_status_temporary = value;
break;
case 0x01:
door_back_status_temporary = value;
break;
case 0x02:
turn_left_status_temporary = value;
break;
case 0x03:
turn_right_status_temporary = value;
break;
case 0x04:
reversing_status_temporary = value;
break;
case 0x05:
diaodu_status_temporry = value;
break;
case 0x06:
set_volume_level(value);
break;
}
}