K1Guitar/protocol/bl_uart_parse.c

833 lines
27 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 "includes.h"
// Э<><D0AD>֡ͷ/֡β
#define FRAME_SYS_HEAD 0xF0
#define FRAME_SYS_TAIL 0xF7
#define FRAME_MIDI_NOTEON 0x90
#define FRAME_MIDI_NOTEOFF 0x80
#define FRAME_MIDI_PROCHANGE 0xC0
#define UART4_RCV_TIMEOUT_MS 50
/**
* @brief UART4<54><34><EFBFBD><EFBFBD>״̬ö<CCAC><C3B6>
*/
typedef enum
{
UART4_RCV_BUFF_IDLE, // <20><><EFBFBD><EFBFBD>״̬
UART4_RCV_BUFF_HEAD, // <20><><EFBFBD><EFBFBD>֡ͷ<D6A1><CDB7>̶<EFBFBD><CCB6>ֽ<EFBFBD>(0x60/0x51)
UART4_RCV_BUFF_CMD1, // <20><>ָ<EFBFBD><D6B8>
UART4_RCV_BUFF_CMD2, // <20><>ָ<EFBFBD><D6B8>
UART4_RCV_BUFF_DATA, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UART4_RCV_BUFF_END, // ֡β<D6A1><CEB2><EFBFBD><EFBFBD>
UART4_RCV_BUFF_MIDI1,
UART4_RCV_BUFF_MIDI2,
UART4_RCV_BUFF_MIDIEND
} UART4_RCV_StatusType;
#define UART4_PROCESS_BUFF_SIZE 64 /* 02 04 full chord-map frame is 47 bytes */
// UART4<54><34><EFBFBD><EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>
static UART4_RCV_StatusType UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
static uint8_t UART4_Process_Buff[UART4_PROCESS_BUFF_SIZE];
static uint8_t UART4_RCV_cnt = 0;
//static uint32_t UART4_RCV_Last_Tick = 0;
//static uint8_t expect_data_len = 0;
/**
* @brief ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5A3A8>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>UART3<54><33><EFBFBD>
*/
typedef struct
{
uint8_t cmd[2]; // <20><>ָ<EFBFBD><D6B8>+<2B><>ָ<EFBFBD><D6B8>
void (*handler)(uint8_t *data);// <20><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
} BLE_SysExCmdItem;
// ==============================
// ָ<><EFBFBD><EEB4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB> static<69><63>
// ==============================
static void handleDevDisconnect(uint8_t *data);
static void handleDevConnect(uint8_t *data);
static void handleDevName(uint8_t *data);
static void handleFwMainVer(uint8_t *data);
static void handleSoundVer(uint8_t *data);
static void handleUIVer(uint8_t *data);
static void handleOtherInfo(uint8_t *data);
static void handleDevCode(uint8_t *data);
static void handleAutoPowerOff(uint8_t *data);
static void handleUserFwVer(uint8_t *data);
static void handleAutoPowerOffSet(uint8_t *data);
static void handleFwCode(uint8_t *data);
static void handleReadRhythmMap(uint8_t *data);
static void handlePitchOffset(uint8_t *data);
static void handleChordOffset(uint8_t *data);
static void handleResetChordMap(uint8_t *data);
static void handleRhythmStyle(uint8_t *data);
static void handleStringTimbre(uint8_t *data);
static void handleBPM(uint8_t *data);
static void handleTranspose(uint8_t *data);
static void handleLED0(uint8_t *data);
static void handleLED1(uint8_t *data);
static void handleLED2(uint8_t *data);
static void handleLED3(uint8_t *data);
static void handleLED4(uint8_t *data);
static void handleLED5(uint8_t *data);
static void handleLED6(uint8_t *data);
static void handleDeviceReset(uint8_t *data);
static void handleIntro(uint8_t *data);
static void handleInterlude(uint8_t *data);
static void handleOutro(uint8_t *data);
static void handleEnd(uint8_t *data);
static void handleSectionA(uint8_t *data);
static void handleSectionB(uint8_t *data);
static void handleSectionC(uint8_t *data);
static void handleSectionD(uint8_t *data);
/*************************************************
* <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>
*************************************************/
static const BLE_SysExCmdItem bleSysExCmdTable[] =
{
/*======== 1. device info 0x01 ========*/
{{0x01, 0x00}, handleDevDisconnect}, /* disconnect */
{{0x01, 0x01}, handleDevConnect}, /* connect */
{{0x01, 0x02}, handleDevName}, /* device name */
{{0x01, 0x03}, handleFwMainVer}, /* fw main version */
{{0x01, 0x04}, handleSoundVer}, /* sound version */
{{0x01, 0x05}, handleUIVer}, /* UI version */
{{0x01, 0x06}, handleOtherInfo}, /* other info */
{{0x01, 0x07}, handleDevCode}, /* device code (96bit UID) */
{{0x01, 0x0A}, handleAutoPowerOff}, /* auto power-off read (minutes) */
{{0x01, 0x0C}, handleUserFwVer}, /* user fw version */
{{0x01, 0x11}, handleAutoPowerOffSet}, /* auto power-off set (minutes) */
{{0x01, 0x0F}, handleFwCode}, /* fw code (MIDI/BLE-safe; replaces 01 FF) */
{{0x01, 0xFF}, handleFwCode}, /* fw code alias (raw UART only; 0xFF illegal in BLE-MIDI SysEx) */
/*======== 2. chord map 0x02 ========*/
{{0x02, 0x01}, handleReadRhythmMap}, /* read chord/pitch map */
{{0x02, 0x02}, handlePitchOffset}, /* pitch offset */
{{0x02, 0x03}, handleChordOffset}, /* chord offset */
{{0x02, 0x04}, handleResetChordMap}, /* write whole map (default reset) */
/*======== 3. guitar params 0x03 ========*/
{{0x03, 0x04}, handleRhythmStyle}, /* rhythm style r/w + user list */
{{0x03, 0x05}, handleStringTimbre}, /* string timbre r/w */
{{0x03, 0x06}, handleBPM}, /* BPM r/w */
{{0x03, 0x07}, handleTranspose}, /* transpose r/w */
/*======== 4. play / LED 0x04 ========*/
{{0x04, 0x00}, handleLED0}, /* LED 1 */
{{0x04, 0x01}, handleLED1}, /* LED 2 */
{{0x04, 0x02}, handleLED2}, /* LED 3 */
{{0x04, 0x03}, handleLED3}, /* LED 4 */
{{0x04, 0x04}, handleLED4}, /* LED 5 */
{{0x04, 0x05}, handleLED5}, /* LED 6 */
{{0x04, 0x06}, handleLED6}, /* LED 7 */
{{0x04, 0x07}, handleEnd}, /* end / stop play */
/*======== 5. reset / power off 0x05 ========*/
{{0x05, 0x00}, handleDeviceReset}, /* device reset -> soft power off */
/*======== 6. section jump 0x06 ========*/
{{0x06, 0x01}, handleIntro}, /* intro */
{{0x06, 0x02}, handleInterlude}, /* interlude */
{{0x06, 0x03}, handleOutro}, /* outro */
{{0x06, 0x05}, handleSectionA}, /* section A */
{{0x06, 0x06}, handleSectionB}, /* section B */
{{0x06, 0x07}, handleSectionC}, /* section C */
{{0x06, 0x08}, handleSectionD}, /* section D */
};
// ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define BLE_SYS_EX_CMD_COUNT (sizeof(bleSysExCmdTable) / sizeof(BLE_SysExCmdItem))
/**
* @brief <20><><EFBFBD><EFBFBD>SysExָ<78><D6B8>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
* @param data: <20><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
* @param cnt: ֡<><D6A1><EFBFBD><EFBFBD>
*/
void processBLESysEXData(uint8_t* data, uint8_t cnt)
{
//ResetAutoPowerCount();
// ֡У<D6A1><D0A3>
if (data[0] != FRAME_SYS_HEAD || data[cnt - 1] != FRAME_SYS_TAIL || cnt > UART4_PROCESS_BUFF_SIZE || data[1] != 0x60)
{
return;
}
LOG_I("BLE", "sysex ok len=%u cmd=%02X %02X", (unsigned)cnt, data[2], data[3]);
// ȡ<><C8A1>ָ<EFBFBD><D6B8> + <20><>ָ<EFBFBD><D6B8>
uint8_t cmd[2] = {data[2], data[3]};
// <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>ƥ<EFBFBD><C6A5>
for (uint8_t i = 0; i < BLE_SYS_EX_CMD_COUNT; i++)
{
if (memcmp(cmd, bleSysExCmdTable[i].cmd, 2) == 0)
{
if (bleSysExCmdTable[i].handler != NULL)
{
bleSysExCmdTable[i].handler(data);
}
return;
}
}
}
void UART4_Data_Process(volatile uint8_t* data)
{
uint8_t rcv = *data;
uint32_t now = rt_tick_get();
static uint32_t last_tick;
if(now - last_tick >= UART4_RCV_TIMEOUT_MS)
{
last_tick = now;
memset(UART4_Process_Buff, 0, sizeof(UART4_Process_Buff));
UART4_RCV_cnt = 0;
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
}
switch (UART4_RCV_Status)
{
case UART4_RCV_BUFF_IDLE:
memset(UART4_Process_Buff, 0, sizeof(UART4_Process_Buff));
UART4_RCV_cnt = 0;
switch(rcv & 0xF0)
{
case FRAME_SYS_HEAD:
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
UART4_RCV_Status = UART4_RCV_BUFF_HEAD;
break;
case FRAME_MIDI_NOTEON:
case FRAME_MIDI_NOTEOFF:
case FRAME_MIDI_PROCHANGE:
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
UART4_RCV_Status = UART4_RCV_BUFF_MIDI1;
break;
default:UART4_RCV_Status = UART4_RCV_BUFF_IDLE; return; break;
}
//UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
break;
case UART4_RCV_BUFF_MIDI1:
if((UART4_Process_Buff[0] & 0xF0) == FRAME_MIDI_PROCHANGE)
{
USART2_SendData(UART4_Process_Buff,UART4_RCV_cnt);
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
}
else
{
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
UART4_RCV_Status = UART4_RCV_BUFF_MIDI2;
}
break;
case UART4_RCV_BUFF_MIDI2:
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
USART2_SendData(UART4_Process_Buff,UART4_RCV_cnt);
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
break;
case UART4_RCV_BUFF_HEAD:
if (UART4_RCV_cnt < UART4_PROCESS_BUFF_SIZE)
{
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
}
if (rcv == 0x60)
{
UART4_RCV_Status = UART4_RCV_BUFF_CMD1;
}
else
{
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
}
break;
case UART4_RCV_BUFF_CMD1:
// <20><>ָ<EFBFBD><D6B8>
if (UART4_RCV_cnt < UART4_PROCESS_BUFF_SIZE)
{
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
}
UART4_RCV_Status = UART4_RCV_BUFF_CMD2;
break;
case UART4_RCV_BUFF_CMD2:
// <20><>ָ<EFBFBD><D6B8>
if (UART4_RCV_cnt < UART4_PROCESS_BUFF_SIZE)
{
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
}
UART4_RCV_Status = UART4_RCV_BUFF_DATA;
break;
case UART4_RCV_BUFF_DATA:
// <20><><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>ݣ<EFBFBD>ֱ<EFBFBD><D6B1>֡β 0xF7
if (UART4_RCV_cnt < UART4_PROCESS_BUFF_SIZE)
{
UART4_Process_Buff[UART4_RCV_cnt++] = rcv;
}
if (rcv == FRAME_SYS_TAIL)
{
// ִ<><D6B4>ָ<EFBFBD><EFBFBD><EEB4A6>
processBLESysEXData(UART4_Process_Buff, UART4_RCV_cnt);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD>λ״̬<D7B4><CCAC>
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
}
break;
default:
// δ֪״̬ǿ<CCAC>Ƹ<EFBFBD>λ
UART4_RCV_Status = UART4_RCV_BUFF_IDLE;
break;
}
}
static void handleStringTimbre(uint8_t *data)
{
switch(data[4])
{
case 0:
{
uint8_t ReturnTimbre[8] = {0xF0,0x60,0x03,0x05,0x00,0x00,0x00,0xF7};
ReturnTimbre[6] = mGuiData[GUI_TIMBRE_SELECT].Current;
USART4_SendData(ReturnTimbre,sizeof(ReturnTimbre));
}
break;
case 1:
{
NvmParam_Type * nvm = drv_nvm_param_ptr();
uint8_t new_val = data[6]; // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>ɫֵ
// <20><><EFBFBD>ֵû<D6B5>䣬ֱ<E4A3AC><D6B1><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>
if (new_val == mGuiData[GUI_TIMBRE_SELECT].Current)
{
return;
}
mGuiData[GUI_TIMBRE_SELECT].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3)
{
//Refresh_StringTimbre(last_value, &UI_Label[GUI_TIMBRE_SELECT], &mGuiData[GUI_TIMBRE_SELECT]);
}
if(nvm->param.Timbre != mGuiData[GUI_TIMBRE_SELECT].Current)
{
nvm->param.Timbre = mGuiData[GUI_TIMBRE_SELECT].Current;
drv_nvm_save_to_flash();
}
// uint8_t buff[10] = {0,};
// LCD_ShowString(200,30, Num_To_String(mGuiData[GUI_TIMBRE_SELECT].Current,buff,4), RED, WHITE, 16, 0);
}
break;
}
}
//extern int8_t delta;
extern STRING_MIDI USE_MIDI;
static void handleTranspose(uint8_t *data)
{
//uint8_t last_value;
switch(data[4])
{
case 0:
{
/* doc: F0 60 03 07 00 <val> F7 (7 bytes total) */
uint8_t ReturnTranspose[7] = {0xF0,0x60,0x03,0x07,0x00,0x00,0xF7};
ReturnTranspose[5] = (uint8_t)mGuiData[GUI_TRANSPOSE].Current;
USART4_SendData(ReturnTranspose,sizeof(ReturnTranspose));
}
break;
case 1:
{
NvmParam_Type * nvm = drv_nvm_param_ptr();
uint8_t new_val = data[5]; // <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>ɫֵ
// <20><><EFBFBD>ֵû<D6B5>䣬ֱ<E4A3AC><D6B1><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>
if (new_val == mGuiData[GUI_TRANSPOSE].Current)
{
return;
}
mGuiData[GUI_TRANSPOSE].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3)
{
Refresh_Transpose(&UI_Label[GUI_TRANSPOSE], &mGuiData[GUI_TRANSPOSE]);
}
if(nvm->param.Transpose != mGuiData[GUI_TRANSPOSE].Current)
{
nvm->param.Transpose = mGuiData[GUI_TRANSPOSE].Current;
drv_nvm_save_to_flash();
}
// delta = new_trans - last_value;
// USE_MIDI.Midi_1 += delta;
// USE_MIDI.Midi_2 += delta;
// USE_MIDI.Midi_3 += delta;
// USE_MIDI.Midi_4 += delta;
// USE_MIDI.Midi_5 += delta;
// USE_MIDI.Midi_6 += delta;
//AutoBandTop1_Note_On(USE_MIDI.Midi_6,0x50);
}
break;
}
}
// <20>յ<EFBFBD>˫<EFBFBD>ֽ<EFBFBD> hi, lo<6C><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>BPM
uint16_t Calc_BPM(uint8_t bpmHi, uint8_t bpmLo)
{
return (uint16_t)bpmHi * 128 + bpmLo;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>BPM<50><4D><EFBFBD><EFBFBD>ֳ<EFBFBD>hi<68><69>lo˫<6F>ֽ<EFBFBD>
void Split_BPM(uint16_t target_bpm, uint8_t *hi_out, uint8_t *lo_out)
{
*hi_out = target_bpm / 128;
*lo_out = target_bpm % 128;
}
static void handleBPM(uint8_t *data)
{
switch(data[4])
{
case 0:
{
uint8_t ReturnSpeed[8] = {0xF0,0x60,0x03,0x06,0x00,0x00,0x00,0xF7};
ReturnSpeed[5] = mGuiData[GUI_SPEED].Current / 128;
ReturnSpeed[6] = mGuiData[GUI_SPEED].Current % 128;
USART4_SendData(ReturnSpeed,sizeof(ReturnSpeed));
}
break;
case 1:
{
NvmParam_Type * nvm = drv_nvm_param_ptr();
uint16_t new_val = Calc_BPM(data[5],data[6]);
// <20><><EFBFBD>ֵû<D6B5>䣬ֱ<E4A3AC><D6B1><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD><CBA2>
if (new_val == mGuiData[GUI_SPEED].Current)
{
return;
}
mGuiData[GUI_SPEED].Current = new_val;
if(mGuiData[GUI_TAB_INDEX].Current != 3)
{
Refresh_Transpose(&UI_Label[GUI_SPEED], &mGuiData[GUI_SPEED]);
}
if(nvm->param.BPM != mGuiData[GUI_SPEED].Current)
{
nvm->param.BPM = mGuiData[GUI_SPEED].Current;
drv_nvm_save_to_flash();
}
AutoBandTop1_ChangeBPM(mGuiData[GUI_SPEED].Current);
}
break;
}
}
static void handleLED0(uint8_t *data)
{
// DefaultTask_SendMsg(MSG_ID_LIGHT_LED, LED_L1, data[5], 0);
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L1, data[5], 0);
}
static void handleLED1(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L2, data[5], 0);
}
static void handleLED2(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L3, data[5], 0);
}
static void handleLED3(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L4, data[5], 0);
}
static void handleLED4(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L5, data[5], 0);
}
static void handleLED5(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L6, data[5], 0);
}
static void handleLED6(uint8_t *data)
{
BL_Sendmsg(MSG_ID_LIGHT_LED, LED_L7, data[5], 0);
}
static void handlePitchOffset(uint8_t *data)
{
BL_Sendmsg(MSG_ID_PITCH_OFFSET, data[4]+1, data[5], 0);
}
static void handleChordOffset(uint8_t *data)
{
BL_Sendmsg(MSG_ID_CHORD_OFFSET, data[4]+1, data[5], 0);
}
extern CHORD_TYPE_INDEX chord_type_index_map[22];
static void handleReadRhythmMap(uint8_t *data)
{
uint8_t ReadChordMap[47] = {0xF0, 0x60, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7};
uint8_t chord_map = 0;
for(uint8_t i = 1;i < 22;i ++)
{
ReadChordMap[3+i] = chord_type_index_map[i].PitchOffset;
}
for(uint8_t i = 25;i < 46;i ++)
{
switch(chord_type_index_map[i-24].type)
{
case 0:
chord_map = 0;
break;
case 1:
chord_map = 8;
break;
case 2:
chord_map = 2;
break;
case 3:
chord_map = 13;
break;
case 4:
chord_map = 10;
break;
case 5:
chord_map = 31;
break;
case 6:
chord_map = 30;
break;
case 7:
chord_map = 4;
break;
case 8:
chord_map = 11;
break;
}
ReadChordMap[i] = chord_map;
}
USART4_SendData(ReadChordMap,sizeof(ReadChordMap));
}
static void handleIntro(uint8_t *data)
{
BL_Sendmsg(MSG_ID_ADCIN1KEY, 3, 0, 0);
}
static void handleInterlude(uint8_t *data)
{
BL_Sendmsg(MSG_ID_ADCIN1KEY, 0, 0, 0);
}
static void handleOutro(uint8_t *data)
{
BL_Sendmsg(MSG_ID_ADCIN1KEY, 1, 0, 0);
}
static void handleEnd(uint8_t *data)
{
//DefaultTask_SendMsg(MSG_ID_ADCIN1KEY, 2, 0, 0);
// osMutexAcquire(Tm1629Mutex,osWaitForever);
// TM1629D_AllLedOff();
// TM1629D_AllLedOn(LED_COLOR_G);
// TM1629D_UpdateDisplay(0);
// osMutexRelease(Tm1629Mutex);
BL_Sendmsg(MSG_ID_ADCIN1KEY, 2, 0, 0); /* End -> Postamble(1), distinct from Outro(key=1) */
}
static void handleSectionA(uint8_t *data)
{
BL_Sendmsg(MSG_ID_KEY_1617, 3, 0, 0);
}
static void handleSectionB(uint8_t *data)
{
BL_Sendmsg(MSG_ID_KEY_1617, 2, 0, 0);
}
static void handleSectionC(uint8_t *data)
{
BL_Sendmsg(MSG_ID_KEY_1617, 1, 0, 0);
}
static void handleSectionD(uint8_t *data)
{
BL_Sendmsg(MSG_ID_KEY_1617, 0, 0, 0);
}
static void BL_Sendmsg(uint16_t Data1, uint16_t Data2, uint16_t Data3, uint16_t Data4)
{
BLTask_Sendmsg(Data1, Data2, Data3, Data4);
}
/* ======================================================================
* Appended protocol handlers (per Doc/指令测试.docx)
* ==================================================================== */
/*-------- 1. device info 0x01 --------*/
#define AT32_UID_BASE 0x1FFFF7E8UL /* 96-bit unique device ID */
/* placeholders: 01 04/05/0C — bump manually at each release (Dream has no ver query) */
static const uint8_t SOUND_VER[4] = {0x4D, 0x06, 0x7F, 0x01};
static const uint8_t UI_VER[4] = {0x21, 0x05, 0x7F, 0x01};
static const uint8_t USER_FW_VER[4] = {0x4D, 0x06, 0x7F, 0x01};
static void handleDevDisconnect(uint8_t *data)
{
uint8_t resp[6] = {0xF0, 0x60, 0x01, 0x00, 0x01, 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
static void handleDevConnect(uint8_t *data)
{
uint8_t resp[6] = {0xF0, 0x60, 0x01, 0x01, 0x01, 0xF7};
(void)data;
ResetAutoPowerCount();
USART4_SendData(resp, sizeof(resp));
}
static void handleDevName(uint8_t *data)
{
char name[BLE_DEVICE_NAME_LEN + 1];
uint8_t resp[4 + BLE_DEVICE_NAME_LEN + 1]; /* head4 + name + F7 */
(void)data;
BleBuildDeviceName(name);
resp[0] = 0xF0; resp[1] = 0x60; resp[2] = 0x01; resp[3] = 0x02;
memcpy(&resp[4], name, BLE_DEVICE_NAME_LEN);
resp[4 + BLE_DEVICE_NAME_LEN] = 0xF7;
USART4_SendData(resp, (uint16_t)sizeof(resp));
}
static void handleFwMainVer(uint8_t *data)
{
uint8_t resp[9] = {0xF0, 0x60, 0x01, 0x03, Version[0], Version[1], Version[2], 0x01, 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
static void handleSoundVer(uint8_t *data)
{
uint8_t resp[9] = {0xF0, 0x60, 0x01, 0x04, SOUND_VER[0], SOUND_VER[1], SOUND_VER[2], SOUND_VER[3], 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
static void handleUIVer(uint8_t *data)
{
uint8_t resp[9] = {0xF0, 0x60, 0x01, 0x05, UI_VER[0], UI_VER[1], UI_VER[2], UI_VER[3], 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
static void handleOtherInfo(uint8_t *data)
{
/* 01 06: reserved — keep 8 zero bytes until product defines fields */
uint8_t resp[13] = {0xF0, 0x60, 0x01, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
static void handleDevCode(uint8_t *data)
{
/* 96-bit UID as 24 hex ASCII — SysEx data must stay 7-bit for BLE-MIDI */
static const char hex[] = "0123456789ABCDEF";
uint8_t resp[29];
const uint8_t *uid = (const uint8_t *)AT32_UID_BASE;
uint8_t i;
(void)data;
resp[0] = 0xF0;
resp[1] = 0x60;
resp[2] = 0x01;
resp[3] = 0x07;
for (i = 0; i < 12u; i++)
{
resp[4u + 2u * i] = (uint8_t)hex[uid[i] >> 4];
resp[4u + 2u * i + 1u] = (uint8_t)hex[uid[i] & 0x0Fu];
}
resp[28] = 0xF7;
USART4_SendData(resp, sizeof(resp));
}
static void handleAutoPowerOff(uint8_t *data)
{
uint8_t resp[6] = {0xF0, 0x60, 0x01, 0x0A, 0x00, 0xF7};
(void)data;
resp[4] = AutoCloseTime;
USART4_SendData(resp, sizeof(resp));
}
static void handleUserFwVer(uint8_t *data)
{
uint8_t resp[9] = {0xF0, 0x60, 0x01, 0x0C, USER_FW_VER[0], USER_FW_VER[1], USER_FW_VER[2], USER_FW_VER[3], 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
}
/* F0 60 01 11 <minutes> F7 : set auto power-off, 0 = disable */
static void handleAutoPowerOffSet(uint8_t *data)
{
NvmParam_Type *nvm = drv_nvm_param_ptr();
uint8_t resp[6] = {0xF0, 0x60, 0x01, 0x11, 0x00, 0xF7};
AutoCloseTime = data[4];
if (nvm->param.AutoCloseTime != AutoCloseTime)
{
nvm->param.AutoCloseTime = AutoCloseTime;
drv_nvm_save_to_flash();
}
ResetAutoPowerCount();
resp[4] = AutoCloseTime;
USART4_SendData(resp, sizeof(resp));
}
static void handleFwCode(uint8_t *data)
{
/* 固件编码: 请求 01 0F推荐或 01 FF仅裸串口应答统一 01 0F + ASCII避免 BLE-MIDI 吃掉 0xFF */
uint8_t resp[16];
uint8_t len = (uint8_t)strlen(fwname);
(void)data;
if (len > 10u)
len = 10u;
resp[0] = 0xF0;
resp[1] = 0x60;
resp[2] = 0x01;
resp[3] = 0x0F;
memcpy(&resp[4], fwname, len);
resp[4 + len] = 0xF7;
USART4_SendData(resp, (uint16_t)(4u + len + 1u));
}
/*-------- 2. chord map 0x02 --------*/
/* F0 60 02 04 <21B pitch> <21B chord> F7 : write whole map; reply in 02 01 format */
static void handleResetChordMap(uint8_t *data)
{
uint8_t key;
for (key = 1; key <= 21; key++)
{
BT_Pitch_offset_map(key, data[3 + key]); /* data[4..24] pitch offsets */
BT_Chord_offset_map(key, data[24 + key]); /* data[25..45] chord types */
}
handleReadRhythmMap(data);
}
/*-------- 3. rhythm style 0x03 0x04 --------*/
static void handleRhythmStyle(uint8_t *data)
{
switch (data[4])
{
case 0: /* read current style: F0 60 03 04 00 <src> <idHi> <idLo> F7 */
{
uint8_t resp[9] = {0xF0, 0x60, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0xF7};
uint8_t src = (uint8_t)(mGuiData[GUI_AUTOBAND_SW].Current ? 1 : 0);
uint16_t id = src ? ParamGuiData[EXPRESS_MODE_PARAM].Current
: ParamGuiData[SONG_MODE_PARAM].Current;
resp[5] = src;
resp[6] = (uint8_t)(id / 128);
resp[7] = (uint8_t)(id % 128);
USART4_SendData(resp, sizeof(resp));
}
break;
case 1: /* set style: F0 60 03 04 01 <src:0 sys/1 user> <idHi> <idLo> F7, reply BPM */
{
uint8_t src = (data[5] != 0) ? 1 : 0;
uint16_t id = (uint16_t)data[6] * 128 + data[7];
GUI_SWITCH *slot = src ? &ParamGuiData[EXPRESS_MODE_PARAM]
: &ParamGuiData[SONG_MODE_PARAM];
uint8_t resp[7] = {0xF0, 0x60, 0x03, 0x04, 0x01, 0x00, 0xF7};
if (src)
slot->Max = (LOCAL_SONG_COUNT > 0) ? (uint16_t)(LOCAL_SONG_COUNT - 1) : 0;
if (id > slot->Max)
id = slot->Max;
mGuiData[GUI_AUTOBAND_SW].Current = src;
slot->Current = id;
StartFlag = 0;
AutoBandTop1_Stop();
UI_ReloadTonePreset();
/* doc: single-byte bpm; clamp >127 (App should read exact bpm via 03 06) */
resp[5] = (mGuiData[GUI_SPEED].Current > 0x7F)
? 0x7F : (uint8_t)mGuiData[GUI_SPEED].Current;
USART4_SendData(resp, sizeof(resp));
/* boot / song-entry special: F0 60 03 04 01 00 00 00 F7
doc: also push current BPM as active report F0 51 03 <hi> <lo> F7 */
if (data[5] == 0 && data[6] == 0 && data[7] == 0)
{
uint8_t bpmr[6] = {0xF0, 0x51, 0x03, 0x00, 0x00, 0xF7};
bpmr[3] = (uint8_t)(mGuiData[GUI_SPEED].Current / 128);
bpmr[4] = (uint8_t)(mGuiData[GUI_SPEED].Current % 128);
USART4_SendData(bpmr, sizeof(bpmr));
}
}
break;
case 2: /* user style list page: F0 60 03 04 02 <from3B> <to3B> F7
reply: F0 60 03 04 02 <cntHi> <cntLo> [<idHi> <idLo> <code 4B ascii> ...] F7 */
{
uint8_t resp[64];
uint32_t from = 0, to = LOCAL_SONG_COUNT;
uint16_t i, n = 0, len;
/* from/to: 24-bit big-endian, optional (doc example: 00 00 00 07) */
if (data[5] || data[6] || data[7])
{
from = ((uint32_t)data[5] << 16) | ((uint32_t)data[6] << 8) | data[7];
to = ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10];
}
if (from > LOCAL_SONG_COUNT) from = LOCAL_SONG_COUNT;
if (to > LOCAL_SONG_COUNT || to <= from) to = LOCAL_SONG_COUNT;
resp[0] = 0xF0; resp[1] = 0x60; resp[2] = 0x03; resp[3] = 0x04; resp[4] = 0x02;
len = 7; /* count filled after loop */
for (i = (uint16_t)from; i < to; i++)
{
if (len + 6 + 1 > sizeof(resp)) break;
resp[len++] = (uint8_t)(i / 128);
resp[len++] = (uint8_t)(i % 128);
memcpy(&resp[len], LocalSongCode[i], 4);
len += 4;
n++;
}
resp[5] = (uint8_t)(n / 128);
resp[6] = (uint8_t)(n % 128);
resp[len++] = 0xF7;
USART4_SendData(resp, len);
}
break;
case 3: /* user style total: reply F0 60 03 04 00 <total 3B BE> F7 (doc: 00 00 1E) */
{
uint8_t resp[9] = {0xF0, 0x60, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0xF7};
resp[5] = (uint8_t)((LOCAL_SONG_COUNT >> 16) & 0xFF);
resp[6] = (uint8_t)((LOCAL_SONG_COUNT >> 8) & 0xFF);
resp[7] = (uint8_t)(LOCAL_SONG_COUNT & 0xFF);
USART4_SendData(resp, sizeof(resp));
}
break;
default:
break;
}
}
/*-------- 5. reset / power off 0x05 --------*/
/* F0 60 05 00 F7 : ack then soft power off (executed in main-loop context) */
static void handleDeviceReset(uint8_t *data)
{
uint8_t resp[6] = {0xF0, 0x60, 0x05, 0x00, 0x01, 0xF7};
(void)data;
USART4_SendData(resp, sizeof(resp));
System_RequestPowerOff();
}