A9101_對講機加入對碼_Pair system_功能

SamYang2024-04-24A9101/A8101166

本篇介紹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,來達到連線狀況。

image.png


此應用系統架構於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 channel4 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();

介紹:

  1. 判斷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;

===================================================================

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。