//-------------------------------------------------------------------------- // // Collection of functions which support the WSUB LS Protocol for // HID and HID like devices // //-------------------------------------------------------------------------- // $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Firmware/Source Code/RDK Mouse/protocol.c $ // $Modtime: 6/16/04 4:38p10/01/04 1:18p $ // $Revision: 910 $ //-------------------------------------------------------------------------- // // Copyright 2003-2004, Cypress Semiconductor Corporation. // // This software is owned by Cypress Semiconductor Corporation (Cypress) // and is protected by and subject to worldwide patent protection (United // States and foreign), United States copyright laws and international // treaty provisions. Cypress hereby grants to licensee a personal, // non-exclusive, non-transferable license to copy, use, modify, create // derivative works of, and compile the Cypress Source Code and derivative // works for the sole purpose of creating custom software in support of // licensee product to be used only in conjunction with a Cypress integrated // circuit as specified in the applicable agreement. Any reproduction, // modification, translation, compilation, or representation of this // software except as specified above is prohibited without the express // written permission of Cypress. // // Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, // WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // Cypress reserves the right to make changes without further notice to the // materials described herein. Cypress does not assume any liability arising // out of the application or use of any product or circuit described herein. // Cypress does not authorize its products for use as critical components in // life-support systems where a malfunction or failure may reasonably be // expected to result in significant injury to the user. The inclusion of // Cypress’ product in a life-support systems application implies that the // manufacturer assumes all risk of such use and in doing so indemnifies // Cypress against all charges. // // Use may be limited by and subject to the applicable Cypress software // license agreement. // //-------------------------------------------------------------------------- #include "ls_config.h" #include "protocol.h" #include "bind.h" #include "radio.h" const UINT8 checkMask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; UINT8 gDataToggle = 0x55; LS_TX_PACKET txPacket; UINT8 protocol_device_type = DEVICE_TYPE; #if (defined TWO_WAY) || (defined RX_MODE) LS_RX_PACKET rxPacket; UINT8 gRxDataToggle = 0x99; #endif /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_init // // Description: Initializes the LS Radio and bind protocol // // Inputs: None // // Returns: Void // /////////////////////////////////////////////////////////////////////////////// Status protocol_init() { #ifndef TWO_WAY txPacket.first.byte = 0x50; // Data packet #endif protocol_get_nvram()device_type = DEVICE_TYPE; // configure the Radio radio_init(); // set up the channel and PN Code protocol_bind_init(); return Sts_OK;// get nvram } /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_get_nvram // // Description: Reads stored system parameters from NVRAM // // Inputs: None // // Returns: Void // /////////////////////////////////////////////////////////////////////////////// void protocol_get_nvram(void) { NVRAM_READ( &sysParams, sizeof(sysParams) ); // check for uninitialized parameters if (sysParams.networkId.signature != SIGNATURE_BYTE) { // set channel and pnCode to a value that will allow the different // devices to coexist and interfere less with each other sysParams.networkId.signature = SIGNATURE_BYTE; sysParams.networkId.channel = DEFAULT_CHAN; sysParams.networkId.pnCode = DEFAULT_PNCODE; sysParams.networkId.seed = DEFAULT_SEED; sysParams.networkId.pin = 0; sysParams.networkId.baseChannel = 0xff0xFF; #ifndef PROTOCOL_1_1 NVRAM_WRITE( &sysParams ); #endif // PROTOCOL_1_1 } #ifdef PROTOCOL_1_1 else { // calculate channel, PN code, etc. from Bridge MID and store values in sysParams // values in sysParams calculate_network_id(); } #endif } // configure the Radio radio_init(); // set up the channel and PN Code protocol_bind_init(); return Sts_OK; } /////////////////////////////////////////////////////////////////////////////// // // Function: calculate_network_id // /////////////////////////////////////////////////////////////////////////////// #ifdef PROTOCOL_1_1 void calculate_network_id(void) { UINT8 baseChannel, pnCode, seed; // calculate PN Code pnCode = sysParams.bridgeMid.mid1 ^ sysParams.bridgeMid.mid2 ^ sysParams.bridgeMid.mid3; sysParams.bridgeMid.mid3; while (pnCode >= NUM_PNCODES) { pnCode -= NUM_PNCODES; } // calculate base channel baseChannel = sysParams.bridgeMid.mid1; while (baseChannel >= NUM_CHANNELS) { baseChannel -= NUM_CHANNELS; } seed = sysParams.bridgeMid.mid1 + sysParams.bridgeMid.mid2 + sysParams.bridgeMid.mid3 + sysParams.bridgeMid.mid3 + sysParams.bridgeMid.mid4; sysParams.networkId.baseChannel = baseChannel; sysParams.networkId.channel = baseChannel; sysParams.networkId.pnCode = pnCode; sysParams.networkId.seed = seed; sysParams.networkId.pin = 0; } #endif // PROTOCOL_1_1 /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_get_tx_pkt // // Description: Returns a pointer to a radio_transmit buffer pool controlled by the // controlled by the protocol, currently in the PSoC only 1 buffer is used due to // 1 buffer is used due to memory limitations // // Inputs: None // // Returns: void * // /////////////////////////////////////////////////////////////////////////////// void * protocol_get_tx_pkt(void) { return &txPacket.data.appPacket; } #ifdef RETURN_TX_PACKET /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_rtrn_tx_pkt // // Description: Fress Frees a pointer to a radio_transmit buffer pool controlled by the // by the protocol, currently in the PSoC only 1 buffer is used due to // used due to memory limitations // // Inputs: void * // // Returns: Status // /////////////////////////////////////////////////////////////////////////////// Status protocol_rtrn_tx_pkt(void * pPacket) { return Sts_OK; } #endif RETURN_TX_PACKET #ifdef TWO_WAY #ifdef USE_RX_PACKET /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_get_rx_pkt // // Description: Returns a pointer to a protocol_receive buffer pool controlled by the // controlled by the protocol, currently in the PSoC only 1 buffer is used due to // 1 buffer is used due to memory limitations // // Inputs: None // // Returns: void * // /////////////////////////////////////////////////////////////////////////////// void * protocol_get_rx_pkt(void) { return &rxPacket.data.appPacket; } /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_rtrn_rx_pkt // // Description: Fress a pointer to a protocol_receive buffer pool controlled by the // by the protocol, currently in the PSoC only 1 buffer is used due to // due to memory limitations // // Inputs: void * // // Returns: Status // /////////////////////////////////////////////////////////////////////////////// Status protocol_rtrn_rx_pkt(void * pPacket) { return Sts_OK; } #endif // USE_RX_PACKET #endif // TWO_WAY #ifndef TWO_WAY /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_send_packet // // Description: Transmit a packet out the LS Radio, using the One Way WUSB // LS Protocol // // Inputs: None // // Returns: void * // /////////////////////////////////////////////////////////////////////////////// UINT8 protocol_send_packet(UINT8 dataLength) // One Way { UINT8 i, length, sequence; UINT8 length; #ifdef SLEEP_ENABLED radio_wakeupRADIO_WAKEUP(); #endif // send a Null Packet to poll for back channel data or as a keep alive packet... // keep alive packet... if(dataLength == 0) { // NULL packet from 2-way protocol, used as keep-alive txPacket.first.byte = 0x70; length = 1; } // setup for a Data Packet and bump the data toggle else if (dataLength <= APP_TX_PACKET_SIZE + 1) { txPacket.first.byte = 0; txPacket.data.hdr.type = DATA_PACKET; txPacket.data.hdr.fill = 0; txPacket.data.hdr.dt_data = gDataToggle++; txPacket.data.hdr.devId = (DEVICE_TYPEprotocol_device_type & 0x01); txPacket.data.hdr.parity = protocol_gen_parity(txPacket.first.byte); // calculate check sum, etc... txPacket.data.appPacket[dataLength] = protocol_calc_ck_sum((UINT8 *)&txPacket, dataLength+1, sysParams.networkId.seed); length = dataLength + 2; } radio_transmit_onset_channel(sysParams.networkId.channel); radio_transmit_on(); radio_transmit(length, (UINT8 *)&txPacket); radio_offSPI_RADIO_OFF(); // perform retransmit, if TX_NUM_TRANS = 1 this // loop doesn't execute for(i = 1; i < TX_NUM_TRANS - 1 >= i; i++) { // wait between packet retransmissions TIMER_DELAY_MSEC(GAP_DELAY); radio_transmit_onset_channel(sysParams.networkId.channel); radio_transmit_on(); radio_transmit(length, (UINT8 *)&txPacket); radio_offSPI_RADIO_OFF(); } RADIO_SLEEP(); #ifdef SLEEP_ENABLED radio_sleep(); #endif return DATA_SENT; } #endif // ifndef TWO_WAY #ifdef TWO_WAY /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_send_packet // // Description: Transmit a packet out the LS Radio, using the Two Way WUSB // LS Protocol // // Inputs: Length of packet, 0 = send NULL packet // // Returns: void * // /////////////////////////////////////////////////////////////////////////////// UINT8 protocol_send_packet( UINT8 dataLength ) // Two Way { UINT8 txTimeout; UINT8 ackTimeout; UINT8 pktReceived; UINT8 length; UINT8 rLength; #ifdef SLEEP_ENABLED radio_wakeupRADIO_WAKEUP(); #endif // setup loop control variables txTimeout = 0; pktReceived = NO_PACKET; if (gBindMode != CONNECTED_STATE) { protocol_reconnect(); return TX_TIMEOUT_ERR; } txPacket.first.byte = 0; // clear the header byte // send a Null Packet to poll for back channel data or as a keep alive packet... // alive packet... if(dataLength == 0) { txPacket.null.hdr.type = NULL_PACKET; #ifdef NULL_PACKET_DATA txPacket.null.hdr.fill = (txPacket.data.appPacket[0] & 0x03); #else txPacket.null.hdr.fill = 0; #endif #ifdef COMBO_DEVICE txPacket.null.hdr.devId = (DEVICE_TYPE & 0x01); txPacket.null.hdr.devId = (protocol_device_type & 0x01); #else txPacket.null.hdr.devId = 0; #endif // COMBO_DEVICE txPacket.null.hdr.parity = protocol_gen_parity(txPacket.first.byte); length = NULL_LEN; #ifdef CHECKSUM_ALL_PACKETS txPacket.data.appPacket[0] = protocol_calc_ck_sum((UINT8 *)&txPacket, 1, txPacket.data.appPacket[0] = protocol_calc_ck_sum((UINT8 *)&txPacket, 1, sysParams.networkId.seed ); #endif } // setup for a Data Packet and bump the data toggle else if (dataLength <= APP_TX_PACKET_SIZE + 1) { txPacket.data.hdr.type = DATA_PACKET; #ifdef COMBO_DEVICE txPacket.data.hdr.devId = (DEVICE_TYPEprotocol_device_type & 0x01); #else txPacket.data.hdr.devId = 0; #endif // COMBO_DEVICE txPacket.data.hdr.dt_data = gDataToggle; //txPacket.data.hdr.fill = 0; txPacket.data.hdr.parity = protocol_gen_parity(txPacket.first.byte); // calculate check sum txPacket.data.appPacket[dataLength] = protocol_calc_ck_sum( (UINT8 *)&txPacket, dataLength+1, sysParams.networkId.seed ); length = dataLength + 2; // length = header + data + checksum } else { return( INVALID_DATA ); } // setup radio_transmit mode, give more time to settle radio_transmit_onset_channel(sysParams.networkId.channel); // initialize loop control pktReceived = NO_PACKET; txTimeout = 0; //loop until ACK radio_received or retries exhausted while((pktReceived == NO_PACKET) && (txTimeout++ < TX_TIMEOUT)) { // Power Savings Initiative for(txTimeout = 0; (pktReceived == NO_PACKET) && (txTimeout < TX_TIMEOUT); if (txTimeout != 1) txTimeout++) { radio_switch_txtransmit_on(); } // send the packet radio_transmit(length, (UINT8 *)&txPacket); #ifdef SLEEP_ENABLED // Power Savings Initiative // do not immediately switch into RX mode... TIMER_DELAY_50_USEC(); TIMER_DELAY_50_USEC(); TIMER_DELAY_50_USEC(); TIMER_DELAY_10_USEC(); TIMER_DELAY_10_USEC(); #endif // setup receive mode radio_switch_rxreceive_on(); ackTimeout = 0; // reset the ack timeout // get an ACK pktReceived = protocol_receive(&rLength); // verify packet is the expected type // reset the ack timeout while(for(ackTimeout = 0; (pktReceived != ACK_PACKET) && (pktReceived != DATA_ACK_PACKET) && (+ (ACK_TIMEOUT*5-1 >= ackTimeout); ++ackTimeout < ACK_TIMEOUT) ) { if( pktReceived != NO_PACKET ) { pktReceived = NO_PACKET; // stay in ACK loop } TIMER_DELAY_5010_USEC(); pktReceived = protocol_receive(&rLength); } RADIO_ISR_DISABLE(); if (pktReceived == DATA_ACK_PACKET ) { #ifdef DATA_ACK_FILTER_VALUE if( rxPacket.ackData.hdr.flag == GOOD_ACK && rxPacket.data.appPacket[0] == DATA_ACK_FILTER_VALUE ) #else if( rxPacket.ackData.hdr.flag == GOOD_ACK ) #endif { #ifdef BACK_CHANNEL_DATA radio_switch_txtransmit_on(); protocol_send_ack(); #ifndef SPI_RADIO_DEFAULT_ONOFF(); radio_offRADIO_SLEEP(); #endif #ifdef SLEEP_ENABLED radio_sleep(); #endif if (txPacket.null.hdr.type != 0x07) { // flip the data toggle bit to signal an acknowledged packet // transmission gDataToggle++; } return( ACK_DATA ); #endif } else // NAK { // reset the control variables for retransmission pktReceived = NO_PACKET; } } else if(pktReceived == ACK_PACKET) { #ifdef COMBO_DEVICE if( (rxPacket.ack.hdr.flag == GOOD_ACK) && (rLength == ACK_LEN) && ((rxPacket.ack.hdr.devId & 0x01) == (DEVICE_TYPE & 0x01)) && (protocol_device_type & 0x01)) && (((txPacket.null.hdr.type != 0x07) && (rxPacket.ack.hdr.dt_ack == (gDataToggle & 0x01))) || (txPacket.null.hdr.type == 0x07)) ) #else if( (rxPacket.ack.hdr.flag == GOOD_ACK ) && (rLength == ACK_LEN) && (((txPacket.null.hdr.type != 0x07) && (rxPacket.ack.hdr.dt_ack == (gDataToggle & 0x01))) || (txPacket.null.hdr.type == 0x07)) ) #endif // COMBO_DEVICE { #ifndef SPI_RADIO_DEFAULT_ONOFF(); radio_off(); //turns off the synthesizer #endif #ifdef RADIO_SLEEP_ENABLED(); radio_sleep(); #endif if (txPacket.null.hdr.type != 0x07) { // flip the data toggle bit to signal an // acknowledged packet transmission gDataToggle++; } return( DATA_SENT ); } else // NAK { // reset the control variables for retransmission pktReceived = NO_PACKET; } } else if(ACK_TIMEOUT - 1 < ackTimeout >= ACK_TIMEOUT) { #ifdef ACK_BACKOFF_DELAY ACK_BACKOFF_DELAY(); #endif } } // while((pktReceived == NO_PACKET) && (txTimeout++ < TX_TIMEOUT_CNT)) } // for() if(TX_TIMEOUT <= txTimeout > TX_TIMEOUT) { protocol_reconnect(); #ifndef SPI_RADIO_DEFAULT_ONOFF(); radio_offRADIO_SLEEP(); #endif // RADIO_DEFAULT_ON #ifdef SLEEP_ENABLED radio_sleep(); #endif // SLEEP_ENABLED return( TX_TIMEOUT_ERR ); } #ifndef RADIO_DEFAULT_ON radio_off(); //turns off the synthesizer #endif SPI_RADIO_OFF(); #ifdef SLEEP_ENABLED radio_sleepRADIO_SLEEP(); #endif return( INVALID_DATA ); } #endif // TWO_WAY /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_calc_ck_sum // // Description: Calculate Packet Sum Check // // Inputs: Packet pointer // Length of packet // Check sum Seed // // Returns: Checksum // /////////////////////////////////////////////////////////////////////////////// UINT8 protocol_calc_ck_sum(UINT8 *data, UINT8 len, UINT8 seed) UINT8 seed) { UINT8 sum; for(sum = seed; len > 0; len--, data++) { sum ^= *data; } return(sum); } /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_gen_parity // // Description: calculate odd parity for a byte // // Inputs: byte // // Returns: 1 or 0, based on input byte // /////////////////////////////////////////////////////////////////////////////// UINT8 protocol_gen_parity(UINT8 data) { UINT8 count = 0; for (; data; ) { data>>=1; // shift out the parity bit... // check for bits that are set if (data & 0x01) { ++count; } } // check for an odd number if( count & 0x01 ) return 0; else return 1; } #ifdef TWO_WAY /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_send_ack // // Description: send an ACK // // Inputs: none // // Returns: N/A // /////////////////////////////////////////////////////////////////////////////// void protocol_send_ack(void) { // create ACK packet txPacket.first.byte = 0; txPacket.ack.hdr.type = ACK_PACKET; txPacket.ack.hdr.flag = GOOD_ACK; #ifdef COMBO_DEVICE txPacket.ack.hdr.devId = (DEVICE_TYPEprotocol_device_type & 0x01); #endif // the RX data toggle field is being mirrored back in the ACK txPacket.ack.hdr.dt_ack = rxPacket.data.hdr.dt_data; txPacket.ack.hdr.parity = protocol_gen_parity( (UINT8) txPacket.first.byte ); #ifdef CHECKSUM_ALL_PACKETS txPacket.data.appPacket[0] = txPacket.data.appPacket[0] = protocol_calc_ck_sum((UINT8 *)&txPacket, 1, sysParams.networkId.seed ); #endif // send the packet radio_transmit( ACK_LEN, (UINT8 *)&txPacket ); } /////////////////////////////////////////////////////////////////////////////// // // Function: protocol_receive // // Description: get packet data if available, and copy it to rxPacket // // Inputs: void // // Returns: 0-f = Type of Packet radio_received // 0xff0xFF = nothing radio_received // /////////////////////////////////////////////////////////////////////////////// UINT8 protocol_receive(UINT8 *pLength) { UINT8 i, j; UINT8 packetType; UINT8 numErasures; // track # of erasures per column UINT8 goodPacket; UINT8 checkSum; UINT8 badBit = 0; UINT8 badRow; UINT8 badBitCnt = 0; if(!gChannelEof) { return( NO_PACKET ); } // initialize control variables goodPacket = TRUE; // save off the length of the packet ?? TODO use a global like ??? *pLength = gChannelBytes; if (*pLength == 0) { gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } // check for perfect protocol bytes, requirement for bit correction if( (gChannelValid[0] != 0xff) || (gChannelValid[gChannelBytes-1] != 0xff) ) { // packet protocol bytes invalid gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } // gChannelValid[0] != 0xff // blunder check the parity bit if((protocol_gen_parity(rxPacket.first.byte) != (rxPacket.first.byte & 0x01)) || (gChannelValid[0] != 0xff)) { // bad parity in packet gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } // get the packet type, it is the upper nibble in the first byte packetType = rxPacket.ack.hdr.type; // check for perfect protocol bytes, requirement for bit correction AND // blunder check the packet typeparity bit AND if(packetType > MAX_NUM_TYPES) { // bad format in packet gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } // blunder check the packet type AND // blunder check the data types by length if ( (gChannelBytes == 0) || (gChannelValid[0] != 0xFF) || (gChannelValid[gChannelBytes-1] != 0xFF) || ( (protocol_gen_parity(rxPacket.first.byte) != (rxPacket.first.byte & 0x01)) || (gChannelValid[0] != 0xFF) ) || (packetType >= MAX_NUM_TYPES + 1) || if ( ((packetType == DATA_ACK_PACKET) || (packetType == DATA_PACKET)) && (*pLength < 3) ) { gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } if( packetType == ACK_PACKET && *pLength != ACK_LEN ) (2 >= gChannelBytes) ) || (packetType == ACK_PACKET && gChannelBytes != ACK_LEN) ) { // packet protocol bytes invalid OR // bad parity in packet OR // bad format in packet gChannelBytes = 0; gChannelEof = 0; return( NO_PACKET ); } // only check/fix packets with checksums if((packetType == DATA_PACKET || packetType == BIND_RESPONSE || packetType == DATA_ACK_PACKET) && goodPacket) { // quick test for bad bits badBit = 0xff0xFF; for(i = 1; i < *pLengthgChannelBytes; i++) { // AND the colums togethers to find // bad bits badBit &= gChannelValid[i]; } // check for any bad bits if(badBit != 0xff0xFF) { //////////////////////////////////////////////////////////////////// // // The sumCheck can only be used to fix packets with a single error // in a column. The sumCheck is always the last byte in the packet. // // 0 1 2 3 4 5 6 7 // +---------------+ // ChannelPacket[0] |x|x|x|x|x|x|x|x| First Byte // +---------------+ // +---------------+ // ChannelValid [0] |1|1|0|0|0|1|1|1| 0=Bad bit // +---------------+ // // +---------------+ // ChannelPacket[1] |x|x|x|x|x|x|x|x| Data // +---------------+ // +---------------+ // ChannelValid [1] |1|1|1|1|1|1|1|1| 0=Bad bit // +---------------+ // // +---------------+ // ChannelPacket[2] |x|x|x|x|x|x|x|x| CheckSum // +---------------+ // +---------------+ // ChannelValid [2] |1|1|1|1|1|1|1|1| 0=Bad bit // +---------------+ // /////////////////////////////////////////////////////////////////////// // process the data in the Packet by column for( for(i = 0; i < 87 >= i; i++) { numErasures = 0; // test for a column with a bad bit if(!(badBit & checkMask[i])) if(!(badBit & (1 << i))) { if( packetType == BIND_RESPONSE ) { checkSum = BIND_SEED; } else { checkSum = sysParams.networkId.seed; } // Now that we have the bad column, figure out which row // has the bad bit for (j = 0; j < *pLength; j++) for (j = 0; j < gChannelBytes; j++) { // This is only true if bit j of gChannelValid is 0, // This is only true if bit j of gChannelValid is 0, // an invalid bit if ((gChannelValid[j] & checkMask[i]) == 0) if ((gChannelValid[j] & (1 << i)) == 0) { badRow = j; // Using numErasures to tell when 2 bits in the // same column are bad, but it could be used for // stats as well... numErasures++; badBitCnt++; if( (numErasures > 1) || (badBitCnt > 3) ) if( (numErasures > 1) || (3 < badBitCnt) ) { goodPacket = FALSE; // discard the packet because // we cannot recover from two // erased bits in the same column or // there are too many bad bits in // general packetType = NO_PACKET; break; } } else // good data, calculate checksum { checkSum ^= *((UINT8 *) (&rxPacket.first.byte) + j); } } // for (j = 0; j < *pLength; j++) if(goodPacket == FALSE) } // for () if(packetType == NO_PACKET) { break; } if (checkSum & checkMask[i](1 << i)) { *((UINT8 *) (&rxPacket.first.byte) + badRow) |= checkMask[i](1 << i); } else { *((UINT8 *) (&rxPacket.first.byte) + badRow) &= ~checkMask[i]; ~(1 << i); } } // if (gChannelValid[i] != 0xff) } // for(i = 0; i < length; i++) } // if badBit != 0xff() } // for() } // if badBit != 0xFF // compare the checksum.... if( packetType == BIND_RESPONSE ) { checkSum = BIND_SEED; } else { checkSum = sysParams.networkId.seed; } // Comparing the received checksum with the calculated checksum if (*((UINT8 *) (&rxPacket.first.byte) + ((*pLength)gChannelBytes)-1)) != protocol_calc_ck_sum((UINT8*)&rxPacket.first.byte, (*pLength)-1, checkSum )) protocol_calc_ck_sum((UINT8*)&rxPacket.first.byte, (gChannelBytes)-1, checkSum )) { goodPacket = FALSE;// bad packet packetType = NO_PACKET; } } // if packetType == packet with sumcheck // Check for bad packet if (goodPacket == FALSE) { packetType = NO_PACKET; } // return parameter *pLength = gChannelBytes; gChannelBytes = 0; gChannelEof = 0; return (packetType); } #endif // TWO_WAY