📄 protocol.c
字号:
{
unsigned char rssi;
// Dummy read
(void)RadioGetRssi();
rssi = RadioGetRssi();
// If RSSI was triggered from SOP read RSSI again to get a non-transmission reading
if (rssi & SOP_RSSI)
{
rssi = RadioGetRssi();
}
return rssi & RSSI_LVL_MSK;
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: MasterProtocolDeviceTypeToBit
//
//! Description: Convert the device type to bit
//!
//!
//! Inputs: Device type
//!
//! Returns: Bit mask
//!
///////////////////////////////////////////////////////////////////////////////
static unsigned char MasterProtocolDeviceTypeToBit(unsigned char dev_type)
{
return (1 << dev_type);
}
#else //MASTER_PROTOCOL
//*****************************************************************************
//*****************************************************************************
//
// ******************* For Slave Protocol ************************************
//
//*****************************************************************************
//*****************************************************************************
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolInit
//
//! Description: Inspects stored configuration and figures device parameters using
//! algorithms to find PN code, channel, pin, and CRC seed
//! (based off the MID). Calls radio init,.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
void SlaveProtocolInit(void)
{
// Configure the Radio
RadioInit(ACK_EN|END_STATE_SLEEP|ACK_TO_8X, DATA_MODE_PA|DATCODE_LEN_32|DATMODE_8DR);
// Configure the frame
RadioSetFrameConfig(SOP_EN|LEN_EN|4);
// Load the Preamble with 0x01
// This design defaults to using 16-chip Preamble. The 16 chip Preamble sequence
// may be repeated multiple times (see Register PREAMBLE_ADR). The longer
// Preamble allows the receiver amble time to "lock" to the coming signal. Our
// testing shows that 16-chip sequence is sufficient.
RadioSetPreambleCount(0x01);
// Set LVI Threshold to 1.8V
RadioWrite(PWR_CTRL_ADR, PWR_CTRL_SETTING);
// Retrieve the bridge MID
SlaveProtocolRetrieveBridgeMid();
// Set CRC
RadioSetNonzeroCrcSeed();
connected_state = PROTOCOL_DISCONNECTED;
#ifdef ENCRYPT_TEA
encrypt_key_received = FALSE;
#endif //ENCRYPT_TEA
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolButtonBind
//
//! Description: The device sets the current channel and PN code to the channel
//! and PN code specified in the Bind ID. The device sends out
//! a Bind Request on each channel for a certain time before selecting
//! the next channel. If the device receives a Bind Response from the
//! Bridge, it will store the bridge抯 Manufacturing ID and try to
//! connect to the bridge. The device will also exit the bind mode
//! if the defined time period has elapsed.
//!
//! Inputs:
//! - dev_type - device type
//!
//! Returns:
//! - PROTOCOL_CONNECT_STATE
//!
///////////////////////////////////////////////////////////////////////////////
void SlaveProtocolButtonBind(unsigned char dev_type)
{
unsigned short bind_retry = 0;
unsigned char packet_length;
PROTOCOL_STATUS status = PROTOCOL_FAILED;
NotifyStartBind();
// Enter disconnected state
connected_state = PROTOCOL_DISCONNECTED;
#ifdef ENCRYPT_TEA
encrypt_key_received = FALSE;
#endif //ENCRYPT_TEA
// Initialize tx packet header
tx_packet.first.byte = 0; // clear the packet
tx_packet.bind_request.hdr.type = BIND_REQ;
tx_packet.bind_request.hdr.dev_type = dev_type;
// Set the bind pn code
RadioSetSopPnCode( BIND_PN_CODE );
// seed the channel algorithm with bind parameters 0,0
sys_params.network_id.channel = BIND_BASE_CHANNEL;
// Set Zero CRC
RadioSetCrcSeed(0);
// Set PA setting
RadioSetPa( BUTTON_BIND_PA );
// Force endstate to idle
RadioForceState(END_STATE_IDLE);
// send a bind request and wait for response, if no response change
// the channel and try again
while(bind_retry < BIND_RETRY_COUNT)
{
bind_retry++;
M8C_ClearWDTAndSleep;
RadioSetChannel( sys_params.network_id.channel );
if( RadioSendPacket(BIND_REQ_RETRIES, BIND_REQ_LEN) )
{
// If a ACK is received, it will take 50ms to wait for a packet.
// It roughly equals to 32 cycles (1.56ms per cycle).
bind_retry += 32;
packet_length = RadioReceivePacket();
if( packet_length == BIND_RESP_LEN &&
rx_packet.bind_response.hdr.type == BIND_RESP )
{
// extract Bridge MID from bind response packet
sys_params.bridge_mid.mid_1 = rx_packet.bind_response.mid_1;
sys_params.bridge_mid.mid_2 = rx_packet.bind_response.mid_2;
sys_params.bridge_mid.mid_3 = rx_packet.bind_response.mid_3;
sys_params.bridge_mid.mid_4 = rx_packet.bind_response.mid_4;
sys_params.bridge_mid.signature = SIGNATURE_BYTE;
// exit loop with success
status = PROTOCOL_SUCCESS;
break;
}
}
RadioGetNextChannel();
if((bind_retry & 0x00FF) == 0x0080)
NotifyContinueBind();
}
// Force endstate to sleep
RadioForceState(END_STATE_SLEEP);
// Restore PA setting to default state
RadioSetPa( DATA_MODE_PA );
if( status == PROTOCOL_SUCCESS )
{
StoreSystemParameters();
RadioCalculateNetworkId();
// set CRC
RadioSetNonzeroCrcSeed();
// give the dongle time to ping before trying to reconnect
TimerDelayMsec( BRIDGE_PING_TIME_MS );
SlaveProtocolReconnect(dev_type);
}
else
{
// can't Bind, reset to original bind parameters
SlaveProtocolRetrieveBridgeMid();
// Set CRC
RadioSetNonzeroCrcSeed();
}
NotifyStopBind();
}
#ifdef KISS_BIND
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolKissBind
//
//! Description: Kiss bind
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
static void SlaveProtocolKissBind(unsigned char dev_type)
{
unsigned char status = PROTOCOL_FAILED;
unsigned char packet_length;
unsigned char pncode;
unsigned char channel;
connected_state = PROTOCOL_DISCONNECTED;
#ifdef ENCRYPT_TEA
encrypt_key_received = FALSE;
#endif //ENCRYPT_TEA
// Set BIND PA on the radio
RadioSetPa( KISS_BIND_PA );
// Force endstate to idle
RadioForceState(END_STATE_IDLE);
// Set Zero CRC
RadioSetCrcSeed(0);
for( pncode = 0; pncode < NUM_PN_CODES; pncode++)
{
// build the Kiss Bind Request Packet
tx_packet.first.byte = 0; // clear the packet
tx_packet.bind_request.hdr.type = KISS_BIND_REQ;
tx_packet.bind_request.hdr.dev_type = dev_type;
RadioSetSopPnCode( pncode );
for(channel = 0; channel < NUM_CHANNELS; channel++)
{
M8C_ClearWDTAndSleep;
RadioSetChannel( channel );
if( RadioSendPacket(KISS_BIND_REQ_RETRIES, KISS_BIND_REQ_LEN) )
{
packet_length = RadioReceivePacket();
if((packet_length == BIND_RESP_LEN) &&
(rx_packet.bind_response.hdr.type == KISS_BIND_RESP) &&
(rx_packet.bind_response.hdr.dev_type == dev_type))
{
// In order to use RSSI_QUALIFY, the Master side MUST define PROMISCUOUS_MODE
#if (defined RSSI_QUALIFY && defined PROMISCUOUS_MODE)
if((RadioGetRxRssi() >= KISS_BIND_RSSI_THRESHOLD))
#endif //defined RSSI_QUALIFY && defined PROMISCUOUS_MODE
{
// Copy radio MID from receive packet
sys_params.bridge_mid.mid_1 = rx_packet.bind_response.mid_1;
sys_params.bridge_mid.mid_2 = rx_packet.bind_response.mid_2;
sys_params.bridge_mid.mid_3 = rx_packet.bind_response.mid_3;
sys_params.bridge_mid.mid_4 = rx_packet.bind_response.mid_4;
sys_params.bridge_mid.signature = SIGNATURE_BYTE;
status = PROTOCOL_SUCCESS;
break;
}
}
}
}
if( status == PROTOCOL_SUCCESS )
{
StoreSystemParameters();
RadioCalculateNetworkId();
sys_params.network_id.channel = channel;
break;
}
}
// Force endstate to sleep
RadioForceState(END_STATE_SLEEP);
// Restore default PA
RadioSetPa( DATA_MODE_PA );
// Set CRC
RadioSetNonzeroCrcSeed();
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolUnbind
//
//! Description: Unbind the device from the bridge by writting invalid signature
//! into the flash.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
void SlaveProtocolUnbind(void)
{
// Enter disconnected state
connected_state = PROTOCOL_DISCONNECTED;
sys_params.bridge_mid.signature = 0;
StoreSystemParameters();
//loop here indefinately.
while(1)
{
//Clear Watchdog and Sleep
M8C_ClearWDTAndSleep;
// Once this state is entered, it does not exit until the
// batteries are changed.
M8C_Sleep;
}
}
#endif // KISS_BIND
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolGetTxPkt
//
//! Description: returns the pointer to the application packet.
//!
//! Inputs: Void
//!
//! Returns: Void
//!
///////////////////////////////////////////////////////////////////////////////
void *SlaveProtocolGetTxPkt(void)
{
return tx_packet.data.payload;
}
///////////////////////////////////////////////////////////////////////////////
//
// Function: SlaveProtocolSendPacket
//
//! Description: Sends packet to the bridge if the device is connected to this
//! brige. Otherwise, connects to this brige first.
//!
//! Inputs:
//! - dev_type - device type
//! - data_length - data length
//!
//! Returns:
//! - PROTOCOL_STATUS
//!
///////////////////////////////////////////////////////////////////////////////
PROTOCOL_STATUS SlaveProtocolSendPacket( unsigned char dev_type
,unsigned char data_dev_type
,unsigned char data_length
#ifdef BACK_CHANNEL_SUPPORT
,unsigned char back_channel
#endif //BACK_CHANNEL_SUPPORT
)
{
if( connected_state == PROTOCOL_DISCONNECTED )
{
SlaveProtocolReconnect(dev_type);
return PROTOCOL_TX_TIMEOUT;
}
tx_packet.first.byte = 0; // clear the header byte
if( data_length < PAYLOAD_LENGTH + 1 )
{
// setup for a Data Packet and bump the data toggle
tx_packet.data.hdr.type = DATA_PACKET;
tx_packet.data.hdr.data_dev_type = data_dev_type_swap_table[data_dev_type];
tx_packet.data.hdr.dt_data = tx_data_toggle;
#ifdef BACK_CHANNEL_SUPPORT
tx_packet.data.hdr.back_ch_req = back_channel;
#else //BACK_CHANNEL_SUPPORT
tx_packet.data.hdr.back_ch_req = 0;
#endif //BACK_CHANNEL_SUPPORT
data_length += 1; // length = header + data
}
else
{
return( PROTOCOL_FAILED );
}
#ifdef ENCRYPT_AES
EncryptData(data_length);
data_length = 16;
#endif //ENCRYPT_AES
#ifdef BACK_CHANNEL_SUPPORT
// Force endstate to idle
RadioForceState(END_STATE_IDLE);
#endif //BACK_CHANNEL_SUPPORT
if( RadioSendPacket( DATA_PACKET_RETRIES, data_length ) )
{
tx_data_toggle ^= 1;
#ifdef BACK_CHANNEL_SUPPORT
if( back_channel)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -