A9101_對講機加入對碼_Pair system_功能
本篇介紹A9101 A50 470Mhz Walkie Talkie 加上配對功能
代碼:
A9101_A50_Walkie Talkie & Pair system(DR=512Kbps_SR8K8bit_16CHs) CL=18pF_V0.2_0613.zip
當按下 Talk 鍵時(P3.2 =0),系統將從被動端轉變為 Master (TX),主動發射喚醒訊號通知 Slave,來達到連線狀況。
此應用系統架構於A9101 SubGHz Voice SoC,以下為Demo Code中的操作規格:
RF data Rate = 512Kbps
Codec Sample Rate = 8KHz , A-law壓縮技術
Codec AGC ON
Talk Key (P3.2) Low/Master ,High/Slave
Fix Channel Function (P3.3) Low, Channel =85 (439.761 MHz)
連線使用到 16 個 channel, 4 個 1 組,12ms 後依序切換不同 Channel set, Hopping Table 如下:
A50-1 | Channel | 頻率(MHz) | A50-2 | Channel | 頻率(MHz) |
1 | 5 | 468.241 | 1 | 10 | 469.521 |
2 | 35 | 475.921 | 2 | 20 | 472.801 |
3 | 25 | 473.361 | 3 | 30 | 474.641 |
4 | 15 | 470.801 | 4 | 40 | 477.201 |
A50-3 | Channel | 頻率(MHz) | A50-4 | Channel | 頻率(MHz) |
1 | 45 | 478.481 | 1 | 50 | 479.761 |
2 | 75 | 486.161 | 2 | 60 | 482.321 |
3 | 65 | 483.601 | 3 | 70 | 484.881 |
4 | 50 | 481.041 | 4 | 80 | 487.441 |
連線頻率查詢,RSSI 查詢,電池電量查詢
靜音(P1.6) Low,增加音量(P1.1) Low,減少音量(P1.0) Low
每個傳輸封包 100Byte,96Byte 是語音資料,剩餘 4Byte 資料內容使用者可自行定義
可選用配對模式(P0.3) Low,需近距離下進行配對,大於設定的 RSSI_threshold 即配對成功,配對模式下 Master/Slave 可選用不同配對 ID(P0.0)Low or ID(P0.1)Low 進行配對,一組廣播 ID,兩組配對 ID,ID 使用者可自行修改,配對成功後也可改用廣播 ID 對兩個 Slave 端進行連線
==================================================================
配對功能介紹
1. 目前有 3 個裝置分別是 Master,Slave1,Slave2,每進入配對模式一次,"Master/Slave P0.3 都要
先拉 HIGH 再拉 LOW"
2. 針對 Master/Slave1 進行配對,兩裝置選擇 ID1(P0.0)Low,若配對成功 P0.2 會有反覆 High/Low 訊號
3. 針對 Master/Slave2 進行配對,兩裝置選擇 ID2(P0.1)Low,若配對成功 P0.2 會有反覆 High/Low 訊號
4. 若因接收狀況不佳配對失敗, 重複上述動作即可,之後 Slave1(P0.0),Slave2(P0.1) 固定 IO 拉 LOW,以
區分兩種裝置
5.配對成功後,將所有裝置 P0.3 拉 HIGH, 回到語音傳輸模式
若要對 Slave1 進行link,Master P0.0 拉 LOW,Slave2 不會接收到封包
若要對 Slave2 進行link,Master P0.1 拉 LOW,Slave1 不會接收到封包
若 Master P0.0 & P0.1 拉 HIGH,Slave 端不用改 IO 設定,回到廣播 ID 廣播模式,Slave1 & Slave 2 都會出現聲音
Note1: 若還沒配對前,都是用廣播 ID 進行 link
Note2: 按 Reset 取消配對
===================================================================
P.S.配對前需先設置GIO1,GIO2,CKO的配置模式,否則會造成第一次配對成功後,若要再次進入重新配對時會出現無法配對的狀況發生
"
A9101_WriteReg ( GIO1_REG, 0x1C ); //PDN_RX
A9101_WriteReg ( GIO2_REG, 0x00 ); //WTR
A9101_WriteReg ( CKO_REG, 0x00 ); //RCK
"
配對函數:
A9101_Pair();
介紹:
判斷P0_3是否拉LOW,先寫入預設廣播ID"Broadcast_ID_Tab"
while(Pair_IO==0)// Define P0_3 { WriteID(Broadcast_ID_Tab);
2.開啟檢測RSSI
if(Pair1_IO == 0 || Pair2_IO == 0)//Define P0_0 & P0_1 { Slave_rssi = 0; link_OK = 0; A9101_WriteReg (ADC_REG, 0xF2); //RRS=1, FSARS=0,RADC=1,HDM=1 ,RSM=3 A9101_WriteReg (MODEC2_REG, A9101_CONFIGTABLE[MODEC2_REG - CONFIG] | 0x40 ); //ARRSI=1 EA = 1; //enable interrupt ERFINT = 1;
3.設定FIFO 長度1Byte,並發射通知Slave端選擇0x01 (ID1) 或 0x02 (ID2)
A9101_WriteReg (FIFO1_REG, 0x01); //FIFO Length = 1 ResetCmd(TXPOINT_RST); if(Pair1_IO == 0) A9101_WriteReg(TX_FIFO, 0x01); else if(Pair2_IO == 0) A9101_WriteReg(TX_FIFO, 0x02);
4.Master端,將ID Select Number發射出去告知slave端
if(P3_2 == 0) //Master { for (i=0;i<1;i++) { Delay1ms(5); A9101_WriteReg(INTSW_REG, 0x02);//WTR SetCH (75); RF_FLAG = 1; StrobeCmd (CMD_TX); while (RF_FLAG); StrobeCmd (CMD_STBY); //Tx finish Entry PLL MODE Delay1ms(1);
5.TX 完後進入RX mode,等待slave端發射RSSI返回值
ResetCmd(RXPOINT_RST); TIMEOUT = 1 ; t0hrel = 11200; InitTimer0(); StrobeCmd(CMD_RX); //Entry RX MODE RF_FLAG = 1; //Set RF Interrupt Flag TR0 = 1; //Enable Timer0 for counting RX Time out TimeoutFlag = 0; //Reset RX Timeout Flag timer = 0; //Reset Timer0 counter while (RF_FLAG && (TimeoutFlag == 0)); //Wait for RX Receive done or RX Time out if (TimeoutFlag) { StrobeCmd(CMD_STBY); //Entry StandBy MODE } /* RX Receive done Process */ else { pair_cmd = A9101_ReadReg(RX_FIFO); Slave_rssi = A9101_ReadReg(RX_FIFO+1); link_OK++;
===================================================================
Slave端 P3_2=1
1. 進入RX Mode,等待TX端發射過來的ID Select Number "pair_cmd"=0x01 or 0x02
for (i=0;i<1;i++) { A9101_WriteReg(INTSW_REG, 0x80); //Fsync SetCH (75); RF_FLAG = 1; //Set RF Interrupt Flag StrobeCmd(CMD_RX); //Entry RX MODE while (RF_FLAG && (Pair_IO == 0)); //Wait for RX Receive if((RF_FLAG == 0) && (Pair_IO == 0)) { Slave_rssi = A9101_ReadReg(RSSI_REG); RF_FLAG = 1; A9101_WriteReg(INTSW_REG, 0x02); //WTR while (RF_FLAG && (Pair_IO == 0)); //Wait for RX Receive done link_OK++; pair_cmd = A9101_ReadReg(RX_FIFO);
2.回傳Slave端的RSSI值給Master端
A9101_WriteReg(TX_FIFO+1, Slave_rssi); Delay1ms(5); SetCH (75); A9101_WriteReg(INTSW_REG, 0x02); //WTR RF_FLAG = 1; StrobeCmd(CMD_TX); while (RF_FLAG);
3.若Slave端一直沒收到ID Select Number,則將link_OK =0,表示配對不成功
else { link_OK = 0; }
4. 如果link_OK >0 & RSSI值>RSSI門檻值,表示訊號正常,並判斷是要使用ID1 或 ID2進行通訊,並觸發P0_2反覆HIGH/LOW提示功能,直到P0_3拉HIGH後退出配對模式,回到語音傳輸模式
if(link_OK && Slave_rssi > RSSI_threshold) { if(Pair1_IO == 0 && pair_cmd == 0x01) Pair1_OK = 1; else if(Pair2_IO == 0 && pair_cmd == 0x02) Pair2_OK = 1; else break; while(Pair_IO == 0) //pair ok, user can print message... P0_2 ^=1;
===================================================================
配對完成後進入語音通話模式
while(DeviceLink(ScanMode(Pin_ModeSelect)));
Master介紹:
1. 開啟WTR中斷+CRC Data Filtering+FIFO長度定義成(0x63+1)=100Byte==>96 CodeC+4 Byte user CMD
/* Set RF */ EA = 1; //enable interrupt A9101_WriteReg ( INTSW_REG, 0x02 ); //enable WTR interrupt A9101_WriteReg ( RX_REG, A9101_CONFIGTABLE[RX_REG - CONFIG] | 0x80 ); //enable MSCRC A9101_WriteReg ( FIFO1_REG, 0x63 ); //FIFO Length = 96 bytes + 4byte cmd
2.開啟RSSI 檢測功能
/* Set RSSI */ A9101_WriteReg ( ADC_REG, 0xF2 ); //RRS=1, FSARS=0,RADC=1,HDM=1 ,RSM=3 A9101_WriteReg ( MODEC2_REG, A9101_CONFIGTABLE[MODEC2_REG - CONFIG] | 0x40 ); //ARRSI=1
3.初始化CodeC
InitCodec ( MASTER ); A9101_WriteReg ( CODEC_CODECTL, 0xB0 ); //ADC ON
4.判斷之前在A9101_Pair() 選中的ID Number ID1 或 ID2或廣播ID
if(Pair1_OK && (Pair1_IO == 0)) WriteID(Pair1_ID_Tab); else if(Pair2_OK && (Pair2_IO == 0)) WriteID(Pair2_ID_Tab); else WriteID(Broadcast_ID_Tab);
5.將ADC CodeC資料 & 自定義的0x01,0x02,0x03,0x04的字節加載到TX_FIFO Buffer裡
/* Write Packet to FIFO Buffer */ ResetCmd (TXPOINT_RST); //Reset RX FIFO Point X2X_DDP_MAMCPY(AU+TSL,CODECBUF[~TxIndex],TX_FIFO,96); //voice data A9101_WriteReg(TX_FIFO+96, 0x01); //control data A9101_WriteReg(TX_FIFO+97, 0x02); A9101_WriteReg(TX_FIFO+98, 0x03); A9101_WriteReg(TX_FIFO+99, 0x04);
6.連續在4個頻點上各打1包Tx Data
for ( TXTimes = 0; TXTimes < 4; TXTimes++ ) { Delay100us(1); /* Send TX */ ERFINT = 1; //Enable RF Interrupt SetCH (HoppingCH[TXTimes][channel_set]); //Set RF Channel StrobeCmd ( CMD_TX ); //Entry TX MODE RF_FLAG = 1; //Set RF Interrupt Flag while ( RF_FLAG ); //Waiting RF Interrupt Trigger Read_RXIndex ( TXBufIndex ); //For Audio 對齊 0x1C=28,28/2 =14,14*125us=1.75ms,實測約1.769ms StrobeCmd ( CMD_PLL ); //Entry PLL MODE }
7. 更換下一組hopping table
channel_set++; if(channel_set == 4) channel_set = 0;
8.檢測當PTT Key 放開後退出語音模式
if ( ScanMode ( Pin_ModeSelect ) != MASTER || ScanMode ( Pin_ModeSelect ) == NonValid ) return 0;
9.如果按下Pair key時退出語音模式重新進入配對
if(Pair_IO == 0) { A9101_WriteReg(CODEC_CODECTL, 0x00); //ADC OFF return 0; }
===================================================================
Slave端介紹:
1.開啟RSSI
2. 設定開啟WTR中斷+CRC Data Filtering+FIFO長度定義成(0x63+1)=100Byte==>96 CodeC+4 Byte user CMD
3.初始化CodeC & DAC ON & 靜音(Mute)
4.設定DAC 音量0x3C
/* Set RSSI */ A9101_WriteReg ( ADC_REG, 0xF2 ); //RRS=1, FSARS=0,RADC=1,HDM=1 ,RSM=3 A9101_WriteReg ( MODEC2_REG, A9101_CONFIGTABLE[MODEC2_REG - CONFIG] | 0x40 ); //ARRSI=1 /* Set RF */ EA = 1; //enable interrupt A9101_WriteReg ( INTSW_REG, 0x02 ); //enable WTR interrupt A9101_WriteReg ( RX_REG, A9101_CONFIGTABLE[RX_REG - CONFIG] | 0x80 ); //enable MSCRC A9101_WriteReg ( FIFO1_REG, 0x63 ); //FIFO Length = 96 bytes + 4byte cmd /* Set CODEC */ Empty = 1; //Set Empty Flag RxIndex = 0; TXBufIndex = 0; RXBufIndex = 0; InitCodec ( SLAVE ); A9101_WriteReg ( CODEC_CODECTL, 0x03 ); //DAC ON A9101_WriteReg ( CODEC_EFFCTL, 0x01 ); //Set Mute A9101_WriteReg(CODEC_VOL, VOLTest);
5.判斷選中的ID Number ID1 或 ID2 或廣播ID
6.若按下PTT KEY退出Slave,切到Master
7.如果按下Pair key時退出語音模式重新進入配對
if(Pair1_OK && (Pair1_IO == 0)) { if(broacast_flag) WriteID(Pair1_ID_Tab); else WriteID(Broadcast_ID_Tab); } else if(Pair2_OK && (Pair2_IO == 0)) { if(broacast_flag) WriteID(Pair2_ID_Tab); else WriteID(Broadcast_ID_Tab); } else WriteID(Broadcast_ID_Tab); broacast_flag ^=1;//broacast_flag=1 if ( ScanMode ( Pin_ModeSelect ) != SLAVE || ScanMode ( Pin_ModeSelect ) == NonValid ) return 0; if(Pair_IO == 0) return 0;
8.分別在4個頻點上做接收,若接收超時重新進Standby
for ( TXTimes = 0; TXTimes < sizeof 4; TXTimes++ ) { if ( GetPacket ) break; TIMEOUT = 1 ; t0hrel = 22400; //2.03ms @16.384MHz InitTimer0(); SetCH ( HoppingCH[TXTimes][channel_set]); //Set RF Channel ResetCmd ( RXPOINT_RST ); //Reset RX FIFO Point ERFINT = 1; //Enable RF Interrupt StrobeCmd ( CMD_RX ); //Entry RX MODE RF_FLAG = 1; //Set RF Interrupt Flag TR0 = 1; //Enable Timer0 for counting RX Time out TimeoutFlag = 0; //Reset RX Timeout Flag timer = 0; //Reset Timer0 counter while ( RF_FLAG && ( TimeoutFlag == 0 ) ); //Wait for RX Receive done or RX Time out if ( TimeoutFlag ) { ERFINT = 0; //Disable RF Interrupt StrobeCmd ( CMD_STBY ); //Entry StandBy MODE }
9.對其每個接收頻點的時間差=RXBufIndex
/* RX Receive done Process */ else { Read_RXIndex ( RXBufIndex ); //for 對齊 GetPacket = 1; switch ( TXTimes ) { case 0: RXBufIndex = 0x15 ; break; case 1: RXBufIndex = 0x2B; break; case 2: RXBufIndex = 0x40 ; break; case 3: RXBufIndex = 0x57 ; break; } } }
10.若4個頻點都沒收到包,TXTimes == 3 就觸發一下P0_2 Low/High一回
if ( TimeoutFlag ) { ERFINT = 0; //Disable RF Interrupt StrobeCmd ( CMD_STBY ); //Entry StandBy MODE LossCnt ++; if(TXTimes == 3) { P0_2 = 0; P0_2 = 1; P0_2 = 0; } }
11. 掉包太多,跳出語音模式重新連接
if ( LossCnt > 10 ) return 0;
12.切換下一組hopping table & 解析CodeC資料與自定義資料寫入cmd[0],cmd[1],cmd[2],cmd[3]
channel_set++; if(channel_set == 4) channel_set = 0; while ( Empty ); //Wait for DAC Buffer Empty X2X_DDP_MAMCPY(AU+TSL,RX_FIFO,CODECBUF[~RxIndex],96); cmd[0]=A9101_ReadReg(RX_FIFO+96); cmd[1]=A9101_ReadReg(RX_FIFO+97); cmd[2]=A9101_ReadReg(RX_FIFO+98); cmd[3]=A9101_ReadReg(RX_FIFO+99);
13.當P1_6 拉LOW"進入靜音模式"
14.當P1_1拉LOW "+音量" / P1_0拉LOW "-音量"
if ( LossCnt == 0 ) { if(P1_6==0) { A9101_WriteReg ( CODEC_EFFCTL, 0x01 );//Mute } else { A9101_WriteReg ( CODEC_EFFCTL, 0x00 );//Disable Mute if(P1_1==0) { if(VOLTest>=0x3C) VOLTest=0x3C; else VOLTest=VOLTest+1; A9101_WriteReg(CODEC_VOL, VOLTest); } else if(P1_0==0) { if(VOLTest<=0x00) VOLTest=0; else VOLTest=VOLTest-1; A9101_WriteReg(CODEC_VOL, VOLTest); } A9101_WriteReg ( CODEC_EFFCTL, 0x00 );//Disable Mute } }
15.若有掉包則將DAC設成Mute,若按下PTT KEY退出Slave,切到Master,或是按下Pair Key時也可以跳出重新進入A9101_Pair();函數
else { A9101_WriteReg ( CODEC_EFFCTL, 0x01 );//Mute } Empty = 1; //Set Empty Flag to avoid DAC Buffer doesn't finish the play if ( ScanMode ( Pin_ModeSelect ) != SLAVE || ScanMode ( Pin_ModeSelect ) == NonValid||Pair_IO == 0) return 0;
===================================================================