K1Guitar/protocol/bl_uart_parse.c

814 lines
26 KiB
C
Raw Normal View History

#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<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ö<EFBFBD><EFBFBD>
*/
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 ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>UART3<EFBFBD><EFBFBD><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);
/*************************************************
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><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, 0xFF}, handleFwCode}, /* fw code */
/*======== 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 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>SysExָ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param data: <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param cnt: ֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void processBLESysEXData(uint8_t* data, uint8_t cnt)
{
//ResetAutoPowerCount();
// <20><><EFBFBD><EFBFBD>֡У<D6A1><D0A3>
if (data[0] != FRAME_SYS_HEAD || data[cnt - 1] != FRAME_SYS_TAIL || cnt > UART4_PROCESS_BUFF_SIZE || data[1] != 0x60)
{
return;
}
// <20><>ȡ <20><>ָ<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;
}
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
{
// <20>Ƿ<EFBFBD><C7B7>ֽڣ<D6BD><DAA3><EFBFBD>λ
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)
{
uint8_t resp[17] = {0xF0, 0x60, 0x01, 0x07};
(void)data;
memcpy(&resp[4], (const void *)AT32_UID_BASE, 12);
resp[16] = 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 FF 固件编码: product string TBD; interim reply uses NVM fwname ("BRS08L") */
uint8_t resp[16];
uint8_t len = (uint8_t)strlen(fwname);
(void)data;
resp[0] = 0xF0; resp[1] = 0x60; resp[2] = 0x01; resp[3] = 0xFF;
memcpy(&resp[4], fwname, len);
resp[4 + len] = 0xF7;
USART4_SendData(resp, (uint16_t)(4 + len + 1));
}
/*-------- 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();
}