導(dǎo)語(yǔ):此主題為ULM300系列項(xiàng)目開(kāi)發(fā)中遇到的一些問(wèn)題以及它們的解決方式。
一,IA2E芯片無(wú)法直接輸出RSSI信號(hào)強(qiáng)度信息
- IA2E芯片是一款2.4G頻段的無(wú)線音頻芯片,屬于10年前的產(chǎn)品,芯片原廠的技術(shù)支持較弱,芯片文檔簡(jiǎn)單;
- 該芯片推薦電路方案中,開(kāi)發(fā)的源代碼是匯編由供應(yīng)商提供,外圍電路指示信號(hào)強(qiáng)度的4個(gè)燈,若要用該芯片直接接燈并修改底層程序來(lái)實(shí)現(xiàn)指示信號(hào)強(qiáng)度的功能則困難較大;
- 公司前期產(chǎn)品USB300里通過(guò)加第三方MCU接收IA2E的音頻數(shù)據(jù)流實(shí)現(xiàn)了USB可插拔播放音樂(lè)的功能和一些其它的IA2E無(wú)法實(shí)現(xiàn)的功能,由此若IA2E芯片能夠在工作時(shí)把其RSSI數(shù)據(jù)傳輸給第三方MCU、由MCU控制指示燈來(lái)顯示產(chǎn)品工作時(shí)的信號(hào)強(qiáng)度則可達(dá)到所開(kāi)發(fā)產(chǎn)品的功能設(shè)計(jì)目的。
解決思路
在上一代產(chǎn)品USB300中發(fā)現(xiàn),若發(fā)送端(TX)改變了音量大小,則TX會(huì)發(fā)送一個(gè)代表音量大小的值(比如0xd7)到接收端(RX),這個(gè)值只會(huì)在音量大小有改變的時(shí)候發(fā)送一次。
-
人為模擬RSSI信號(hào)發(fā)送過(guò)程
人為假定一個(gè)信號(hào)發(fā)送周期T(實(shí)際測(cè)試周期T=1080ms)、TX端在這個(gè)周期T內(nèi)重復(fù)發(fā)送音量大小值(比如0xd7)、據(jù)統(tǒng)計(jì)大概發(fā)送了Ntx=168個(gè)、每個(gè)間隔6.4ms左右,然后在RX端統(tǒng)計(jì)接收到的該音量值的個(gè)數(shù)(比如Nrx=80個(gè)),那么誤碼率BER=Ntx/Nrx=50%,根據(jù)不同的BER值來(lái)顯示滿格、兩格或者一格信號(hào)強(qiáng)度,具體代碼如下。
#define BER_FULL_VALUE 168//在一個(gè)周期里總共可以接收168個(gè)數(shù)據(jù)
#define BER_COUNT_CYCLE 108 /*set the PER count cycle 1080ms*/
void RSSI_Process(uint8_t PER_CODE){
if((PER_CODE==0xee)||(PER_CODE==0xf1)||(PER_CODE==0xf4)||(PER_CODE==0x0f7)\
||(PER_CODE==0xfa)||(PER_CODE==0xfd)||(PER_CODE==0x00)){
ANT_RSSI.ber_count++;
if(ANT_RSSI.ber_count_time>=BER_COUNT_CYCLE){/*set the BER count cycle 1080ms*/
ANT_RSSI.ber_count_time=0;
ANT_RSSI.BER=((ANT_RSSI.ber_count*100)/BER_FULL_VALUE);
if(ANT_RSSI.BER>=80){
Led.RSSI=RSSI_Good;
}
if((ANT_RSSI.BER>=70)&&(ANT_RSSI.BER<80)){
Led.RSSI=RSSI_soso;
}
if((ANT_RSSI.BER>=60)&&(ANT_RSSI.BER<70)){
Led.RSSI=RSSI_low;
}
if(ANT_RSSI.BER<60){
Led.RSSI=RSSI_bad;
ANT_RSSI.count++;
if(ANT_RSSI.count==4){//連續(xù)5S信號(hào)差就切換天線
ANT_RSSI.count=0;
ANT_Switch(); /*switch the ant*/
}
}
ANT_RSSI.ber_count=0;
}
}
}
-
數(shù)據(jù)包傳輸給MCU
IA2E接收到音量值數(shù)據(jù)包package后通過(guò)I2C傳輸給MCU,MCU獲得package后處理數(shù)據(jù)來(lái)控制四個(gè)LED燈指示信號(hào)強(qiáng)度。共5種信號(hào)強(qiáng)度等級(jí):good(亮4個(gè)綠燈)、soso(亮3個(gè)綠燈)、low(亮2個(gè)綠燈)、bad(亮1個(gè)綠燈)、none(亮1個(gè)紅燈)相關(guān)效果如下圖。
信號(hào)good
信號(hào)soso
無(wú)信號(hào)
二、更改后的軟件無(wú)MUTE功能
發(fā)送端TX長(zhǎng)按Down鍵達(dá)3秒以上,接收端RX(只有RX端有第三方MCU)收到后不播放聲音來(lái)實(shí)現(xiàn)MUTE功能。
解決過(guò)程
此為純軟件BUG,經(jīng)過(guò)調(diào)試軟件發(fā)現(xiàn)產(chǎn)生此問(wèn)題的兩個(gè)原因。
1、IA2E芯片的運(yùn)行程序存儲(chǔ)背景
IA2E芯片的代碼是BIN文件(BACHRX_inno_per_vol.bin),由供應(yīng)商提供;此BIN文件數(shù)據(jù)作為一個(gè)數(shù)組
const uint8_t IA2E_ROM[/*6144*/]合成在MCU程序中。編譯MCU軟件后,數(shù)組
const uint8_t IA2E_ROM[/*6144*/]成為MCU軟件的一部分放置于FLASH中,具體在哪個(gè)位置由編譯器決定,但可以肯定的是數(shù)組const uint8_t IA2E_ROM[/*6144*/]名代表IA2E軟件存儲(chǔ)的首地址。RX端MCU發(fā)送bin文件給IA2E具體代碼如下。
uint8_t EEPROM_TxByte() {
uint8_t tx;
if( byte_addr >= sizeof( IA2E_ROM ) ) {
IA2E_Boot_Complete = SET;
}
if( byte_addr == IA2E_LATENCY_ADDR ) {
byte_addr++;
tx = IA2E_LATENCY_VAL;
} else if( ( byte_addr >= IA2E_ID_ADDR ) &&
( byte_addr < ( IA2E_ID_ADDR + IA2E_ID_SIZE ) ) ) {//三個(gè)字節(jié)存放MCU的ID號(hào)
tx = UID >> ( ( byte_addr++ - IA2E_ID_ADDR ) << 3 );//寫固定的MCU的ID號(hào),只寫6位
} else {
tx = *( IA2E_ROM + byte_addr++ );
}
return tx;
}
2、無(wú)MUTE功能產(chǎn)生的原因
- 修改后的代碼如下
void EEPROM_RxByte( uint8_t rx ) {
switch( byte_cnt++ ) {
case 0:
( ( uint8_t *)&byte_addr )[1] = rx; // store MSB
break;
case 1:
( ( uint8_t *)&byte_addr )[0] = rx; // store LSB
break;
default:
// IA2E_ROM[ ( byte_addr++ - 2 ) & 0x1FFF ] = rx;
switch( byte_addr++ ) {
// case SYNIC_EEPROM_PER_ADDR:
// RSSI_Process( rx );
// break;
case SYNIC_EEPROM_STATUS_ADDR:
// SYNIC_STATUS=rx;
SYNIC_SetStatus( rx );
break;
case SYNIC_EEPROM_VOLUME_ADDR:
if(rx==0x06)//衣領(lǐng)夾麥克峰固定發(fā)射06值過(guò)來(lái)表示最大值
rx=0x00;//00表示音量最大值
if(SYNIC_Volume_Mute==0)
{
SYNIC_SetVolume( rx );
}
RSSI_Process( rx );
break;
}
break;
}
}
-
函數(shù)
Stream_SetLevel( volume )實(shí)現(xiàn)音量大小的改變,程序case SYNIC_EEPROM_STATUS_ADDR:和程序case SYNIC_EEPROM_VOLUME_ADDR:都會(huì)調(diào)用Stream_SetLevel( volume )函數(shù); - RX端中IA2E芯片音量狀態(tài)值放置在地址
#define SYNIC_EEPROM_STATUS_ADDR 0x17DD上,音量值放置在地址#define SYNIC_EEPROM_VOLUME_ADDR 0x17F0上,MUTE屬于音量狀態(tài)數(shù)據(jù); - 無(wú)論status值還是volume值,只有有按鍵變化TX端才會(huì)發(fā)送值到RX端且一次只可能發(fā)送其中的一種,如此在按了MUTE鍵后,RX端只會(huì)執(zhí)行
case SYNIC_EEPROM_STATUS_ADDR:中的程序?qū)崿F(xiàn)MUTE功能; - 若后續(xù)TX端無(wú)按鍵變化,則RX端的IA2E芯片不會(huì)通過(guò)I2C發(fā)送音量值到RX中的MCU中,這樣MCU也就不會(huì)執(zhí)行
switch( byte_addr++ )里面的程序,如此RX端音量狀態(tài)和音量大小將保持前一狀態(tài); - 由于要模擬RSSI功能,產(chǎn)生了以下現(xiàn)象:
- TX端會(huì)不斷的發(fā)送volume值(假設(shè)volume=0xD7)到RX,意味著無(wú)論TX端有無(wú)按鍵變化都會(huì)隔一小段時(shí)間(6.4ms)發(fā)送volume值給RX,RX端會(huì)周期性的執(zhí)行
case SYNIC_EEPROM_VOLUME_ADDR:程序?qū)崿F(xiàn)聲音;- 假設(shè)某一時(shí)刻t=6.4ms內(nèi),有一個(gè)MUTE值過(guò)來(lái)(假設(shè)此時(shí)volume=0xD7,聲音正常大?。@時(shí)RX端執(zhí)行
case SYNIC_EEPROM_STATUS_ADDR:程序?qū)崿F(xiàn)了MUTE功能,在過(guò)t=6.4ms后,TX又發(fā)送volume=0xD7數(shù)據(jù)到RX,之后RX端執(zhí)行程序case SYNIC_EEPROM_VOLUME_ADDR:實(shí)現(xiàn)聲音正常大小,這樣MUTE的效果就聽(tīng)不出來(lái)了。
3、解決的方法
在
case SYNIC_EEPROM_VOLUME_ADDR:程序內(nèi)執(zhí)行函數(shù)SYNIC_SetVolume( rx )前添加條件if(SYNIC_Volume_Mute==0),表示只有在無(wú)MUTE情況下,才會(huì)執(zhí)行SYNIC_SetVolume( rx )函數(shù),這樣在MUTE狀態(tài)不解除的情況下即使有volume值發(fā)送到RX端也不會(huì)影響MUTE功能。