#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); #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); } #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 return; 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; } }