#include "includes.h" /* ==================== �ⲿ���� ==================== */ extern void SendNoteOnMidiEvent(uint8_t Key, uint8_t OnVal); extern void SendNoteOffMidiEvent(uint8_t Key, uint8_t OffVal); extern uint8_t get_note_by_channel(uint8_t ch); extern bool powon; extern bool InModeFlag; uint8_t get_note_by_channel(uint8_t ch) { switch(ch) { case 0: return USE_MIDI.Midi_5; // 5�� case 1: return USE_MIDI.Midi_4; // 4�� case 2: return USE_MIDI.Midi_3; // 3�� case 3: return USE_MIDI.Midi_6; // 6�� case 4: return USE_MIDI.Midi_1; // 1�� case 6: return USE_MIDI.Midi_2; // 2�� default: return 0x3C; } } static uint8_t string_state[7] = {0}; /* ��Ƭ״̬�� */ typedef enum { PICK_STATE_IDLE, PICK_STATE_DOWN, PICK_STATE_UP } pick_state_t; typedef enum { PICK_FSM_STATE_IDLE, PICK_FSM_STATE_DOWN, PICK_FSM_STATE_UP, PICK_FSM_STATE_UP_LONG, } pick_fsm_state_t; static pick_fsm_state_t pick_fsm = PICK_FSM_STATE_IDLE; static pick_state_t pick_prev = PICK_STATE_IDLE; static pick_state_t pick_curr = PICK_STATE_IDLE; bool pick_hold_up = 0; static uint32_t pick_hold_tick = 0; #define PICK_LONG_PRESS_MS 200 static uint8_t key_stable_flag[4] = {0}; bool usb_charging_state = 0; bool usb_charging_laststate = 0; /* ���� */ static uint16_t vol_last = 0xFFFF; uint8_t level = 0; /* ��� */ #define BAT_SAMPLE_COUNT 20 static uint16_t bat_buffer[BAT_SAMPLE_COUNT] = {0}; static uint8_t bat_index = 0; static uint32_t bat_sum = 0; uint8_t percentage = 0; //static uint32_t charge_step_tick = 0; #define VBAT_MIN_RAW 2520 #define VBAT_MAX_RAW 3528 /* ==================== ͨ��0~4,6���������� ==================== */ static void app_adc_string_process(uint8_t channel) { uint16_t adc_val = ADC_ReadChannel(ADC_CHANNEL_0) >> 5; uint8_t vel_out = 80; if (adc_val >= 127) { /* δ���� �� Note Off */ if (string_state[channel]) { string_state[channel] = 0; //SendNoteOffMidiEvent(get_note_by_channel(channel), 0x00); } } else { /* ���� �� ���� */ if (adc_val <= 20) vel_out = 127; else { uint16_t delta = adc_val - 20; vel_out = 127 - delta * 57 / 110; } if (!string_state[channel]) { string_state[channel] = 1; SendNoteOnMidiEvent(get_note_by_channel(channel), vel_out); } } } pick_state_t app_adc_get_pick_input(void) { uint16_t adc_val = ADC_ReadChannel(ADC_CHANNEL_0); pick_prev = pick_curr; if (adc_val <= 1000) pick_curr = PICK_STATE_DOWN; else if (adc_val >= 3800) pick_curr = PICK_STATE_UP; else pick_curr = PICK_STATE_IDLE; return pick_curr; } static void app_adc_pick_process(void) { pick_state_t curstate = app_adc_get_pick_input(); uint32_t now = rt_tick_get(); uint32_t hold_tick; switch(pick_fsm) { case PICK_FSM_STATE_IDLE: if(curstate == PICK_STATE_DOWN) { pick_hold_tick = now; pick_fsm = PICK_FSM_STATE_DOWN; /* 音师:拨片下拨即响(进入 DOWN 触发),不要等复位 */ MainTask_Sendmsg(MSG_ID_BP_KEY,PICK_STATE_DOWN,0,0); } if(curstate == PICK_STATE_UP) { pick_hold_tick = now; pick_fsm = PICK_FSM_STATE_UP; } break; case PICK_FSM_STATE_DOWN: if(curstate != PICK_STATE_DOWN) { pick_fsm = PICK_FSM_STATE_IDLE; } break; case PICK_FSM_STATE_UP: if(curstate != PICK_STATE_UP) { pick_fsm = PICK_FSM_STATE_IDLE; //发送上拨消息 }else { hold_tick = now - pick_hold_tick; if(hold_tick > PICK_LONG_PRESS_MS && !pick_hold_up) { pick_hold_up = 1; pick_fsm = PICK_FSM_STATE_UP_LONG; //发送长按消息 } } break; case PICK_FSM_STATE_UP_LONG: /* 长按已发过,等释放回 IDLE */ if(curstate != PICK_STATE_UP) { pick_fsm = PICK_FSM_STATE_IDLE; pick_hold_up = 0; //发送上拨消息 } break; } } /* ==================== ADC1 in0~3 ==================== */ static void app_adc_key_process(uint8_t idx) { static uint8_t debounce_cnt[4] = {0}; // 每个按键独立消抖计数 uint16_t val = ADC_ReadChannel(ADC_CHANNEL_1); // 按下判定:连续多次采样小于1000 if (val < 1000) { if (!key_stable_flag[idx]) { if (++debounce_cnt[idx] >= 3) // 连续3次满足,判定按下 { key_stable_flag[idx] = 1; ADC_IN1_KEY_Handle(idx, 1); debounce_cnt[idx] = 0; } } else { debounce_cnt[idx] = 0; } } // 释放判定:连续多次采样大于2000 else if (val > 2000) { if (key_stable_flag[idx]) { if (++debounce_cnt[idx] >= 3) // 连续3次满足,判定释放 { key_stable_flag[idx] = 0; debounce_cnt[idx] = 0; } } else { debounce_cnt[idx] = 0; } } // 中间迟滞区间,保持原状态,不做处理 } /* ==================== ADC1 in4 ==================== */ /* 快速探测 Type-C / USB 是否接入(关机开机路径共用) */ bool app_adc_usb_is_plugged(void) { uint16_t val; BSP_SelectAdcChannel(4); /* E_ADC1_FUNCTION_USB_CHECK */ Delay_us(20); val = ADC_ReadChannel(ADC_CHANNEL_1) >> 5; return (val > 80) ? true : false; } static void app_adc_charge_process(void) { uint16_t val = ADC_ReadChannel(ADC_CHANNEL_1) >> 5; /* 插入充电:阈值80,仅状态跳变时执行一次 */ if (val > 80) { if (usb_charging_state != 1) { usb_charging_state = 1; usb_charging_laststate = 1; if (powon) { MainTask_Sendmsg(MSG_ID_CHARG, usb_charging_state, usb_charging_laststate, 0); } else { /* 关机态插电:立即进全屏充电页,勿走开机 Logo */ LOG_I("CHG", "usb plug while soft-off → charge UI"); MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, usb_charging_state, 0); } } } /* 拔掉充电:阈值40,迟滞防抖,仅状态跳变时执行一次 */ else if (val < 40) { if (usb_charging_state != 0) { usb_charging_state = 0; usb_charging_laststate = 0; if (powon) { MainTask_Sendmsg(MSG_ID_CHARG, usb_charging_state, 1, 0); } else { /* 通知 UI 熄灭充电页并关主电 */ MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, 0, 0); BSP_MainPowerEnable(0); } } } } /* ==================== ADC1 in5 ==================== */ static void app_adc_hp_process(void) { uint16_t val = ADC_ReadChannel(ADC_CHANNEL_1) >> 5; if (val > 50) { MainTask_Sendmsg(MSG_ID_HP_SPK_IN, 1, 0, 0); } else { MainTask_Sendmsg(MSG_ID_HP_SPK_IN, 1, 0, 0); } } /* ==================== ADC1 in6 ==================== */ static void app_adc_volume_process(void) { uint16_t val = ADC_ReadChannel(ADC_CHANNEL_1)>>5; if(abs((int16_t)vol_last - (int16_t)val) > 2) { vol_last = val; /* 5 格状态栏音量条:0=静音,5=最大 */ if (val <= 5) level = 0; else if (val <= 35) level = 1; else if (val <= 65) level = 2; else if (val <= 95) level = 3; else if (val <= 115) level = 4; else level = 5; MainTask_Sendmsg(MSG_ID_EC_VOL, val, level, 0); } } /* ==================== ADC1 ͨ��7����� ==================== */ static bat_state_t bat_state = BAT_IDLE; static uint32_t bat_last_sample_tick = 0; /* 上次采样时刻 */ static uint32_t bat_state_tick = 0; /* 进当前状态的时刻 */ static uint8_t bat_charge_paused = 0; /* 本次是否暂停了充电 */ static uint8_t bat_poweron_done = 0; /* 开机首采标志 */ static uint8_t bat_sample_cnt = 0; /* SAMPLE 内已采了几个 */ static uint32_t bat_sample_tick = 0; /* SAMPLE 内上次采样的时刻 */ /* ==================== ��ʼ�� ==================== */ void app_adc_init(void) { for (int i = 0; i < 7; i++) string_state[i] = 0; for (int i = 0; i < 4; i++) key_stable_flag[i] = 0; pick_prev = pick_curr = PICK_STATE_IDLE; pick_hold_up = 0; usb_charging_state = 0; vol_last = 0xFFFF; level = 0; bat_index = 0; bat_sum = 0; percentage = 0; for (int i = 0; i < BAT_SAMPLE_COUNT; i++) bat_buffer[i] = 0; /* 电池状态机复位:下次开机触发首采 */ bat_state = BAT_IDLE; bat_last_sample_tick = 0; bat_charge_paused = 0; bat_poweron_done = 0; bat_sample_cnt = 0; bat_sample_tick = 0; } /* 采样:读 ADC + 滑动平均 */ static void app_adc_battery_do_sample(void) { uint16_t adc_raw = ADC_ReadChannel(ADC_CHANNEL_1); bat_sum -= bat_buffer[bat_index]; bat_buffer[bat_index] = adc_raw; bat_sum += bat_buffer[bat_index]; bat_index = (bat_index + 1) % BAT_SAMPLE_COUNT; } /* 上报:映射成百分比,变化才发消息 */ static void app_adc_battery_report(void) { uint16_t filtered = bat_sum / BAT_SAMPLE_COUNT; uint8_t pct; if (filtered < VBAT_MIN_RAW) pct = 0; else if (filtered > VBAT_MAX_RAW) pct = 100; else pct = 100 * (filtered - VBAT_MIN_RAW) / (VBAT_MAX_RAW - VBAT_MIN_RAW); pct = (pct / 10) * 10; if (pct != percentage) { /* 变化才上报 */ percentage = pct; if(usb_charging_state && !powon) { MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, usb_charging_state, 0); } else { MainTask_Sendmsg(MSG_ID_BATTERY_VALUE, percentage, usb_charging_state, 0); } } } /* 电池采集状态机入口(app_adc_scan 每 1ms 调用,状态推进约每 10ms 一次) */ static void app_adc_battery_process(void) { uint32_t now = rt_tick_get(); switch (bat_state) { case BAT_IDLE: /* 触发:开机后首采,或距上次 ≥30s */ if (/*powon && */!bat_poweron_done) { bat_poweron_done = 1; bat_state = BAT_START; } else if (now - bat_last_sample_tick >= BAT_SAMPLE_INTERVAL_MS) { bat_state = BAT_START; } break; case BAT_START: if (usb_charging_state) /* 充电中:先停充电,采真实电压 */ { BSP_ChargerEnable(0); bat_charge_paused = 1; bat_state_tick = now; bat_state = BAT_WAIT_CHARGE_OFF; } else { bat_charge_paused = 0; bat_state = BAT_SAMPLE; } break; case BAT_WAIT_CHARGE_OFF: if (now - bat_state_tick >= BAT_CHARGE_OFF_WAIT_MS) bat_state = BAT_SAMPLE; break; case BAT_SAMPLE: /* 连续采满 BAT_SAMPLE_COUNT 次(间隔 10ms),填满滑动平均 buffer */ if (now - bat_sample_tick >= 10) { app_adc_battery_do_sample(); bat_sample_cnt++; bat_sample_tick = now; } if (bat_sample_cnt >= BAT_SAMPLE_COUNT) { bat_sample_cnt = 0; /* 采满,进入收尾 */ if (bat_charge_paused) bat_state = BAT_RESTORE_CHARGE; else bat_state = BAT_DONE; } break; case BAT_RESTORE_CHARGE: BSP_ChargerEnable(1); /* 恢复充电 */ bat_charge_paused = 0; bat_state = BAT_DONE; break; case BAT_DONE: app_adc_battery_report(); bat_last_sample_tick = now; bat_state = BAT_IDLE; break; } } void app_adc_scan_all(void) { static uint8_t channel = 0; BSP_SelectAdcChannel(channel); Delay_us(10); // adc_in 0 switch (channel) { case 0: case 1: case 2: case 3: case 4: case 6: if(!InModeFlag) break; app_adc_string_process(channel); break; case 7: if(!InModeFlag) break; app_adc_pick_process(); break; } // adc_in 1 switch (channel) { case 0: case 1: case 2: case 3: if(!InModeFlag) break; app_adc_key_process(channel); break; case 4: app_adc_charge_process(); break; case 5: if(!InModeFlag) break; app_adc_hp_process(); break; case 6: app_adc_volume_process(); break; case 7: app_adc_battery_process(); break; } if(channel < 8) { channel++; }else { channel = 0; } } void app_adc_in1_scan_part(uint8_t channel) { BSP_SelectAdcChannel(channel); Delay_us(10); // adc_in 1 switch (channel) { case 0: case 1: case 2: case 3: app_adc_key_process(channel); break; case 4: app_adc_charge_process(); break; case 5: app_adc_hp_process(); break; case 6: app_adc_volume_process(); break; case 7: app_adc_battery_process(); break; } }